// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tests/DawnTest.h"

#include "common/Assert.h"
#include "common/Constants.h"
#include "common/Math.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"

// Create a 2D texture for sampling in the tests.
dawn::Texture Create2DTexture(dawn::Device device,
                              dawn::TextureFormat format,
                              uint32_t width,
                              uint32_t height,
                              uint32_t arrayLayerCount = 1,
                              uint32_t mipLevelCount = 1,
                              dawn::TextureUsageBit usage = dawn::TextureUsageBit::Sampled |
                                                            dawn::TextureUsageBit::CopyDst) {
    dawn::TextureDescriptor descriptor;
    descriptor.dimension = dawn::TextureDimension::e2D;
    descriptor.format = format;
    descriptor.size.width = width;
    descriptor.size.height = height;
    descriptor.size.depth = 1;
    descriptor.arrayLayerCount = arrayLayerCount;
    descriptor.sampleCount = 1;
    descriptor.mipLevelCount = mipLevelCount;
    descriptor.usage = usage;
    return device.CreateTexture(&descriptor);
}

// The helper struct to configure the copies between buffers and textures.
struct CopyConfig {
    dawn::TextureFormat format;
    uint32_t textureWidthLevel0;
    uint32_t textureHeightLevel0;
    dawn::Extent3D copyExtent3D;
    dawn::Origin3D copyOrigin3D = {0, 0, 0};
    uint32_t arrayLayerCount = 1;
    uint32_t mipmapLevelCount = 1;
    uint32_t baseMipmapLevel = 0;
    uint32_t baseArrayLayer = 0;
    uint32_t bufferOffset = 0;
    uint32_t rowPitchAlignment = kTextureRowPitchAlignment;
};

class CompressedTextureBCFormatTest : public DawnTest {
  protected:
    void SetUp() override {
        DawnTest::SetUp();
        mBindGroupLayout = utils::MakeBindGroupLayout(
            device, {{0, dawn::ShaderStageBit::Fragment, dawn::BindingType::Sampler},
                     {1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture}});
    }

    // Copy the compressed texture data into the destination texture as is specified in copyConfig.
    void CopyDataIntoCompressedTexture(dawn::Texture bcCompressedTexture,
                                       const CopyConfig& copyConfig) {
        // Compute the upload buffer size with rowPitchAlignment and the copy region.
        uint32_t actualWidthAtLevel = copyConfig.textureWidthLevel0 >> copyConfig.baseMipmapLevel;
        uint32_t actualHeightAtLevel = copyConfig.textureHeightLevel0 >> copyConfig.baseMipmapLevel;
        uint32_t copyWidthInBlockAtLevel =
            (actualWidthAtLevel + kBCBlockWidthInTexels - 1) / kBCBlockWidthInTexels;
        uint32_t copyHeightInBlockAtLevel =
            (actualHeightAtLevel + kBCBlockHeightInTexels - 1) / kBCBlockHeightInTexels;
        uint32_t bufferRowPitchInBytes = 0;
        if (copyConfig.rowPitchAlignment != 0) {
            bufferRowPitchInBytes = copyConfig.rowPitchAlignment;
        } else {
            bufferRowPitchInBytes =
                copyWidthInBlockAtLevel * CompressedFormatBlockSizeInBytes(copyConfig.format);
        }
        uint32_t uploadBufferSize =
            copyConfig.bufferOffset + bufferRowPitchInBytes * copyHeightInBlockAtLevel;

        // Fill uploadData with the pre-prepared one-block compressed texture data.
        std::vector<uint8_t> uploadData(uploadBufferSize, 0);
        std::vector<uint8_t> oneBlockCompressedTextureData =
            GetOneBlockBCFormatTextureData(copyConfig.format);
        for (uint32_t h = 0; h < copyHeightInBlockAtLevel; ++h) {
            for (uint32_t w = 0; w < copyWidthInBlockAtLevel; ++w) {
                uint32_t uploadBufferOffset = copyConfig.bufferOffset + bufferRowPitchInBytes * h +
                                              oneBlockCompressedTextureData.size() * w;
                std::memcpy(&uploadData[uploadBufferOffset], oneBlockCompressedTextureData.data(),
                            oneBlockCompressedTextureData.size() * sizeof(uint8_t));
            }
        }

        // Copy texture data from a staging buffer to the destination texture.
        dawn::Buffer stagingBuffer = utils::CreateBufferFromData(
            device, uploadData.data(), uploadBufferSize, dawn::BufferUsageBit::CopySrc);
        dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
            stagingBuffer, copyConfig.bufferOffset, copyConfig.rowPitchAlignment, 0);
        dawn::TextureCopyView textureCopyView =
            utils::CreateTextureCopyView(bcCompressedTexture, copyConfig.baseMipmapLevel,
                                         copyConfig.baseArrayLayer, copyConfig.copyOrigin3D);

        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copyConfig.copyExtent3D);
        dawn::CommandBuffer copy = encoder.Finish();
        queue.Submit(1, &copy);
    }

    // Create the bind group that includes a BC texture and a sampler.
    dawn::BindGroup CreateBindGroupForTest(dawn::Texture bcCompressedTexture,
                                           dawn::TextureFormat bcFormat,
                                           uint32_t baseArrayLayer = 0,
                                           uint32_t baseMipLevel = 0) {
        dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
        samplerDesc.minFilter = dawn::FilterMode::Nearest;
        samplerDesc.magFilter = dawn::FilterMode::Nearest;
        dawn::Sampler sampler = device.CreateSampler(&samplerDesc);

        dawn::TextureViewDescriptor textureViewDescriptor;
        textureViewDescriptor.format = bcFormat;
        textureViewDescriptor.dimension = dawn::TextureViewDimension::e2D;
        textureViewDescriptor.baseMipLevel = baseMipLevel;
        textureViewDescriptor.baseArrayLayer = baseArrayLayer;
        textureViewDescriptor.arrayLayerCount = 1;
        textureViewDescriptor.mipLevelCount = 1;
        dawn::TextureView bcTextureView = bcCompressedTexture.CreateView(&textureViewDescriptor);

        return utils::MakeBindGroup(device, mBindGroupLayout, {{0, sampler}, {1, bcTextureView}});
    }

    // Create a render pipeline for sampling from a BC texture and rendering into the render target.
    dawn::RenderPipeline CreateRenderPipelineForTest() {
        dawn::PipelineLayout pipelineLayout =
            utils::MakeBasicPipelineLayout(device, &mBindGroupLayout);

        utils::ComboRenderPipelineDescriptor renderPipelineDescriptor(device);
        dawn::ShaderModule vsModule =
            utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"(
            #version 450
            layout(location=0) out vec2 texCoord;
            void main() {
                const vec2 pos[3] = vec2[3](
                    vec2(-3.0f, -1.0f),
                    vec2( 3.0f, -1.0f),
                    vec2( 0.0f,  2.0f)
                );
                gl_Position = vec4(pos[gl_VertexIndex], 0.0f, 1.0f);
                texCoord = gl_Position.xy / 2.0f + vec2(0.5f);
            })");
        dawn::ShaderModule fsModule =
            utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"(
            #version 450
            layout(set = 0, binding = 0) uniform sampler sampler0;
            layout(set = 0, binding = 1) uniform texture2D texture0;
            layout(location = 0) in vec2 texCoord;
            layout(location = 0) out vec4 fragColor;

            void main() {
                fragColor = texture(sampler2D(texture0, sampler0), texCoord);
            })");
        renderPipelineDescriptor.cVertexStage.module = vsModule;
        renderPipelineDescriptor.cFragmentStage.module = fsModule;
        renderPipelineDescriptor.layout = pipelineLayout;
        renderPipelineDescriptor.cColorStates[0]->format =
            utils::BasicRenderPass::kDefaultColorFormat;
        return device.CreateRenderPipeline(&renderPipelineDescriptor);
    }

    // Run the given render pipeline and bind group and verify the pixels in the render target.
    void VerifyCompressedTexturePixelValues(dawn::RenderPipeline renderPipeline,
                                            dawn::BindGroup bindGroup,
                                            const dawn::Extent3D& renderTargetSize,
                                            const dawn::Origin3D& expectedOrigin,
                                            const dawn::Extent3D& expectedExtent,
                                            const std::vector<RGBA8>& expected) {
        ASSERT(expected.size() == renderTargetSize.width * renderTargetSize.height);
        utils::BasicRenderPass renderPass =
            utils::CreateBasicRenderPass(device, renderTargetSize.width, renderTargetSize.height);

        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
        {
            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
            pass.SetPipeline(renderPipeline);
            pass.SetBindGroup(0, bindGroup, 0, nullptr);
            pass.Draw(6, 1, 0, 0);
            pass.EndPass();
        }

        dawn::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);

        EXPECT_TEXTURE_RGBA8_EQ(expected.data(), renderPass.color, expectedOrigin.x,
                                expectedOrigin.y, expectedExtent.width, expectedExtent.height, 0,
                                0);
    }

    // Run the tests that copies pre-prepared BC format data into a BC texture and verifies if we
    // can render correctly with the pixel values sampled from the BC texture.
    void TestCopyRegionIntoBCFormatTextures(const CopyConfig& config) {
        dawn::Texture bcTexture = Create2DTexture(device, config.format, config.textureWidthLevel0,
                                                  config.textureHeightLevel0,
                                                  config.arrayLayerCount, config.mipmapLevelCount);
        CopyDataIntoCompressedTexture(bcTexture, config);

        dawn::BindGroup bindGroup = CreateBindGroupForTest(
            bcTexture, config.format, config.baseArrayLayer, config.baseMipmapLevel);
        dawn::RenderPipeline renderPipeline = CreateRenderPipelineForTest();

        dawn::Extent3D virtualSizeAtLevel = GetVirtualSizeAtLevel(config);

        // The copy region may exceed the subresource size because of the required paddings for BC
        // blocks, so we should limit the size of the expectedData to make it match the real size
        // of the render target.
        dawn::Extent3D noPaddingExtent3D = config.copyExtent3D;
        if (config.copyOrigin3D.x + config.copyExtent3D.width > virtualSizeAtLevel.width) {
            noPaddingExtent3D.width = virtualSizeAtLevel.width - config.copyOrigin3D.x;
        }
        if (config.copyOrigin3D.y + config.copyExtent3D.height > virtualSizeAtLevel.height) {
            noPaddingExtent3D.height = virtualSizeAtLevel.height - config.copyOrigin3D.y;
        }

        std::vector<RGBA8> expectedData = GetExpectedData(config.format, virtualSizeAtLevel);
        VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, virtualSizeAtLevel,
                                           config.copyOrigin3D, noPaddingExtent3D, expectedData);
    }

    // Return the BC block size in bytes.
    // TODO(jiawei.shao@intel.com): support all BC formats.
    static uint32_t CompressedFormatBlockSizeInBytes(dawn::TextureFormat format) {
        switch (format) {
            case dawn::TextureFormat::BC5RGSnorm:
            case dawn::TextureFormat::BC5RGUnorm:
                return 16;
            default:
                UNREACHABLE();
                return 0;
        }
    }

    // Return the pre-prepared one-block BC texture data.
    // TODO(jiawei.shao@intel.com): prepare texture data for all BC formats.
    static std::vector<uint8_t> GetOneBlockBCFormatTextureData(dawn::TextureFormat bcFormat) {
        switch (bcFormat) {
            // The expected data represents 4x4 pixel images with the left side red and the right
            // side green and was encoded with DirectXTex from Microsoft.
            case dawn::TextureFormat::BC5RGSnorm:
                return {0x7f, 0x81, 0x40, 0x2,  0x24, 0x40, 0x2,  0x24,
                        0x7f, 0x81, 0x9,  0x90, 0x0,  0x9,  0x90, 0x0};
            case dawn::TextureFormat::BC5RGUnorm:
                return {0xff, 0x0, 0x40, 0x2,  0x24, 0x40, 0x2,  0x24,
                        0xff, 0x0, 0x9,  0x90, 0x0,  0x9,  0x90, 0x0};
            default:
                UNREACHABLE();
                return {};
        }
    }

    // Return the texture data that is decoded from the result of GetOneBlockBCFormatTextureData in
    // RGBA8 formats.
    // TODO(jiawei.shao@intel.com): prepare texture data for all BC formats.
    static std::vector<RGBA8> GetExpectedData(dawn::TextureFormat bcFormat,
                                              const dawn::Extent3D& testRegion) {
        switch (bcFormat) {
            case dawn::TextureFormat::BC5RGSnorm:
            case dawn::TextureFormat::BC5RGUnorm:
                return FillExpectedDataWithPureRedAndPureGreen(testRegion);
            default:
                UNREACHABLE();
                return {};
        }
    }

    // Get one kind of expected data that is filled with pure green and pure red.
    static std::vector<RGBA8> FillExpectedDataWithPureRedAndPureGreen(
        const dawn::Extent3D& testRegion) {
        ASSERT(testRegion.depth == 1);

        constexpr RGBA8 kRed(255, 0, 0, 255);
        constexpr RGBA8 kGreen(0, 255, 0, 255);

        std::vector<RGBA8> expectedData(testRegion.width * testRegion.height, kRed);
        for (uint32_t y = 0; y < testRegion.height; ++y) {
            for (uint32_t x = 0; x < testRegion.width; ++x) {
                if (x % kBCBlockWidthInTexels >= kBCBlockWidthInTexels / 2) {
                    expectedData[testRegion.width * y + x] = kGreen;
                }
            }
        }
        return expectedData;
    }

    static dawn::Extent3D GetVirtualSizeAtLevel(const CopyConfig& config) {
        return {config.textureWidthLevel0 >> config.baseMipmapLevel,
                config.textureHeightLevel0 >> config.baseMipmapLevel, 1};
    }

    static dawn::Extent3D GetPhysicalSizeAtLevel(const CopyConfig& config) {
        dawn::Extent3D sizeAtLevel = GetVirtualSizeAtLevel(config);
        sizeAtLevel.width = (sizeAtLevel.width + kBCBlockWidthInTexels - 1) /
                            kBCBlockWidthInTexels * kBCBlockWidthInTexels;
        sizeAtLevel.height = (sizeAtLevel.height + kBCBlockHeightInTexels - 1) /
                             kBCBlockHeightInTexels * kBCBlockHeightInTexels;
        return sizeAtLevel;
    }

    // TODO(jiawei.shao@intel.com): support all BC formats.
    const std::array<dawn::TextureFormat, 2> kBCFormats = {dawn::TextureFormat::BC5RGSnorm,
                                                           dawn::TextureFormat::BC5RGUnorm};
    // Tthe block width and height in texels are 4 for all BC formats.
    static constexpr uint32_t kBCBlockWidthInTexels = 4;
    static constexpr uint32_t kBCBlockHeightInTexels = 4;

    dawn::BindGroupLayout mBindGroupLayout;
};

// Test copying into the whole BC texture with 2x2 blocks and sampling from it.
TEST_P(CompressedTextureBCFormatTest, Basic) {
    CopyConfig config;
    config.textureWidthLevel0 = 8;
    config.textureHeightLevel0 = 8;
    config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1};

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;
        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test copying into a sub-region of a texture with BC formats works correctly.
TEST_P(CompressedTextureBCFormatTest, CopyIntoSubRegion) {
    CopyConfig config;
    config.textureHeightLevel0 = 8;
    config.textureWidthLevel0 = 8;
    config.rowPitchAlignment = kTextureRowPitchAlignment;

    const dawn::Origin3D kOrigin = {4, 4, 0};
    const dawn::Extent3D kExtent3D = {4, 4, 1};
    config.copyOrigin3D = kOrigin;
    config.copyExtent3D = kExtent3D;

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;
        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test using rowPitch == 0 in the copies with BC formats works correctly.
TEST_P(CompressedTextureBCFormatTest, CopyWithZeroRowPitch) {
    CopyConfig config;
    config.textureHeightLevel0 = 8;

    config.rowPitchAlignment = 0;

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;
        config.textureWidthLevel0 = kTextureRowPitchAlignment /
                                    CompressedFormatBlockSizeInBytes(config.format) *
                                    kBCBlockWidthInTexels;
        config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1};
        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test copying into the non-zero layer of a 2D array texture with BC formats works correctly.
TEST_P(CompressedTextureBCFormatTest, CopyIntoNonZeroArrayLayer) {
    CopyConfig config;
    config.textureHeightLevel0 = 8;
    config.textureWidthLevel0 = 8;
    config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1};
    config.rowPitchAlignment = kTextureRowPitchAlignment;

    constexpr uint32_t kArrayLayerCount = 3;
    config.arrayLayerCount = kArrayLayerCount;
    config.baseArrayLayer = kArrayLayerCount - 1;

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;
        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test copying into a non-zero mipmap level of a texture with BC texture formats.
TEST_P(CompressedTextureBCFormatTest, CopyBufferIntoNonZeroMipmapLevel) {
    CopyConfig config;
    config.textureHeightLevel0 = 60;
    config.textureWidthLevel0 = 60;
    config.rowPitchAlignment = kTextureRowPitchAlignment;

    constexpr uint32_t kMipmapLevelCount = 3;
    config.mipmapLevelCount = kMipmapLevelCount;
    config.baseMipmapLevel = kMipmapLevelCount - 1;

    // The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
    // required in the copies.
    const uint32_t kActualWidthAtLevel = config.textureWidthLevel0 >> config.baseMipmapLevel;
    const uint32_t kActualHeightAtLevel = config.textureHeightLevel0 >> config.baseMipmapLevel;
    ASSERT(kActualWidthAtLevel % kBCBlockWidthInTexels != 0);
    ASSERT(kActualHeightAtLevel % kBCBlockHeightInTexels != 0);

    const uint32_t kCopyWidthAtLevel = (kActualWidthAtLevel + kBCBlockWidthInTexels - 1) /
                                       kBCBlockWidthInTexels * kBCBlockWidthInTexels;
    const uint32_t kCopyHeightAtLevel = (kActualHeightAtLevel + kBCBlockHeightInTexels - 1) /
                                        kBCBlockHeightInTexels * kBCBlockHeightInTexels;

    config.copyExtent3D = {kCopyWidthAtLevel, kCopyHeightAtLevel, 1};

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;
        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test texture-to-texture whole-size copies with BC formats.
TEST_P(CompressedTextureBCFormatTest, CopyWholeTextureSubResourceIntoNonZeroMipmapLevel) {
    // TODO(cwallez@chromium.org): This consistently fails on with the 12th pixel being opaque black
    // instead of opaque red on Win10 FYI Release (NVIDIA GeForce GTX 1660). See
    // https://bugs.chromium.org/p/chromium/issues/detail?id=981393
    DAWN_SKIP_TEST_IF(IsWindows() && IsVulkan() && IsNvidia());

    CopyConfig config;
    config.textureHeightLevel0 = 60;
    config.textureWidthLevel0 = 60;
    config.rowPitchAlignment = kTextureRowPitchAlignment;

    constexpr uint32_t kMipmapLevelCount = 3;
    config.mipmapLevelCount = kMipmapLevelCount;
    config.baseMipmapLevel = kMipmapLevelCount - 1;

    // The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
    // required in the copies.
    const dawn::Extent3D kVirtualSize = GetVirtualSizeAtLevel(config);
    const dawn::Extent3D kPhysicalSize = GetPhysicalSizeAtLevel(config);
    ASSERT(kVirtualSize.width % kBCBlockWidthInTexels != 0);
    ASSERT(kVirtualSize.height % kBCBlockHeightInTexels != 0);

    config.copyExtent3D = kPhysicalSize;
    for (dawn::TextureFormat format : kBCFormats) {
        // Create bcTextureSrc as the source texture and initialize it with pre-prepared BC
        // compressed data.
        config.format = format;
        dawn::Texture bcTextureSrc = Create2DTexture(
            device, config.format, config.textureWidthLevel0, config.textureHeightLevel0,
            config.arrayLayerCount, config.mipmapLevelCount,
            dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::CopyDst);
        CopyDataIntoCompressedTexture(bcTextureSrc, config);

        // Create bcTexture and copy from the content in bcTextureSrc into it.
        dawn::Texture bcTexture = Create2DTexture(device, config.format, config.textureWidthLevel0,
                                                  config.textureHeightLevel0,
                                                  config.arrayLayerCount, config.mipmapLevelCount);
        dawn::TextureCopyView textureCopyViewSrc = utils::CreateTextureCopyView(
            bcTextureSrc, config.baseMipmapLevel, config.baseArrayLayer, config.copyOrigin3D);
        dawn::TextureCopyView textureCopyViewDst = utils::CreateTextureCopyView(
            bcTexture, config.baseMipmapLevel, config.baseArrayLayer, config.copyOrigin3D);
        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyTextureToTexture(&textureCopyViewSrc, &textureCopyViewDst,
                                     &config.copyExtent3D);
        dawn::CommandBuffer copy = encoder.Finish();
        queue.Submit(1, &copy);

        // Verify if we can use bcTexture as sampled textures correctly.
        dawn::BindGroup bindGroup = CreateBindGroupForTest(
            bcTexture, config.format, config.baseArrayLayer, config.baseMipmapLevel);
        dawn::RenderPipeline renderPipeline = CreateRenderPipelineForTest();

        std::vector<RGBA8> expectedData = GetExpectedData(config.format, kVirtualSize);
        VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, kVirtualSize,
                                           config.copyOrigin3D, kVirtualSize, expectedData);
    }
}

// Test BC format texture-to-texture partial copies.
TEST_P(CompressedTextureBCFormatTest, CopyPartofTextureSubResourceIntoNonZeroMipmapLevel) {
    // TODO(jiawei.shao@intel.com): add workaround on the T2T copies where Extent3D fits in one
    // subresource and does not fit in another one on Vulkan. Currently this test causes an error if
    // Vulkan validation layer is enabled.
    DAWN_SKIP_TEST_IF(IsVulkan());

    CopyConfig srcConfig;
    srcConfig.textureHeightLevel0 = 60;
    srcConfig.textureWidthLevel0 = 60;
    srcConfig.rowPitchAlignment = kTextureRowPitchAlignment;
    srcConfig.mipmapLevelCount = 1;
    srcConfig.baseMipmapLevel = srcConfig.mipmapLevelCount - 1;

    const dawn::Extent3D kSrcVirtualSize = GetVirtualSizeAtLevel(srcConfig);

    CopyConfig dstConfig;
    dstConfig.textureHeightLevel0 = 60;
    dstConfig.textureWidthLevel0 = 60;
    dstConfig.rowPitchAlignment = kTextureRowPitchAlignment;

    constexpr uint32_t kMipmapLevelCount = 3;
    dstConfig.mipmapLevelCount = kMipmapLevelCount;
    dstConfig.baseMipmapLevel = kMipmapLevelCount - 1;

    // The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
    // required in the copies.
    const dawn::Extent3D kDstVirtualSize = GetVirtualSizeAtLevel(dstConfig);
    ASSERT(kDstVirtualSize.width % kBCBlockWidthInTexels != 0);
    ASSERT(kDstVirtualSize.height % kBCBlockHeightInTexels != 0);

    const dawn::Extent3D kDstPhysicalSize = GetPhysicalSizeAtLevel(dstConfig);

    srcConfig.copyExtent3D = dstConfig.copyExtent3D = kDstPhysicalSize;
    ASSERT(srcConfig.copyOrigin3D.x + srcConfig.copyExtent3D.width < kSrcVirtualSize.width);
    ASSERT(srcConfig.copyOrigin3D.y + srcConfig.copyExtent3D.height < kSrcVirtualSize.height);

    for (dawn::TextureFormat format : kBCFormats) {
        // Create bcTextureSrc as the source texture and initialize it with pre-prepared BC
        // compressed data.
        srcConfig.format = format;
        dawn::Texture bcTextureSrc = Create2DTexture(
            device, srcConfig.format, srcConfig.textureWidthLevel0, srcConfig.textureHeightLevel0,
            srcConfig.arrayLayerCount, srcConfig.mipmapLevelCount,
            dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::CopyDst);
        CopyDataIntoCompressedTexture(bcTextureSrc, srcConfig);
        dawn::TextureCopyView textureCopyViewSrc =
            utils::CreateTextureCopyView(bcTextureSrc, srcConfig.baseMipmapLevel,
                                         srcConfig.baseArrayLayer, srcConfig.copyOrigin3D);

        // Create bcTexture and copy from the content in bcTextureSrc into it.
        dstConfig.format = format;
        dawn::Texture bcTexture = Create2DTexture(
            device, dstConfig.format, dstConfig.textureWidthLevel0, dstConfig.textureHeightLevel0,
            dstConfig.arrayLayerCount, dstConfig.mipmapLevelCount);
        dawn::TextureCopyView textureCopyViewDst = utils::CreateTextureCopyView(
            bcTexture, dstConfig.baseMipmapLevel, dstConfig.baseArrayLayer, dstConfig.copyOrigin3D);

        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyTextureToTexture(&textureCopyViewSrc, &textureCopyViewDst,
                                     &dstConfig.copyExtent3D);
        dawn::CommandBuffer copy = encoder.Finish();
        queue.Submit(1, &copy);

        // Verify if we can use bcTexture as sampled textures correctly.
        dawn::BindGroup bindGroup = CreateBindGroupForTest(
            bcTexture, dstConfig.format, dstConfig.baseArrayLayer, dstConfig.baseMipmapLevel);
        dawn::RenderPipeline renderPipeline = CreateRenderPipelineForTest();

        std::vector<RGBA8> expectedData = GetExpectedData(dstConfig.format, kDstVirtualSize);
        VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, kDstVirtualSize,
                                           dstConfig.copyOrigin3D, kDstVirtualSize, expectedData);
    }
}

// Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture
// extent exactly fit the RowPitch.
TEST_P(CompressedTextureBCFormatTest, BufferOffsetAndExtentFitRowPitch) {
    CopyConfig config;
    config.textureWidthLevel0 = 8;
    config.textureHeightLevel0 = 8;
    config.rowPitchAlignment = kTextureRowPitchAlignment;
    config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1};

    const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels;

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;

        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
        const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes;

        config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes;

        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test the special case of the B2T copies on the D3D12 backend that the buffer offset exceeds the
// slice pitch (slicePitch = rowPitch * (imageHeightInTexels / blockHeightInTexels)). On D3D12
// backend the texelOffset.y will be greater than 0 after calcuting the texelOffset in the function
// ComputeTexelOffsets().
TEST_P(CompressedTextureBCFormatTest, BufferOffsetExceedsSlicePitch) {
    CopyConfig config;
    config.textureWidthLevel0 = 8;
    config.textureHeightLevel0 = 8;
    config.rowPitchAlignment = kTextureRowPitchAlignment;
    config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1};

    const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels;
    const uint32_t slicePitchInBytes =
        config.rowPitchAlignment * (config.textureHeightLevel0 / kBCBlockHeightInTexels);

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;

        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
        const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes;

        config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes +
                              config.rowPitchAlignment + slicePitchInBytes;

        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture
// extent exceed the RowPitch. On D3D12 backend two copies are required for this case.
TEST_P(CompressedTextureBCFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitch) {
    CopyConfig config;
    config.textureWidthLevel0 = 8;
    config.textureHeightLevel0 = 8;
    config.rowPitchAlignment = kTextureRowPitchAlignment;
    config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1};

    const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels;

    constexpr uint32_t kExceedRowBlockCount = 1;

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;

        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
        const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes;
        config.bufferOffset =
            (blockCountPerRowPitch - blockCountPerRow + kExceedRowBlockCount) * blockSizeInBytes;

        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// Test the special case of the B2T copies on the D3D12 backend that the slicePitch is equal to the
// rowPitch. On D3D12 backend the texelOffset.z will be greater than 0 after calcuting the
// texelOffset in the function ComputeTexelOffsets().
TEST_P(CompressedTextureBCFormatTest, RowPitchEqualToSlicePitch) {
    CopyConfig config;
    config.textureWidthLevel0 = 8;
    config.textureHeightLevel0 = kBCBlockHeightInTexels;
    config.rowPitchAlignment = kTextureRowPitchAlignment;
    config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1};

    const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels;
    const uint32_t slicePitchInBytes = config.rowPitchAlignment;

    for (dawn::TextureFormat format : kBCFormats) {
        config.format = format;

        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
        const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes;

        config.bufferOffset =
            (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes + slicePitchInBytes;

        TestCopyRegionIntoBCFormatTextures(config);
    }
}

// TODO(jiawei.shao@intel.com): support BC formats on Metal and OpenGL backend
DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest, D3D12Backend, VulkanBackend);
