Adds ASTC texture compression formats and Vulkan support for them.

The end to end texture tests with the binary information for the textures are generated using the open source astc-encoder tool.

Also: Refactors end2end compressed texture tests to allow for non-4x4 texel compression formats (ASTC formats are not all 4x4).

Bug: dawn:955
Change-Id: I5311a5aa7bd017de72300bf7c87fba6c869b1db5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63121
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/dawn.json b/dawn.json
index 0aaf23e..9f85591 100644
--- a/dawn.json
+++ b/dawn.json
@@ -1998,7 +1998,36 @@
             {"value": 62, "name": "EAC R11 unorm"},
             {"value": 63, "name": "EAC R11 snorm"},
             {"value": 64, "name": "EAC RG11 unorm"},
-            {"value": 65, "name": "EAC RG11 snorm"}
+            {"value": 65, "name": "EAC RG11 snorm"},
+
+            {"value": 66, "name": "ASTC 4x4 unorm"},
+            {"value": 67, "name": "ASTC 4x4 unorm srgb"},
+            {"value": 68, "name": "ASTC 5x4 unorm"},
+            {"value": 69, "name": "ASTC 5x4 unorm srgb"},
+            {"value": 70, "name": "ASTC 5x5 unorm"},
+            {"value": 71, "name": "ASTC 5x5 unorm srgb"},
+            {"value": 72, "name": "ASTC 6x5 unorm"},
+            {"value": 73, "name": "ASTC 6x5 unorm srgb"},
+            {"value": 74, "name": "ASTC 6x6 unorm"},
+            {"value": 75, "name": "ASTC 6x6 unorm srgb"},
+            {"value": 76, "name": "ASTC 8x5 unorm"},
+            {"value": 77, "name": "ASTC 8x5 unorm srgb"},
+            {"value": 78, "name": "ASTC 8x6 unorm"},
+            {"value": 79, "name": "ASTC 8x6 unorm srgb"},
+            {"value": 80, "name": "ASTC 8x8 unorm"},
+            {"value": 81, "name": "ASTC 8x8 unorm srgb"},
+            {"value": 82, "name": "ASTC 10x5 unorm"},
+            {"value": 83, "name": "ASTC 10x5 unorm srgb"},
+            {"value": 84, "name": "ASTC 10x6 unorm"},
+            {"value": 85, "name": "ASTC 10x6 unorm srgb"},
+            {"value": 86, "name": "ASTC 10x8 unorm"},
+            {"value": 87, "name": "ASTC 10x8 unorm srgb"},
+            {"value": 88, "name": "ASTC 10x10 unorm"},
+            {"value": 89, "name": "ASTC 10x10 unorm srgb"},
+            {"value": 90, "name": "ASTC 12x10 unorm"},
+            {"value": 91, "name": "ASTC 12x10 unorm srgb"},
+            {"value": 92, "name": "ASTC 12x12 unorm"},
+            {"value": 93, "name": "ASTC 12x12 unorm srgb"}
         ]
     },
     "texture usage": {
diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp
index 327e147..082a9c0 100644
--- a/src/dawn_native/Format.cpp
+++ b/src/dawn_native/Format.cpp
@@ -365,6 +365,37 @@
         AddCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, 16, 4, 4, isETC2FormatSupported, 2);
         AddCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, 16, 4, 4, isETC2FormatSupported, 2);
 
+        // ASTC compressed formats
+        bool isASTCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionASTC);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, 16, 4, 4, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, 16, 4, 4, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, 16, 5, 4, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, 16, 5, 4, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, 16, 5, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, 16, 5, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, 16, 6, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, 16, 6, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, 16, 6, 6, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, 16, 6, 6, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, 16, 8, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, 16, 8, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, 16, 8, 6, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, 16, 8, 6, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, 16, 8, 8, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, 16, 8, 8, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, 16, 10, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, 16, 10, 5, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, 16, 10, 6, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, 16, 10, 6, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, 16, 10, 8, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, 16, 10, 8, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, 16, 10, 10, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, 16, 10, 10, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, 16, 12, 10, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, 16, 12, 10, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, 16, 12, 12, isASTCFormatSupported, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, 16, 12, 12, isASTCFormatSupported, 4);
+
         // multi-planar formats
         const bool isMultiPlanarFormatSupported = device->IsExtensionEnabled(Extension::MultiPlanarFormats);
         AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1,
diff --git a/src/dawn_native/Format.h b/src/dawn_native/Format.h
index b4a8a69..e2e9f61 100644
--- a/src/dawn_native/Format.h
+++ b/src/dawn_native/Format.h
@@ -77,7 +77,7 @@
 
     // The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
     // exact number of known format.
-    static constexpr size_t kKnownFormatCount = 65;
+    static constexpr size_t kKnownFormatCount = 93;
 
     struct Format;
     using FormatTable = std::array<Format, kKnownFormatCount>;
diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp
index 9bbad61..e7a97b3 100644
--- a/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -214,6 +214,35 @@
                 case wgpu::TextureFormat::EACRG11Unorm:
                 case wgpu::TextureFormat::EACRG11Snorm:
 
+                case wgpu::TextureFormat::ASTC4x4Unorm:
+                case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+                case wgpu::TextureFormat::ASTC5x4Unorm:
+                case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+                case wgpu::TextureFormat::ASTC5x5Unorm:
+                case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+                case wgpu::TextureFormat::ASTC6x5Unorm:
+                case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+                case wgpu::TextureFormat::ASTC6x6Unorm:
+                case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+                case wgpu::TextureFormat::ASTC8x5Unorm:
+                case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+                case wgpu::TextureFormat::ASTC8x6Unorm:
+                case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+                case wgpu::TextureFormat::ASTC8x8Unorm:
+                case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+                case wgpu::TextureFormat::ASTC10x5Unorm:
+                case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+                case wgpu::TextureFormat::ASTC10x6Unorm:
+                case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+                case wgpu::TextureFormat::ASTC10x8Unorm:
+                case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+                case wgpu::TextureFormat::ASTC10x10Unorm:
+                case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+                case wgpu::TextureFormat::ASTC12x10Unorm:
+                case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+                case wgpu::TextureFormat::ASTC12x12Unorm:
+                case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+
                 case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
                 case wgpu::TextureFormat::Stencil8:
                 case wgpu::TextureFormat::Undefined:
@@ -352,6 +381,35 @@
             case wgpu::TextureFormat::EACRG11Unorm:
             case wgpu::TextureFormat::EACRG11Snorm:
 
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+
             case wgpu::TextureFormat::Stencil8:
             case wgpu::TextureFormat::Undefined:
                 UNREACHABLE();
diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm
index b03da627..0f359ab 100644
--- a/src/dawn_native/metal/TextureMTL.mm
+++ b/src/dawn_native/metal/TextureMTL.mm
@@ -282,6 +282,35 @@
             case wgpu::TextureFormat::EACRG11Unorm:
             case wgpu::TextureFormat::EACRG11Snorm:
 
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+
             case wgpu::TextureFormat::Stencil8:
             case wgpu::TextureFormat::Undefined:
                 UNREACHABLE();
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 4d6549c..c39854c 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -359,6 +359,63 @@
             case wgpu::TextureFormat::EACRG11Snorm:
                 return VK_FORMAT_EAC_R11G11_SNORM_BLOCK;
 
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+                return VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+                return VK_FORMAT_ASTC_4x4_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+                return VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+                return VK_FORMAT_ASTC_5x4_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+                return VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+                return VK_FORMAT_ASTC_5x5_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+                return VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+                return VK_FORMAT_ASTC_6x5_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+                return VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+                return VK_FORMAT_ASTC_6x6_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+                return VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+                return VK_FORMAT_ASTC_8x5_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+                return VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+                return VK_FORMAT_ASTC_8x6_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+                return VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+                return VK_FORMAT_ASTC_8x8_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+                return VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+                return VK_FORMAT_ASTC_10x5_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+                return VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+                return VK_FORMAT_ASTC_10x6_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+                return VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+                return VK_FORMAT_ASTC_10x8_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+                return VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+                return VK_FORMAT_ASTC_10x10_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+                return VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+                return VK_FORMAT_ASTC_12x10_SRGB_BLOCK;
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+                return VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+                return VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
+
             case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
             case wgpu::TextureFormat::Stencil8:
             case wgpu::TextureFormat::Undefined:
diff --git a/src/tests/end2end/CompressedTextureFormatTests.cpp b/src/tests/end2end/CompressedTextureFormatTests.cpp
index 48f5868..3f4b62a 100644
--- a/src/tests/end2end/CompressedTextureFormatTests.cpp
+++ b/src/tests/end2end/CompressedTextureFormatTests.cpp
@@ -391,6 +391,53 @@
                 return {0x2, 0x90, 0xff, 0xff, 0xff, 0x6d, 0xb6, 0xdb,
                         0x2, 0x90, 0x6d, 0xb6, 0xdb, 0xff, 0xff, 0xff};
 
+            // The expected data is a texel block of the corresponding size where the left width / 2
+            // pixels are dark red with an alpha of 0x80 and the remaining (width - width / 2)
+            // pixels are dark green. We specify the same compressed data in both sRGB and non-sRGB
+            // tests, but the rendering result should be different because for sRGB formats, the
+            // red, green, and blue components are converted from an sRGB color space to a linear
+            // color space as part of filtering, and any alpha component is left unchanged.
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+                return {0x13, 0x80, 0xe9, 0x1, 0x0, 0xe8, 0x1,  0x0,
+                        0x0,  0xff, 0x1,  0x0, 0x0, 0x3f, 0xf0, 0x3};
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+                return {0x83, 0x80, 0xe9, 0x1, 0x0,  0xe8, 0x1,  0x0,
+                        0x0,  0xff, 0x1,  0x0, 0x80, 0x14, 0x90, 0x2};
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+                return {0x2, 0x81, 0xe9, 0x1, 0x0, 0xe8, 0x1,  0x0,
+                        0x0, 0xff, 0x1,  0x0, 0x0, 0x3f, 0xf0, 0x3};
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+                return {0x6, 0x80, 0xe9, 0x1, 0x0,  0xe8, 0x1,  0x0,
+                        0x0, 0xff, 0x1,  0x0, 0xff, 0x0,  0xff, 0x0};
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+                return {0x6, 0x81, 0xe9, 0x1,  0x0, 0xe8, 0x1,  0x0,
+                        0x0, 0xff, 0x1,  0xff, 0x3, 0xf0, 0x3f, 0x0};
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+                return {0x4, 0x80, 0xe9, 0x1, 0x0, 0xe8, 0x1,  0x0,
+                        0x0, 0xff, 0x1,  0x0, 0x0, 0x3f, 0xf0, 0x3};
+
             default:
                 UNREACHABLE();
                 return {};
@@ -401,6 +448,9 @@
     // in RGBA8 formats. Since some compression methods may be lossy, we may use different colors
     // to test different formats.
     std::vector<RGBA8> GetExpectedData(const wgpu::Extent3D& testRegion) {
+        constexpr uint8_t kLeftAlpha = 0x88;
+        constexpr uint8_t kRightAlpha = 0xFF;
+
         constexpr RGBA8 kBCDarkRed(198, 0, 0, 255);
         constexpr RGBA8 kBCDarkGreen(0, 207, 0, 255);
         constexpr RGBA8 kBCDarkRedSRGB(144, 0, 0, 255);
@@ -411,8 +461,10 @@
         constexpr RGBA8 kETC2DarkRedSRGB(154, 0, 0, 255);
         constexpr RGBA8 kETC2DarkGreenSRGB(0, 154, 0, 255);
 
-        constexpr uint8_t kLeftAlpha = 0x88;
-        constexpr uint8_t kRightAlpha = 0xFF;
+        constexpr RGBA8 kASTCDarkRed(244, 0, 0, 128);
+        constexpr RGBA8 kASTCDarkGreen(0, 244, 0, 255);
+        constexpr RGBA8 kASTCDarkRedSRGB(231, 0, 0, 128);
+        constexpr RGBA8 kASTCDarkGreenSRGB(0, 231, 0, 255);
 
         switch (GetParam().mTextureFormat) {
             case wgpu::TextureFormat::BC1RGBAUnorm:
@@ -475,6 +527,38 @@
             case wgpu::TextureFormat::EACRG11Snorm:
                 return FillExpectedData(testRegion, RGBA8::kRed, RGBA8::kGreen);
 
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+                return FillExpectedData(testRegion, kASTCDarkRed, kASTCDarkGreen);
+
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+                return FillExpectedData(testRegion, kASTCDarkRedSRGB, kASTCDarkGreenSRGB);
+
             default:
                 UNREACHABLE();
                 return {};
@@ -497,6 +581,55 @@
         return expectedData;
     }
 
+    // Returns a texture size given the number of texel blocks that should be tiled. For example,
+    // if a texel block size is 5x4, then GetTextureSizeFromBlocks(2, 2) -> {10, 8, 1}.
+    wgpu::Extent3D GetTextureSizeWithNumBlocks(uint32_t numBlockWidth,
+                                               uint32_t numBlockHeight,
+                                               uint32_t depthOrArrayLayers = 1) const {
+        return {numBlockWidth * BlockWidthInTexels(), numBlockHeight * BlockHeightInTexels(),
+                depthOrArrayLayers};
+    }
+
+    CopyConfig GetDefaultFullConfig(uint32_t depthOrArrayLayers = 1) const {
+        ASSERT(IsFormatSupported());
+
+        CopyConfig config;
+        config.textureDescriptor.format = GetParam().mTextureFormat;
+        config.textureDescriptor.usage = kDefaultFormatTextureUsage;
+        config.textureDescriptor.size = GetTextureSizeWithNumBlocks(
+            kUnalignedBlockSize, kUnalignedBlockSize, depthOrArrayLayers);
+        config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
+        config.viewMipmapLevel = kMipmapLevelCount - 1;
+
+        const wgpu::Extent3D virtualSize = GetVirtualSizeAtLevel(config);
+        ASSERT(virtualSize.width % BlockWidthInTexels() != 0u);
+        ASSERT(virtualSize.height % BlockHeightInTexels() != 0u);
+
+        return config;
+    }
+
+    CopyConfig GetDefaultSmallConfig(uint32_t depthOrArrayLayers = 1) const {
+        ASSERT(IsFormatSupported());
+
+        CopyConfig config;
+        config.textureDescriptor.format = GetParam().mTextureFormat;
+        config.textureDescriptor.usage = kDefaultFormatTextureUsage;
+        config.textureDescriptor.size = GetTextureSizeWithNumBlocks(2, 2, depthOrArrayLayers);
+        return config;
+    }
+
+    CopyConfig GetDefaultSubresourceConfig(uint32_t depthOrArrayLayers = 1) const {
+        ASSERT(IsFormatSupported());
+
+        CopyConfig config;
+        config.textureDescriptor.format = GetParam().mTextureFormat;
+        config.textureDescriptor.usage = kDefaultFormatTextureUsage;
+        config.textureDescriptor.size =
+            GetPhysicalSizeAtLevel(GetDefaultFullConfig(depthOrArrayLayers));
+        config.viewMipmapLevel = config.textureDescriptor.mipLevelCount - 1;
+        return config;
+    }
+
     // Note: Compressed formats are only valid with 2D (array) textures.
     static wgpu::Extent3D GetVirtualSizeAtLevel(const CopyConfig& config) {
         return {config.textureDescriptor.size.width >> config.viewMipmapLevel,
@@ -504,7 +637,7 @@
                 config.textureDescriptor.size.depthOrArrayLayers};
     }
 
-    wgpu::Extent3D GetPhysicalSizeAtLevel(const CopyConfig& config) {
+    wgpu::Extent3D GetPhysicalSizeAtLevel(const CopyConfig& config) const {
         wgpu::Extent3D sizeAtLevel = GetVirtualSizeAtLevel(config);
         sizeAtLevel.width = (sizeAtLevel.width + BlockWidthInTexels() - 1) / BlockWidthInTexels() *
                             BlockWidthInTexels();
@@ -516,6 +649,13 @@
     static constexpr wgpu::TextureUsage kDefaultFormatTextureUsage =
         wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst;
 
+    // We choose a prime that is greater than the current max texel dimension size as a multiplier
+    // to compute test texture sizes so that we can be certain that its level 2 mipmap (x4)
+    // cannot be a multiple of the dimension. This is useful for testing padding at the edges of
+    // the mipmaps.
+    static constexpr uint32_t kUnalignedBlockSize = 13;
+    static constexpr uint32_t kMipmapLevelCount = 3;
+
     bool mIsFormatSupported = false;
 };
 
@@ -526,12 +666,9 @@
 
     DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, 1};
+    CopyConfig config = GetDefaultSmallConfig();
     config.copyExtent3D = config.textureDescriptor.size;
 
-    config.textureDescriptor.format = GetParam().mTextureFormat;
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -542,16 +679,10 @@
 
     DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, 1};
+    CopyConfig config = GetDefaultSmallConfig();
+    config.copyOrigin3D = {BlockWidthInTexels(), BlockHeightInTexels(), 0};
+    config.copyExtent3D = {BlockWidthInTexels(), BlockHeightInTexels(), 1};
 
-    const wgpu::Origin3D kOrigin = {4, 4, 0};
-    const wgpu::Extent3D kExtent3D = {4, 4, 1};
-    config.copyOrigin3D = kOrigin;
-    config.copyExtent3D = kExtent3D;
-
-    config.textureDescriptor.format = GetParam().mTextureFormat;
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -565,16 +696,13 @@
     // This test uses glTextureView() which is not supported in OpenGL ES.
     DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, 1};
-    config.copyExtent3D = config.textureDescriptor.size;
-
     constexpr uint32_t kArrayLayerCount = 3;
-    config.textureDescriptor.size.depthOrArrayLayers = kArrayLayerCount;
+
+    CopyConfig config = GetDefaultSmallConfig(kArrayLayerCount);
+    config.copyExtent3D = config.textureDescriptor.size;
+    config.copyExtent3D.depthOrArrayLayers = 1;
     config.copyOrigin3D.z = kArrayLayerCount - 1;
 
-    config.textureDescriptor.format = GetParam().mTextureFormat;
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -588,30 +716,11 @@
     // This test uses glTextureView() which is not supported in OpenGL ES.
     DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {60, 60, 1};
+    CopyConfig config = GetDefaultFullConfig();
+    // The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
+    // dimensions so paddings are required in the copies.
+    config.copyExtent3D = GetPhysicalSizeAtLevel(config);
 
-    constexpr uint32_t kMipmapLevelCount = 3;
-    config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
-    config.viewMipmapLevel = 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 wgpu::Extent3D textureSizeLevel0 = config.textureDescriptor.size;
-    const uint32_t kActualWidthAtLevel = textureSizeLevel0.width >> config.viewMipmapLevel;
-    const uint32_t kActualHeightAtLevel = textureSizeLevel0.height >> config.viewMipmapLevel;
-    ASSERT(kActualWidthAtLevel % BlockWidthInTexels() != 0);
-    ASSERT(kActualHeightAtLevel % BlockHeightInTexels() != 0);
-
-    const uint32_t kCopyWidthAtLevel = (kActualWidthAtLevel + BlockWidthInTexels() - 1) /
-                                       BlockWidthInTexels() * BlockWidthInTexels();
-    const uint32_t kCopyHeightAtLevel = (kActualHeightAtLevel + BlockHeightInTexels() - 1) /
-                                        BlockHeightInTexels() * BlockHeightInTexels();
-
-    config.copyExtent3D = {kCopyWidthAtLevel, kCopyHeightAtLevel, 1};
-
-    config.textureDescriptor.format = GetParam().mTextureFormat;
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -629,30 +738,17 @@
     // black instead of opaque red on Win10 FYI Release (NVIDIA GeForce GTX 1660).
     DAWN_SUPPRESS_TEST_IF(IsWindows() && IsVulkan() && IsNvidia());
 
-    CopyConfig config;
-    config.textureDescriptor.size = {60, 60, 1};
-
-    constexpr uint32_t kMipmapLevelCount = 3;
-    config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
-    config.viewMipmapLevel = 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 wgpu::Extent3D kVirtualSize = GetVirtualSizeAtLevel(config);
-    const wgpu::Extent3D kPhysicalSize = GetPhysicalSizeAtLevel(config);
-    ASSERT_NE(0u, kVirtualSize.width % BlockWidthInTexels());
-    ASSERT_NE(0u, kVirtualSize.height % BlockHeightInTexels());
-
-    config.copyExtent3D = kPhysicalSize;
-
-    // Create textureSrc as the source texture and initialize it with pre-prepared compressed
-    // data.
-    config.textureDescriptor.format = GetParam().mTextureFormat;
+    CopyConfig config = GetDefaultFullConfig();
     // Add the usage bit for both source and destination textures so that we don't need to
     // create two copy configs.
     config.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
                                      wgpu::TextureUsage::TextureBinding;
 
+    // The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
+    // dimensions so paddings are required in the copies.
+    const wgpu::Extent3D kVirtualSize = GetVirtualSizeAtLevel(config);
+    config.copyExtent3D = GetPhysicalSizeAtLevel(config);
+
     wgpu::Texture textureSrc = CreateTextureWithCompressedData(config);
 
     // Create textureDst and copy from the content in textureSrc into it.
@@ -678,42 +774,24 @@
     // subresource and does not fit in another one on OpenGL.
     DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
 
-    CopyConfig srcConfig;
-    srcConfig.textureDescriptor.size = {60, 60, 1};
-    srcConfig.viewMipmapLevel = srcConfig.textureDescriptor.mipLevelCount - 1;
+    CopyConfig srcConfig = GetDefaultSubresourceConfig();
+    srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
 
-    const wgpu::Extent3D kSrcVirtualSize = GetVirtualSizeAtLevel(srcConfig);
+    CopyConfig dstConfig = GetDefaultFullConfig();
 
-    CopyConfig dstConfig;
-    dstConfig.textureDescriptor.size = {60, 60, 1};
-    constexpr uint32_t kMipmapLevelCount = 3;
-    dstConfig.textureDescriptor.mipLevelCount = kMipmapLevelCount;
-    dstConfig.viewMipmapLevel = kMipmapLevelCount - 1;
-
-    // The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
-    // required in the copies.
+    // The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
+    // dimensions so paddings are required in the copies.
     const wgpu::Extent3D kDstVirtualSize = GetVirtualSizeAtLevel(dstConfig);
-    ASSERT_NE(0u, kDstVirtualSize.width % BlockWidthInTexels());
-    ASSERT_NE(0u, kDstVirtualSize.height % BlockHeightInTexels());
-
     const wgpu::Extent3D kDstPhysicalSize = GetPhysicalSizeAtLevel(dstConfig);
-
     srcConfig.copyExtent3D = dstConfig.copyExtent3D = kDstPhysicalSize;
-    ASSERT_LT(srcConfig.copyOrigin3D.x + srcConfig.copyExtent3D.width, kSrcVirtualSize.width);
-    ASSERT_LT(srcConfig.copyOrigin3D.y + srcConfig.copyExtent3D.height, kSrcVirtualSize.height);
 
     // Create textureSrc as the source texture and initialize it with pre-prepared compressed
     // data.
-    const wgpu::TextureFormat format = GetParam().mTextureFormat;
-    srcConfig.textureDescriptor.format = format;
-    srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
     wgpu::Texture textureSrc = CreateTextureWithCompressedData(srcConfig);
     wgpu::ImageCopyTexture imageCopyTextureSrc = utils::CreateImageCopyTexture(
         textureSrc, srcConfig.viewMipmapLevel, srcConfig.copyOrigin3D);
 
     // Create textureDst and copy from the content in textureSrc into it.
-    dstConfig.textureDescriptor.format = format;
-    dstConfig.textureDescriptor.usage = kDefaultFormatTextureUsage;
     wgpu::Texture textureDst = CreateTextureFromTexture(textureSrc, srcConfig, dstConfig);
 
     // Verify if we can use texture as sampled textures correctly.
@@ -736,33 +814,20 @@
     // subresource and does not fit in another one on OpenGL.
     DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
 
-    CopyConfig srcConfig;
-    srcConfig.textureDescriptor.size = {60, 60, 1};
-    constexpr uint32_t kMipmapLevelCount = 3;
-    srcConfig.textureDescriptor.mipLevelCount = kMipmapLevelCount;
-    srcConfig.viewMipmapLevel = srcConfig.textureDescriptor.mipLevelCount - 1;
+    CopyConfig srcConfig = GetDefaultFullConfig();
+    srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
 
-    // The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
-    // required in the copies.
+    CopyConfig dstConfig = GetDefaultSubresourceConfig();
+
+    // The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
+    // dimensions so paddings are required in the copies.
     const wgpu::Extent3D kSrcVirtualSize = GetVirtualSizeAtLevel(srcConfig);
-    ASSERT_NE(0u, kSrcVirtualSize.width % BlockWidthInTexels());
-    ASSERT_NE(0u, kSrcVirtualSize.height % BlockHeightInTexels());
-
-    CopyConfig dstConfig;
-    dstConfig.textureDescriptor.size = {16, 16, 1};
-    dstConfig.viewMipmapLevel = dstConfig.textureDescriptor.mipLevelCount - 1;
-
     const wgpu::Extent3D kDstVirtualSize = GetVirtualSizeAtLevel(dstConfig);
     srcConfig.copyExtent3D = dstConfig.copyExtent3D = kDstVirtualSize;
 
     ASSERT_GT(srcConfig.copyOrigin3D.x + srcConfig.copyExtent3D.width, kSrcVirtualSize.width);
     ASSERT_GT(srcConfig.copyOrigin3D.y + srcConfig.copyExtent3D.height, kSrcVirtualSize.height);
 
-    srcConfig.textureDescriptor.format = dstConfig.textureDescriptor.format =
-        GetParam().mTextureFormat;
-    srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
-    dstConfig.textureDescriptor.usage = kDefaultFormatTextureUsage;
-
     // Create textureSrc as the source texture and initialize it with pre-prepared compressed
     // data.
     wgpu::Texture textureSrc = CreateTextureWithCompressedData(srcConfig);
@@ -794,68 +859,52 @@
     std::array<CopyConfig, kTotalCopyCount> srcConfigs;
     std::array<CopyConfig, kTotalCopyCount> dstConfigs;
 
-    constexpr uint32_t kSrcMipmapLevelCount0 = 3;
-    srcConfigs[0].textureDescriptor.size = {60, 60, 1};
-    srcConfigs[0].textureDescriptor.mipLevelCount = kSrcMipmapLevelCount0;
-    srcConfigs[0].viewMipmapLevel = srcConfigs[0].textureDescriptor.mipLevelCount - 1;
-    dstConfigs[0].textureDescriptor.size = {16, 16, 1};
-    dstConfigs[0].viewMipmapLevel = dstConfigs[0].textureDescriptor.mipLevelCount - 1;
+    srcConfigs[0] = GetDefaultFullConfig();
+    srcConfigs[0].textureDescriptor.usage =
+        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+    dstConfigs[0] = GetDefaultSubresourceConfig();
     srcConfigs[0].copyExtent3D = dstConfigs[0].copyExtent3D = GetVirtualSizeAtLevel(dstConfigs[0]);
-    const wgpu::Extent3D kSrcVirtualSize0 = GetVirtualSizeAtLevel(srcConfigs[0]);
-    ASSERT_NE(0u, kSrcVirtualSize0.width % BlockWidthInTexels());
-    ASSERT_NE(0u, kSrcVirtualSize0.height % BlockHeightInTexels());
 
-    constexpr uint32_t kDstMipmapLevelCount1 = 4;
-    srcConfigs[1].textureDescriptor.size = {8, 8, 1};
-    srcConfigs[1].viewMipmapLevel = srcConfigs[1].textureDescriptor.mipLevelCount - 1;
-    dstConfigs[1].textureDescriptor.size = {56, 56, 1};
-    dstConfigs[1].textureDescriptor.mipLevelCount = kDstMipmapLevelCount1;
-    dstConfigs[1].viewMipmapLevel = dstConfigs[1].textureDescriptor.mipLevelCount - 1;
+    srcConfigs[1] = GetDefaultSubresourceConfig();
+    srcConfigs[1].textureDescriptor.usage =
+        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+    dstConfigs[1] = GetDefaultFullConfig();
     srcConfigs[1].copyExtent3D = dstConfigs[1].copyExtent3D = GetVirtualSizeAtLevel(srcConfigs[1]);
 
     std::array<wgpu::Extent3D, kTotalCopyCount> dstVirtualSizes;
     for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
         dstVirtualSizes[i] = GetVirtualSizeAtLevel(dstConfigs[i]);
     }
-    ASSERT_NE(0u, dstVirtualSizes[1].width % BlockWidthInTexels());
-    ASSERT_NE(0u, dstVirtualSizes[1].height % BlockHeightInTexels());
 
     std::array<wgpu::Texture, kTotalCopyCount> srcTextures;
     std::array<wgpu::Texture, kTotalCopyCount> dstTextures;
 
     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
     for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
-        srcConfigs[i].textureDescriptor.format = dstConfigs[i].textureDescriptor.format =
-            GetParam().mTextureFormat;
-        srcConfigs[i].textureDescriptor.usage =
-            wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
-        dstConfigs[i].textureDescriptor.usage = kDefaultFormatTextureUsage;
-
         // Create srcTextures as the source textures and initialize them with pre-prepared
         // compressed data.
         srcTextures[i] = CreateTextureWithCompressedData(srcConfigs[i]);
         dstTextures[i] = device.CreateTexture(&dstConfigs[i].textureDescriptor);
-
         RecordTextureToTextureCopy(encoder, srcTextures[i], dstTextures[i], srcConfigs[i],
                                    dstConfigs[i]);
     }
 
-        wgpu::CommandBuffer commandBuffer = encoder.Finish();
-        queue.Submit(1, &commandBuffer);
+    wgpu::CommandBuffer commandBuffer = encoder.Finish();
+    queue.Submit(1, &commandBuffer);
 
-        wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
+    wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
 
-        for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
-            // Verify if we can use dstTextures as sampled textures correctly.
-            wgpu::BindGroup bindGroup0 =
-                CreateBindGroupForTest(renderPipeline.GetBindGroupLayout(0), dstTextures[i],
-                                       dstConfigs[i].copyOrigin3D.z, dstConfigs[i].viewMipmapLevel);
+    for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
+        // Verify if we can use dstTextures as sampled textures correctly.
+        wgpu::BindGroup bindGroup0 =
+            CreateBindGroupForTest(renderPipeline.GetBindGroupLayout(0), dstTextures[i],
+                                   dstConfigs[i].copyOrigin3D.z, dstConfigs[i].viewMipmapLevel);
 
-            std::vector<RGBA8> expectedData = GetExpectedData(dstVirtualSizes[i]);
-            VerifyCompressedTexturePixelValues(renderPipeline, bindGroup0, dstVirtualSizes[i],
-                                               dstConfigs[i].copyOrigin3D, dstVirtualSizes[i],
-                                               expectedData);
-        }
+        std::vector<RGBA8> expectedData = GetExpectedData(dstVirtualSizes[i]);
+        VerifyCompressedTexturePixelValues(renderPipeline, bindGroup0, dstVirtualSizes[i],
+                                           dstConfigs[i].copyOrigin3D, dstVirtualSizes[i],
+                                           expectedData);
+    }
 }
 
 // A regression test for a bug for the toggle UseTemporaryBufferInCompressedTextureToTextureCopy on
@@ -870,27 +919,18 @@
 
     constexpr uint32_t kArrayLayerCount = 5;
 
-    CopyConfig srcConfig;
-    srcConfig.textureDescriptor.size = {60, 60, kArrayLayerCount};
-    constexpr uint32_t kMipmapLevelCount = 3;
-    srcConfig.textureDescriptor.mipLevelCount = kMipmapLevelCount;
-    srcConfig.viewMipmapLevel = srcConfig.textureDescriptor.mipLevelCount - 1;
+    CopyConfig srcConfig = GetDefaultFullConfig(kArrayLayerCount);
     srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
 
-    // The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
-    // required in the copies.
+    CopyConfig dstConfig = GetDefaultSubresourceConfig(kArrayLayerCount);
+
+    // The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
+    // dimensions so paddings are required in the copies.
     const wgpu::Extent3D kSrcVirtualSize = GetVirtualSizeAtLevel(srcConfig);
-    ASSERT_NE(0u, kSrcVirtualSize.width % BlockWidthInTexels());
-    ASSERT_NE(0u, kSrcVirtualSize.height % BlockHeightInTexels());
-
-    CopyConfig dstConfig;
-    dstConfig.textureDescriptor.size = {16, 16, kArrayLayerCount};
-    dstConfig.viewMipmapLevel = dstConfig.textureDescriptor.mipLevelCount - 1;
-
     const wgpu::Extent3D kDstVirtualSize = GetVirtualSizeAtLevel(dstConfig);
+
     srcConfig.copyExtent3D = dstConfig.copyExtent3D = kDstVirtualSize;
     srcConfig.rowsPerImage = srcConfig.copyExtent3D.height / BlockHeightInTexels();
-
     ASSERT_GT(srcConfig.copyOrigin3D.x + srcConfig.copyExtent3D.width, kSrcVirtualSize.width);
     ASSERT_GT(srcConfig.copyOrigin3D.y + srcConfig.copyExtent3D.height, kSrcVirtualSize.height);
 
@@ -936,19 +976,13 @@
 
     DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, 1};
+    CopyConfig config = GetDefaultSmallConfig();
     config.copyExtent3D = config.textureDescriptor.size;
 
-    const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
-
     const wgpu::TextureFormat format = GetParam().mTextureFormat;
-    config.textureDescriptor.format = format;
-
+    const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
     const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
     const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
-
     config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes;
 
     TestCopyRegionIntoFormatTextures(config);
@@ -964,22 +998,16 @@
 
     DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, 1};
+    CopyConfig config = GetDefaultSmallConfig();
     config.copyExtent3D = config.textureDescriptor.size;
 
-    const wgpu::Extent3D textureSizeLevel0 = config.textureDescriptor.size;
-    const uint32_t blockCountPerRow = textureSizeLevel0.width / BlockWidthInTexels();
-    const uint32_t slicePitchInBytes =
-        config.bytesPerRowAlignment * (textureSizeLevel0.height / BlockHeightInTexels());
-
     const wgpu::TextureFormat format = GetParam().mTextureFormat;
-    config.textureDescriptor.format = format;
-
+    const wgpu::Extent3D textureSizeLevel = config.textureDescriptor.size;
+    const uint32_t blockCountPerRow = textureSizeLevel.width / BlockWidthInTexels();
+    const uint32_t slicePitchInBytes =
+        config.bytesPerRowAlignment * (textureSizeLevel.height / BlockHeightInTexels());
     const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
     const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
-
     config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes +
                           config.bytesPerRowAlignment + slicePitchInBytes;
 
@@ -994,18 +1022,13 @@
 
     DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, 1};
-    config.copyExtent3D = config.textureDescriptor.size;
-
-    const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
-
     constexpr uint32_t kExceedRowBlockCount = 1;
 
-    const wgpu::TextureFormat format = GetParam().mTextureFormat;
-    config.textureDescriptor.format = format;
+    CopyConfig config = GetDefaultSmallConfig();
+    config.copyExtent3D = config.textureDescriptor.size;
 
+    const wgpu::TextureFormat format = GetParam().mTextureFormat;
+    const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
     const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
     const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
     config.bufferOffset =
@@ -1020,20 +1043,15 @@
 TEST_P(CompressedTextureFormatTest, RowPitchEqualToSlicePitch) {
     DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, BlockHeightInTexels(), 1};
+    CopyConfig config = GetDefaultSmallConfig();
+    config.textureDescriptor.size = GetTextureSizeWithNumBlocks(2, 1);
     config.copyExtent3D = config.textureDescriptor.size;
 
+    const wgpu::TextureFormat format = GetParam().mTextureFormat;
     const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
     const uint32_t slicePitchInBytes = config.bytesPerRowAlignment;
-
-    const wgpu::TextureFormat format = GetParam().mTextureFormat;
-    config.textureDescriptor.format = format;
-
     const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
     const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
-
     config.bufferOffset =
         (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes + slicePitchInBytes;
 
@@ -1049,13 +1067,10 @@
 
     DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, 1};
+    CopyConfig config = GetDefaultSmallConfig();
     config.copyExtent3D = config.textureDescriptor.size;
-
     config.rowsPerImage = config.textureDescriptor.size.height * 2 / BlockHeightInTexels();
-    config.textureDescriptor.format = GetParam().mTextureFormat;
+
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -1070,32 +1085,14 @@
     // This test uses glTextureView() which is not supported in OpenGL ES.
     DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {56, 56, 1};
+    CopyConfig config = GetDefaultFullConfig();
 
-    constexpr uint32_t kMipmapLevelCount = 3;
-    config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
-    config.viewMipmapLevel = kMipmapLevelCount - 1;
+    // The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
+    // dimensions so paddings are required in the copies.
+    const wgpu::Extent3D kPhysicalSize = GetPhysicalSizeAtLevel(config);
+    config.copyExtent3D = kPhysicalSize;
+    config.rowsPerImage = kPhysicalSize.height * 2 / BlockHeightInTexels();
 
-    // The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
-    // required in the copies.
-    const wgpu::Extent3D textureSizeLevel0 = config.textureDescriptor.size;
-    const uint32_t kActualWidthAtLevel = textureSizeLevel0.width >> config.viewMipmapLevel;
-    const uint32_t kActualHeightAtLevel = textureSizeLevel0.height >> config.viewMipmapLevel;
-    ASSERT(kActualWidthAtLevel % BlockWidthInTexels() != 0);
-    ASSERT(kActualHeightAtLevel % BlockHeightInTexels() != 0);
-
-    const uint32_t kCopyWidthAtLevel = (kActualWidthAtLevel + BlockWidthInTexels() - 1) /
-                                       BlockWidthInTexels() * BlockWidthInTexels();
-    const uint32_t kCopyHeightAtLevel = (kActualHeightAtLevel + BlockHeightInTexels() - 1) /
-                                        BlockHeightInTexels() * BlockHeightInTexels();
-
-    config.copyExtent3D = {kCopyWidthAtLevel, kCopyHeightAtLevel, 1};
-
-    config.rowsPerImage = kCopyHeightAtLevel * 2 / BlockHeightInTexels();
-
-    config.textureDescriptor.format = GetParam().mTextureFormat;
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -1112,15 +1109,11 @@
 
     constexpr uint32_t kArrayLayerCount = 3;
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, kArrayLayerCount};
+    CopyConfig config = GetDefaultSmallConfig(kArrayLayerCount);
     config.rowsPerImage = 8;
-
     config.copyExtent3D = config.textureDescriptor.size;
     config.copyExtent3D.depthOrArrayLayers = kArrayLayerCount;
 
-    config.textureDescriptor.format = GetParam().mTextureFormat;
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -1136,9 +1129,7 @@
 
     constexpr uint32_t kArrayLayerCount = 3;
 
-    CopyConfig config;
-    config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {8, 8, kArrayLayerCount};
+    CopyConfig config = GetDefaultSmallConfig(kArrayLayerCount);
     config.rowsPerImage = 8;
 
     constexpr uint32_t kCopyBaseArrayLayer = 1;
@@ -1147,7 +1138,6 @@
     config.copyExtent3D = config.textureDescriptor.size;
     config.copyExtent3D.depthOrArrayLayers = kCopyLayerCount;
 
-    config.textureDescriptor.format = GetParam().mTextureFormat;
     TestCopyRegionIntoFormatTextures(config);
 }
 
@@ -1258,15 +1248,25 @@
     // TODO(crbug.com/dawn/976): Failing on Linux Intel OpenGL drivers.
     DAWN_SUPPRESS_TEST_IF(IsIntel() && IsOpenGL() && IsLinux());
 
+    constexpr uint32_t kSizeWidthMultiplier = 5;
+    constexpr uint32_t kSizeHeightMultiplier = 6;
+    constexpr uint32_t kOriginWidthMultiplier = 1;
+    constexpr uint32_t kOriginHeightMultiplier = 2;
+    constexpr uint32_t kExtentWidthMultiplier = 3;
+    constexpr uint32_t kExtentHeightMultiplier = 4;
+
     CopyConfig config;
     config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {20, 24, 1};
-
-    config.copyOrigin3D = {4, 8, 0};
-    config.copyExtent3D = {12, 16, 1};
+    config.textureDescriptor.size = {BlockWidthInTexels() * kSizeWidthMultiplier,
+                                     BlockHeightInTexels() * kSizeHeightMultiplier, 1};
+    config.copyOrigin3D = {BlockWidthInTexels() * kOriginWidthMultiplier,
+                           BlockHeightInTexels() * kOriginHeightMultiplier, 0};
+    config.copyExtent3D = {BlockWidthInTexels() * kExtentWidthMultiplier,
+                           BlockHeightInTexels() * kExtentHeightMultiplier, 1};
     config.bytesPerRowAlignment = 511;
     config.rowsPerImage = 5;
     config.textureDescriptor.format = GetParam().mTextureFormat;
+
     TestWriteRegionIntoFormatTextures(config);
 }
 
@@ -1278,15 +1278,26 @@
     // TODO(crbug.com/dawn/593): This test uses glTextureView() which is not supported on OpenGLES.
     DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
 
+    // TODO(b/198674734): Width multiplier set to 7 because 5 results in square size for ASTC6x5.
+    constexpr uint32_t kSizeWidthMultiplier = 7;
+    constexpr uint32_t kSizeHeightMultiplier = 6;
+    constexpr uint32_t kOriginWidthMultiplier = 1;
+    constexpr uint32_t kOriginHeightMultiplier = 2;
+    constexpr uint32_t kExtentWidthMultiplier = 3;
+    constexpr uint32_t kExtentHeightMultiplier = 4;
+
     CopyConfig config;
     config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-    config.textureDescriptor.size = {20, 24, 9};
-
-    config.copyOrigin3D = {4, 8, 3};
-    config.copyExtent3D = {12, 16, 6};
+    config.textureDescriptor.size = {BlockWidthInTexels() * kSizeWidthMultiplier,
+                                     BlockHeightInTexels() * kSizeHeightMultiplier, 9};
+    config.copyOrigin3D = {BlockWidthInTexels() * kOriginWidthMultiplier,
+                           BlockHeightInTexels() * kOriginHeightMultiplier, 3};
+    config.copyExtent3D = {BlockWidthInTexels() * kExtentWidthMultiplier,
+                           BlockHeightInTexels() * kExtentHeightMultiplier, 6};
     config.bytesPerRowAlignment = 511;
     config.rowsPerImage = 5;
     config.textureDescriptor.format = GetParam().mTextureFormat;
+
     TestWriteRegionIntoFormatTextures(config);
 }
 
@@ -1300,25 +1311,19 @@
     // TODO(crbug.com/dawn/593): This test uses glTextureView() which is not supported on OpenGLES.
     DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
 
-    // Texture virtual size at mipLevel 2 will be {15, 15, 1} while the physical
-    // size will be {16, 16, 1}.
-    // Setting copyExtent.width or copyExtent.height to 16 fits in
-    // the texture physical size, but doesn't fit in the virtual size.
-    for (unsigned int w : {12, 16}) {
-        for (unsigned int h : {12, 16}) {
-                CopyConfig config;
-                config.textureDescriptor.usage = kDefaultFormatTextureUsage;
-                config.textureDescriptor.size = {60, 60, 1};
-                config.textureDescriptor.mipLevelCount = 4;
-                config.viewMipmapLevel = 2;
+    CopyConfig config = GetDefaultFullConfig();
 
-                config.copyOrigin3D = {0, 0, 0};
-                config.copyExtent3D = {w, h, 1};
-                config.bytesPerRowAlignment = 256;
-                config.textureDescriptor.format = GetParam().mTextureFormat;
-                TestWriteRegionIntoFormatTextures(config);
-            }
+    // The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
+    // dimensions so paddings are required in the copies. We then test against the expected
+    // physical size and a valid size smaller than the physical size for verification.
+    const wgpu::Extent3D kPhysicalSize = GetPhysicalSizeAtLevel(config);
+    for (unsigned int w : {kPhysicalSize.width - BlockWidthInTexels(), kPhysicalSize.width}) {
+        for (unsigned int h :
+             {kPhysicalSize.height - BlockHeightInTexels(), kPhysicalSize.height}) {
+            config.copyExtent3D = {w, h, 1};
+            TestWriteRegionIntoFormatTextures(config);
         }
+    }
 }
 
 DAWN_INSTANTIATE_TEST_P(CompressedTextureWriteTextureTest,
diff --git a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
index 728a4a2..63e72b2 100644
--- a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
+++ b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
@@ -198,6 +198,33 @@
     }
 };
 
+// Test copies between buffer and multiple array layers of an uncompressed texture
+TEST_F(CopyCommandTest, CopyToMultipleArrayLayers) {
+    wgpu::Texture destination =
+        CopyCommandTest::Create2DTexture(4, 2, 1, 5, wgpu::TextureFormat::RGBA8Unorm,
+                                         wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
+
+    // Copy to all array layers
+    TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
+                                    {4, 2, 5});
+
+    // Copy to the highest array layer
+    TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 4},
+                                    {4, 2, 1});
+
+    // Copy to array layers in the middle
+    TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
+                                    {4, 2, 3});
+
+    // Copy with a non-packed rowsPerImage
+    TestBothTBCopiesExactBufferSize(256, 3, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
+                                    {4, 2, 5});
+
+    // Copy with bytesPerRow = 512
+    TestBothTBCopiesExactBufferSize(512, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
+                                    {4, 2, 3});
+}
+
 class CopyCommandTest_B2B : public CopyCommandTest {};
 
 // TODO(cwallez@chromium.org): Test that copies are forbidden inside renderpasses
@@ -2026,9 +2053,9 @@
     }
 
     wgpu::Texture Create2DTexture(wgpu::TextureFormat format,
-                                  uint32_t mipmapLevels = 1,
-                                  uint32_t width = kWidth,
-                                  uint32_t height = kHeight) {
+                                  uint32_t mipmapLevels,
+                                  uint32_t width,
+                                  uint32_t height) {
         constexpr wgpu::TextureUsage kUsage = wgpu::TextureUsage::CopyDst |
                                               wgpu::TextureUsage::CopySrc |
                                               wgpu::TextureUsage::TextureBinding;
@@ -2037,8 +2064,12 @@
                                                 kUsage, 1);
     }
 
-    static constexpr uint32_t kWidth = 16;
-    static constexpr uint32_t kHeight = 16;
+    // By default, we use a 4x4 tiling of the format block size.
+    wgpu::Texture Create2DTexture(wgpu::TextureFormat format) {
+        uint32_t width = utils::GetTextureFormatBlockWidth(format) * 4;
+        uint32_t height = utils::GetTextureFormatBlockHeight(format) * 4;
+        return Create2DTexture(format, 1, width, height);
+    }
 };
 
 // Tests to verify that bufferOffset must be a multiple of the compressed texture blocks in bytes
@@ -2049,19 +2080,21 @@
 
     for (wgpu::TextureFormat format : utils::kCompressedFormats) {
         wgpu::Texture texture = Create2DTexture(format);
+        uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+        uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
 
         // Valid usages of BufferOffset in B2T and T2B copies with compressed texture formats.
         {
             uint32_t validBufferOffset = utils::GetTexelBlockSizeInBytes(format);
             TestBothTBCopies(utils::Expectation::Success, buffer, validBufferOffset, 256, 4,
-                             texture, 0, {0, 0, 0}, {4, 4, 1});
+                             texture, 0, {0, 0, 0}, {blockWidth, blockHeight, 1});
         }
 
         // Failures on invalid bufferOffset.
         {
             uint32_t kInvalidBufferOffset = utils::GetTexelBlockSizeInBytes(format) / 2;
             TestBothTBCopies(utils::Expectation::Failure, buffer, kInvalidBufferOffset, 256, 4,
-                             texture, 0, {0, 0, 0}, {4, 4, 1});
+                             texture, 0, {0, 0, 0}, {blockWidth, blockHeight, 1});
         }
     }
 }
@@ -2073,36 +2106,40 @@
     wgpu::Buffer buffer =
         CreateBuffer(1024, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
 
-        constexpr uint32_t kTestWidth = 160;
-        constexpr uint32_t kTestHeight = 160;
+    // Used to compute test width and height. We choose 320 because it isn't divisible by 256 and
+    // hence will need to be aligned.
+    constexpr uint32_t kInvalidBytesPerRow = 320;
 
-        for (wgpu::TextureFormat format : utils::kCompressedFormats) {
-            wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
+    for (wgpu::TextureFormat format : utils::kCompressedFormats) {
+        // Compute the test width and height such that the smallest BytesPerRow is always equal to
+        // 320. We choose 320 because it isn't divisible by 256 and hence needs to be aligned.
+        uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+        uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
+        uint32_t blockByteSize = utils::GetTexelBlockSizeInBytes(format);
+        uint32_t testWidth = kInvalidBytesPerRow * blockWidth / blockByteSize;
+        uint32_t testHeight = kInvalidBytesPerRow * blockHeight / blockByteSize;
+        wgpu::Texture texture = Create2DTexture(format, 1, testWidth, testHeight);
 
-            // Failures on the BytesPerRow that is not large enough.
-            {
-                constexpr uint32_t kSmallBytesPerRow = 256;
-                TestBothTBCopies(utils::Expectation::Failure, buffer, 0, kSmallBytesPerRow, 4,
-                                 texture, 0, {0, 0, 0}, {kTestWidth, 4, 1});
-            }
-
-            // Test it is not valid to use a BytesPerRow that is not a multiple of 256.
-            {
-                uint32_t inValidBytesPerRow =
-                    kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format);
-                ASSERT_NE(0u, inValidBytesPerRow % 256);
-                TestBothTBCopies(utils::Expectation::Failure, buffer, 0, inValidBytesPerRow, 4,
-                                 texture, 0, {0, 0, 0}, {kTestWidth, 4, 1});
-            }
-
-            // Test the smallest valid BytesPerRow should work.
-            {
-                uint32_t smallestValidBytesPerRow =
-                    Align(kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format), 256);
-                TestBothTBCopies(utils::Expectation::Success, buffer, 0, smallestValidBytesPerRow,
-                                 4, texture, 0, {0, 0, 0}, {kTestWidth, 4, 1});
-            }
+        // Failures on the BytesPerRow that is not large enough.
+        {
+            constexpr uint32_t kSmallBytesPerRow = 256;
+            TestBothTBCopies(utils::Expectation::Failure, buffer, 0, kSmallBytesPerRow, 4, texture,
+                             0, {0, 0, 0}, {testWidth, blockHeight, 1});
         }
+
+        // Test it is not valid to use a BytesPerRow that is not a multiple of 256.
+        {
+            TestBothTBCopies(utils::Expectation::Failure, buffer, 0, kInvalidBytesPerRow, 4,
+                             texture, 0, {0, 0, 0}, {testWidth, blockHeight, 1});
+        }
+
+        // Test the smallest valid BytesPerRow should work.
+        {
+            uint32_t smallestValidBytesPerRow = Align(kInvalidBytesPerRow, 256);
+            TestBothTBCopies(utils::Expectation::Success, buffer, 0, smallestValidBytesPerRow, 4,
+                             texture, 0, {0, 0, 0}, {testWidth, blockHeight, 1});
+        }
+    }
 }
 
 // rowsPerImage must be >= heightInBlocks.
@@ -2112,24 +2149,26 @@
 
     for (wgpu::TextureFormat format : utils::kCompressedFormats) {
         wgpu::Texture texture = Create2DTexture(format);
+        uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+        uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
 
         // Valid usages of rowsPerImage in B2T and T2B copies with compressed texture formats.
         {
             constexpr uint32_t kValidRowsPerImage = 5;
             TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, kValidRowsPerImage,
-                             texture, 0, {0, 0, 0}, {4, 16, 1});
+                             texture, 0, {0, 0, 0}, {blockWidth, blockHeight * 4, 1});
         }
         {
             constexpr uint32_t kValidRowsPerImage = 4;
             TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, kValidRowsPerImage,
-                             texture, 0, {0, 0, 0}, {4, 16, 1});
+                             texture, 0, {0, 0, 0}, {blockWidth, blockHeight * 4, 1});
         }
 
         // rowsPerImage is smaller than height.
         {
             constexpr uint32_t kInvalidRowsPerImage = 3;
             TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, kInvalidRowsPerImage,
-                             texture, 0, {0, 0, 0}, {4, 20, 1});
+                             texture, 0, {0, 0, 0}, {blockWidth, blockHeight * 5, 1});
         }
     }
 }
@@ -2144,35 +2183,37 @@
     for (wgpu::TextureFormat format : utils::kCompressedFormats) {
         wgpu::Texture texture = Create2DTexture(format);
         wgpu::Texture texture2 = Create2DTexture(format);
+        uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+        uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
 
-        constexpr wgpu::Origin3D kSmallestValidOrigin3D = {4, 4, 0};
+        wgpu::Origin3D smallestValidOrigin3D = {blockWidth, blockHeight, 0};
 
         // Valid usages of ImageOffset in B2T, T2B and T2T copies with compressed texture formats.
         {
             TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 4, texture, 0,
-                             kSmallestValidOrigin3D, {4, 4, 1});
+                             smallestValidOrigin3D, {blockWidth, blockHeight, 1});
             TestBothT2TCopies(utils::Expectation::Success, texture, 0, {0, 0, 0}, texture2, 0,
-                              kSmallestValidOrigin3D, {4, 4, 1});
+                              smallestValidOrigin3D, {blockWidth, blockHeight, 1});
         }
 
         // Failures on invalid ImageOffset.x.
         {
-            constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x - 1,
-                                                         kSmallestValidOrigin3D.y, 0};
+            wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x - 1, smallestValidOrigin3D.y,
+                                              0};
             TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0,
-                             kInvalidOrigin3D, {4, 4, 1});
-            TestBothT2TCopies(utils::Expectation::Failure, texture, 0, kInvalidOrigin3D, texture2,
-                              0, {0, 0, 0}, {4, 4, 1});
+                             invalidOrigin3D, {blockWidth, blockHeight, 1});
+            TestBothT2TCopies(utils::Expectation::Failure, texture, 0, invalidOrigin3D, texture2, 0,
+                              {0, 0, 0}, {blockWidth, blockHeight, 1});
         }
 
         // Failures on invalid ImageOffset.y.
         {
-            constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x,
-                                                         kSmallestValidOrigin3D.y - 1, 0};
+            wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x, smallestValidOrigin3D.y - 1,
+                                              0};
             TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0,
-                             kInvalidOrigin3D, {4, 4, 1});
-            TestBothT2TCopies(utils::Expectation::Failure, texture, 0, kInvalidOrigin3D, texture2,
-                              0, {0, 0, 0}, {4, 4, 1});
+                             invalidOrigin3D, {blockWidth, blockHeight, 1});
+            TestBothT2TCopies(utils::Expectation::Failure, texture, 0, invalidOrigin3D, texture2, 0,
+                              {0, 0, 0}, {blockWidth, blockHeight, 1});
         }
     }
 }
@@ -2182,105 +2223,95 @@
 // texture-to-buffer or texture-to-texture copies with compressed texture formats.
 TEST_F(CopyCommandTest_CompressedTextureFormats, ImageExtent) {
     wgpu::Buffer buffer =
-        CreateBuffer(512, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
+        CreateBuffer(1024, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
 
     constexpr uint32_t kMipmapLevels = 3;
-    constexpr uint32_t kTestWidth = 60;
-    constexpr uint32_t kTestHeight = 60;
+    // We choose a prime that is greater than the current max texel dimension size as a multiplier
+    // to compute the test texture size so that we can be certain that its level 2 mipmap (x4)
+    // cannot be a multiple of the dimension. This is useful for testing padding at the edges of
+    // the mipmaps.
+    constexpr uint32_t kBlockPerDim = 13;
 
     for (wgpu::TextureFormat format : utils::kCompressedFormats) {
-        wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
-        wgpu::Texture texture2 = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
+        uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+        uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
+        uint32_t testWidth = blockWidth * kBlockPerDim;
+        uint32_t testHeight = blockHeight * kBlockPerDim;
+        wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
+        wgpu::Texture texture2 = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
 
-        constexpr wgpu::Extent3D kSmallestValidExtent3D = {4, 4, 1};
+        wgpu::Extent3D smallestValidExtent3D = {blockWidth, blockHeight, 1};
 
         // Valid usages of ImageExtent in B2T, T2B and T2T copies with compressed texture formats.
         {
-            TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 8, texture, 0, {0, 0, 0},
-                             kSmallestValidExtent3D);
+            TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 4, texture, 0, {0, 0, 0},
+                             smallestValidExtent3D);
             TestBothT2TCopies(utils::Expectation::Success, texture, 0, {0, 0, 0}, texture2, 0,
-                              {0, 0, 0}, kSmallestValidExtent3D);
+                              {0, 0, 0}, smallestValidExtent3D);
         }
 
         // Valid usages of ImageExtent in B2T, T2B and T2T copies with compressed texture formats
         // and non-zero mipmap levels.
         {
             constexpr uint32_t kTestMipmapLevel = 2;
-            constexpr wgpu::Origin3D kTestOrigin = {
-                (kTestWidth >> kTestMipmapLevel) - kSmallestValidExtent3D.width + 1,
-                (kTestHeight >> kTestMipmapLevel) - kSmallestValidExtent3D.height + 1, 0};
-
+            wgpu::Origin3D testOrigin = {
+                ((testWidth >> kTestMipmapLevel) / blockWidth) * blockWidth,
+                ((testHeight >> kTestMipmapLevel) / blockHeight) * blockHeight, 0};
             TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 4, texture,
-                             kTestMipmapLevel, kTestOrigin, kSmallestValidExtent3D);
-            TestBothT2TCopies(utils::Expectation::Success, texture, kTestMipmapLevel, kTestOrigin,
-                              texture2, 0, {0, 0, 0}, kSmallestValidExtent3D);
+                             kTestMipmapLevel, testOrigin, smallestValidExtent3D);
+            TestBothT2TCopies(utils::Expectation::Success, texture, kTestMipmapLevel, testOrigin,
+                              texture2, 0, {0, 0, 0}, smallestValidExtent3D);
         }
 
         // Failures on invalid ImageExtent.x.
         {
-            constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width - 1,
-                                                         kSmallestValidExtent3D.height, 1};
+            wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width - 1,
+                                              smallestValidExtent3D.height, 1};
             TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0, {0, 0, 0},
-                             kInValidExtent3D);
+                             inValidExtent3D);
             TestBothT2TCopies(utils::Expectation::Failure, texture, 0, {0, 0, 0}, texture2, 0,
-                              {0, 0, 0}, kInValidExtent3D);
+                              {0, 0, 0}, inValidExtent3D);
         }
 
         // Failures on invalid ImageExtent.y.
         {
-            constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width,
-                                                         kSmallestValidExtent3D.height - 1, 1};
+            wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width,
+                                              smallestValidExtent3D.height - 1, 1};
             TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0, {0, 0, 0},
-                             kInValidExtent3D);
+                             inValidExtent3D);
             TestBothT2TCopies(utils::Expectation::Failure, texture, 0, {0, 0, 0}, texture2, 0,
-                              {0, 0, 0}, kInValidExtent3D);
+                              {0, 0, 0}, inValidExtent3D);
         }
     }
 }
 
-// Test copies between buffer and multiple array layers of an uncompressed texture
-TEST_F(CopyCommandTest, CopyToMultipleArrayLayers) {
-    wgpu::Texture destination =
-        CopyCommandTest::Create2DTexture(4, 2, 1, 5, wgpu::TextureFormat::RGBA8Unorm,
-                                         wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
-
-    // Copy to all array layers
-    TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
-                                    {4, 2, 5});
-
-    // Copy to the highest array layer
-    TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 4},
-                                    {4, 2, 1});
-
-    // Copy to array layers in the middle
-    TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
-                                    {4, 2, 3});
-
-    // Copy with a non-packed rowsPerImage
-    TestBothTBCopiesExactBufferSize(256, 3, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
-                                    {4, 2, 5});
-
-    // Copy with bytesPerRow = 512
-    TestBothTBCopiesExactBufferSize(512, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
-                                    {4, 2, 3});
-}
-
 // Test copies between buffer and multiple array layers of a compressed texture
 TEST_F(CopyCommandTest_CompressedTextureFormats, CopyToMultipleArrayLayers) {
+    constexpr uint32_t kWidthMultiplier = 3;
+    constexpr uint32_t kHeightMultiplier = 4;
     for (wgpu::TextureFormat format : utils::kCompressedFormats) {
+        uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+        uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
+        uint32_t testWidth = kWidthMultiplier * blockWidth;
+        uint32_t testHeight = kHeightMultiplier * blockHeight;
         wgpu::Texture texture = CopyCommandTest::Create2DTexture(
-            12, 16, 1, 20, format, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
+            testWidth, testHeight, 1, 20, format,
+            wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
 
         // Copy to all array layers
-        TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 0}, {12, 16, 20});
+        TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 0},
+                                        {testWidth, testHeight, 20});
 
         // Copy to the highest array layer
-        TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 19}, {12, 16, 1});
+        TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 19},
+                                        {testWidth, testHeight, 1});
 
         // Copy to array layers in the middle
-        TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 1}, {12, 16, 18});
+        TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 1},
+                                        {testWidth, testHeight, 18});
 
         // Copy touching the texture corners with a non-packed rowsPerImage
-        TestBothTBCopiesExactBufferSize(256, 6, texture, format, {4, 4, 4}, {8, 12, 16});
+        TestBothTBCopiesExactBufferSize(256, 6, texture, format, {blockWidth, blockHeight, 4},
+                                        {testWidth - blockWidth, testHeight - blockHeight, 16});
     }
 }
diff --git a/src/tests/unittests/validation/QueueWriteTextureValidationTests.cpp b/src/tests/unittests/validation/QueueWriteTextureValidationTests.cpp
index 3f1985b..bb7f4f8 100644
--- a/src/tests/unittests/validation/QueueWriteTextureValidationTests.cpp
+++ b/src/tests/unittests/validation/QueueWriteTextureValidationTests.cpp
@@ -586,25 +586,29 @@
                                                               textOrigin, size);
         }
 
-        static constexpr uint32_t kWidth = 16;
-        static constexpr uint32_t kHeight = 16;
+        static constexpr uint32_t kWidth = 120;
+        static constexpr uint32_t kHeight = 120;
     };
 
     // Tests to verify that data offset may not be a multiple of the compressed texture block size
     TEST_F(WriteTextureTest_CompressedTextureFormats, DataOffset) {
         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
             wgpu::Texture texture = Create2DTexture(format);
+            uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+            uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
 
             // Valid if aligned.
             {
                 uint32_t kAlignedOffset = utils::GetTexelBlockSizeInBytes(format);
-                TestWriteTexture(1024, kAlignedOffset, 256, 4, texture, 0, {0, 0, 0}, {4, 16, 1});
+                TestWriteTexture(1024, kAlignedOffset, 256, 4, texture, 0, {0, 0, 0},
+                                 {blockWidth, blockHeight, 1});
             }
 
             // Still valid if not aligned.
             {
                 uint32_t kUnalignedOffset = utils::GetTexelBlockSizeInBytes(format) - 1;
-                TestWriteTexture(1024, kUnalignedOffset, 256, 4, texture, 0, {0, 0, 0}, {4, 16, 1});
+                TestWriteTexture(1024, kUnalignedOffset, 256, 4, texture, 0, {0, 0, 0},
+                                 {blockWidth, blockHeight, 1});
             }
         }
     }
@@ -613,45 +617,41 @@
     // blockSizeInBytes and that it doesn't have to be a multiple of the compressed
     // texture block width.
     TEST_F(WriteTextureTest_CompressedTextureFormats, BytesPerRow) {
-        constexpr uint32_t kTestWidth = 160;
-        constexpr uint32_t kTestHeight = 160;
-
-        // Failures on the BytesPerRow that is not large enough.
-        {
-            constexpr uint32_t kSmallBytesPerRow = 256;
-            for (wgpu::TextureFormat format : utils::kCompressedFormats) {
-                wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
-                ASSERT_DEVICE_ERROR(TestWriteTexture(1024, 0, kSmallBytesPerRow, 4, texture, 0,
-                                                     {0, 0, 0}, {kTestWidth, 4, 1}));
-            }
-        }
-
-        // Test it is valid to use a BytesPerRow that is not a multiple of 256.
-        {
-            for (wgpu::TextureFormat format : utils::kCompressedFormats) {
-                wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
-                uint32_t ValidBytesPerRow =
-                    kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format);
-                ASSERT_NE(0u, ValidBytesPerRow % 256);
-                TestWriteTexture(1024, 0, ValidBytesPerRow, 4, texture, 0, {0, 0, 0},
-                                 {kTestWidth, 4, 1});
-            }
-        }
+        // Used to compute test width and height.
+        constexpr uint32_t kTestBytesPerRow = 320;
 
         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
-            wgpu::Texture texture = Create2DTexture(format);
+            uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+            uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
+            uint32_t blockByteSize = utils::GetTexelBlockSizeInBytes(format);
+            uint32_t testWidth = kTestBytesPerRow * blockWidth / blockByteSize;
+            uint32_t testHeight = kTestBytesPerRow * blockHeight / blockByteSize;
+            wgpu::Texture texture = Create2DTexture(format, 1, testWidth, testHeight);
+
+            // Failures on the BytesPerRow that is not large enough.
+            {
+                uint32_t kSmallBytesPerRow = kTestBytesPerRow - blockByteSize;
+                ASSERT_DEVICE_ERROR(TestWriteTexture(1024, 0, kSmallBytesPerRow, 4, texture, 0,
+                                                     {0, 0, 0}, {testWidth, blockHeight, 1}));
+            }
+
+            // Test it is valid to use a BytesPerRow that is not a multiple of 256.
+            {
+                TestWriteTexture(1024, 0, kTestBytesPerRow, 4, texture, 0, {0, 0, 0},
+                                 {testWidth, blockHeight, 1});
+            }
 
             // Valid usage of bytesPerRow in WriteTexture with compressed texture formats.
             {
-                constexpr uint32_t kValidBytesPerRow = 20;
-                TestWriteTexture(512, 0, kValidBytesPerRow, 4, texture, 0, {0, 0, 0}, {4, 4, 1});
+                TestWriteTexture(512, 0, blockByteSize, 4, texture, 0, {0, 0, 0},
+                                 {blockWidth, blockHeight, 1});
             }
 
-            // Valid bytesPerRow.
-            // Note that image width is not a multiple of blockWidth.
+            // Valid usage of bytesPerRow in WriteTexture with compressed texture formats. Note that
+            // BytesPerRow is not a multiple of the blockByteSize (but is greater than it).
             {
-                constexpr uint32_t kValidBytesPerRow = 17;
-                TestWriteTexture(512, 0, kValidBytesPerRow, 4, texture, 0, {0, 0, 0}, {4, 4, 1});
+                TestWriteTexture(512, 0, blockByteSize + 1, 4, texture, 0, {0, 0, 0},
+                                 {blockWidth, blockHeight, 1});
             }
         }
     }
@@ -660,24 +660,26 @@
     TEST_F(WriteTextureTest_CompressedTextureFormats, RowsPerImage) {
         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
             wgpu::Texture texture = Create2DTexture(format);
+            uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+            uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
 
             // Valid usages of rowsPerImage in WriteTexture with compressed texture formats.
             {
                 constexpr uint32_t kValidRowsPerImage = 5;
                 TestWriteTexture(1024, 0, 256, kValidRowsPerImage, texture, 0, {0, 0, 0},
-                                 {4, 16, 1});
+                                 {blockWidth, blockHeight * 4, 1});
             }
             {
                 constexpr uint32_t kValidRowsPerImage = 4;
                 TestWriteTexture(1024, 0, 256, kValidRowsPerImage, texture, 0, {0, 0, 0},
-                                 {4, 16, 1});
+                                 {blockWidth, blockHeight * 4, 1});
             }
 
-            // Failure on invalid rowsPerImage.
+            // rowsPerImage is smaller than height.
             {
                 constexpr uint32_t kInvalidRowsPerImage = 3;
                 ASSERT_DEVICE_ERROR(TestWriteTexture(1024, 0, 256, kInvalidRowsPerImage, texture, 0,
-                                                     {0, 0, 0}, {4, 16, 1}));
+                                                     {0, 0, 0}, {blockWidth, blockWidth * 4, 1}));
             }
         }
     }
@@ -688,26 +690,31 @@
         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
             wgpu::Texture texture = Create2DTexture(format);
             wgpu::Texture texture2 = Create2DTexture(format);
+            uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+            uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
 
-            constexpr wgpu::Origin3D kSmallestValidOrigin3D = {4, 4, 0};
+            wgpu::Origin3D smallestValidOrigin3D = {blockWidth, blockHeight, 0};
 
             // Valid usages of ImageOffset in WriteTexture with compressed texture formats.
-            { TestWriteTexture(512, 0, 256, 4, texture, 0, kSmallestValidOrigin3D, {4, 4, 1}); }
+            {
+                TestWriteTexture(512, 0, 256, 4, texture, 0, smallestValidOrigin3D,
+                                 {blockWidth, blockHeight, 1});
+            }
 
             // Failures on invalid ImageOffset.x.
             {
-                constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x - 1,
-                                                             kSmallestValidOrigin3D.y, 0};
-                ASSERT_DEVICE_ERROR(
-                    TestWriteTexture(512, 0, 256, 4, texture, 0, kInvalidOrigin3D, {4, 4, 1}));
+                wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x - 1,
+                                                  smallestValidOrigin3D.y, 0};
+                ASSERT_DEVICE_ERROR(TestWriteTexture(512, 0, 256, 4, texture, 0, invalidOrigin3D,
+                                                     {blockWidth, blockHeight, 1}));
             }
 
             // Failures on invalid ImageOffset.y.
             {
-                constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x,
-                                                             kSmallestValidOrigin3D.y - 1, 0};
-                ASSERT_DEVICE_ERROR(
-                    TestWriteTexture(512, 0, 256, 4, texture, 0, kInvalidOrigin3D, {4, 4, 1}));
+                wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x,
+                                                  smallestValidOrigin3D.y - 1, 0};
+                ASSERT_DEVICE_ERROR(TestWriteTexture(512, 0, 256, 4, texture, 0, invalidOrigin3D,
+                                                     {blockWidth, blockHeight, 1}));
             }
         }
     }
@@ -716,66 +723,83 @@
     // and ImageExtent.y must be a multiple of the compressed texture block height
     TEST_F(WriteTextureTest_CompressedTextureFormats, ImageExtent) {
         constexpr uint32_t kMipmapLevels = 3;
-        constexpr uint32_t kTestWidth = 60;
-        constexpr uint32_t kTestHeight = 60;
+        // We choose a prime that is greater than the current max texel dimension size as a
+        // multiplier to compute the test texture size so that we can be certain that its level 2
+        // mipmap (x4) cannot be a multiple of the dimension. This is useful for testing padding at
+        // the edges of the mipmaps.
+        constexpr uint32_t kBlockPerDim = 13;
 
         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
-            wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
-            wgpu::Texture texture2 =
-                Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
+            uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+            uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
+            uint32_t testWidth = blockWidth * kBlockPerDim;
+            uint32_t testHeight = blockHeight * kBlockPerDim;
+            wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
+            wgpu::Texture texture2 = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
 
-            constexpr wgpu::Extent3D kSmallestValidExtent3D = {4, 4, 1};
+            wgpu::Extent3D smallestValidExtent3D = {blockWidth, blockHeight, 1};
 
             // Valid usages of ImageExtent in WriteTexture with compressed texture formats.
-            { TestWriteTexture(512, 0, 256, 8, texture, 0, {0, 0, 0}, kSmallestValidExtent3D); }
+            { TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, smallestValidExtent3D); }
 
             // Valid usages of ImageExtent in WriteTexture with compressed texture formats
             // and non-zero mipmap levels.
             {
                 constexpr uint32_t kTestMipmapLevel = 2;
-                constexpr wgpu::Origin3D kTestOrigin = {
-                    (kTestWidth >> kTestMipmapLevel) - kSmallestValidExtent3D.width + 1,
-                    (kTestHeight >> kTestMipmapLevel) - kSmallestValidExtent3D.height + 1, 0};
+                wgpu::Origin3D testOrigin = {
+                    ((testWidth >> kTestMipmapLevel) / blockWidth) * blockWidth,
+                    ((testHeight >> kTestMipmapLevel) / blockHeight) * blockHeight, 0};
 
-                TestWriteTexture(512, 0, 256, 4, texture, kTestMipmapLevel, kTestOrigin,
-                                 kSmallestValidExtent3D);
+                TestWriteTexture(512, 0, 256, 4, texture, kTestMipmapLevel, testOrigin,
+                                 smallestValidExtent3D);
             }
 
             // Failures on invalid ImageExtent.x.
             {
-                constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width - 1,
-                                                             kSmallestValidExtent3D.height, 1};
+                wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width - 1,
+                                                  smallestValidExtent3D.height, 1};
                 ASSERT_DEVICE_ERROR(
-                    TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, kInValidExtent3D));
+                    TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, inValidExtent3D));
             }
 
             // Failures on invalid ImageExtent.y.
             {
-                constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width,
-                                                             kSmallestValidExtent3D.height - 1, 1};
+                wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width,
+                                                  smallestValidExtent3D.height - 1, 1};
                 ASSERT_DEVICE_ERROR(
-                    TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, kInValidExtent3D));
+                    TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, inValidExtent3D));
             }
         }
     }
 
     // Test writes to multiple array layers of a compressed texture
     TEST_F(WriteTextureTest_CompressedTextureFormats, WriteToMultipleArrayLayers) {
+        constexpr uint32_t kWidthMultiplier = 3;
+        constexpr uint32_t kHeightMultiplier = 4;
         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
+            uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+            uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
+            uint32_t testWidth = kWidthMultiplier * blockWidth;
+            uint32_t testHeight = kHeightMultiplier * blockHeight;
             wgpu::Texture texture = QueueWriteTextureValidationTest::Create2DTexture(
-                {12, 16, 20}, 1, format, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
+                {testWidth, testHeight, 20}, 1, format,
+                wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
 
             // Write to all array layers
-            TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 0}, {12, 16, 20});
+            TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 0},
+                                          {testWidth, testHeight, 20});
 
             // Write to the highest array layer
-            TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 19}, {12, 16, 1});
+            TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 19},
+                                          {testWidth, testHeight, 1});
 
             // Write to array layers in the middle
-            TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 1}, {12, 16, 18});
+            TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 1},
+                                          {testWidth, testHeight, 18});
 
             // Write touching the texture corners with a non-packed rowsPerImage
-            TestWriteTextureExactDataSize(256, 6, texture, format, {4, 4, 4}, {8, 12, 16});
+            TestWriteTextureExactDataSize(256, 6, texture, format, {blockWidth, blockHeight, 4},
+                                          {testWidth - blockWidth, testHeight - blockHeight, 16});
         }
     }
 
diff --git a/src/tests/unittests/validation/TextureValidationTests.cpp b/src/tests/unittests/validation/TextureValidationTests.cpp
index 5417da6..4a6758f 100644
--- a/src/tests/unittests/validation/TextureValidationTests.cpp
+++ b/src/tests/unittests/validation/TextureValidationTests.cpp
@@ -52,8 +52,10 @@
         wgpu::Queue queue;
 
       private:
-        static constexpr uint32_t kWidth = 32;
-        static constexpr uint32_t kHeight = 32;
+        // Choose the LCM of all current compressed texture format texel dimensions as the
+        // dimensions of the default texture.
+        static constexpr uint32_t kWidth = 120;
+        static constexpr uint32_t kHeight = 120;
         static constexpr uint32_t kDefaultDepth = 1;
         static constexpr uint32_t kDefaultMipLevels = 1;
         static constexpr uint32_t kDefaultSampleCount = 1;
@@ -577,8 +579,16 @@
                 TextureValidationTest::CreateDefaultTextureDescriptor();
             descriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
                                wgpu::TextureUsage::TextureBinding;
+            descriptor.size.width = kWidth;
+            descriptor.size.height = kHeight;
             return descriptor;
         }
+
+      private:
+        // Choose the LCM of all current compressed texture format texel dimensions as the
+        // dimensions of the default texture.
+        static constexpr uint32_t kWidth = 120;
+        static constexpr uint32_t kHeight = 120;
     };
 
     // Test that only CopySrc, CopyDst and Sampled are accepted as usage in compressed formats.
@@ -641,71 +651,51 @@
         }
     }
 
-    // Test that it is invalid to use a number that is not a multiple of 4 (the compressed block
-    // width and height of all BC formats) as the width or height in BC formats.
-    TEST_F(CompressedTextureFormatsValidationTests, BCFormatsTextureSize) {
-        for (wgpu::TextureFormat format : utils::kBCFormats) {
+    // Test that it is invalid to use numbers for a texture's width/height that are not multiples
+    // of the compressed block sizes.
+    TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
+        for (wgpu::TextureFormat format : utils::kCompressedFormats) {
+            uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
+            uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
+
+            // Test that the default size (120 x 120) is valid for all formats.
             {
                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
                 descriptor.format = format;
-                ASSERT_TRUE(descriptor.size.width % 4 == 0 && descriptor.size.height % 4 == 0);
+                ASSERT_TRUE(descriptor.size.width % blockWidth == 0 &&
+                            descriptor.size.height % blockHeight == 0);
                 device.CreateTexture(&descriptor);
             }
 
+            // Test that invalid width should cause an error. Note that if the block width of the
+            // compression type is even, we test that alignment to half the width is not sufficient.
             {
                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
                 descriptor.format = format;
-                descriptor.size.width = 30;
+                descriptor.size.width =
+                    blockWidth % 2 == 0 ? blockWidth - (blockWidth / 2) : blockWidth - 1;
                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
             }
 
+            // Test that invalid width should cause an error. Note that if the block height of the
+            // compression type is even, we test that alignment to half the height is not
+            // sufficient.
             {
                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
                 descriptor.format = format;
-                descriptor.size.height = 30;
+                descriptor.size.height =
+                    blockHeight % 2 == 0 ? blockHeight - (blockHeight / 2) : blockHeight - 1;
                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
             }
 
+            // Test a working dimension based on some constant multipliers to the dimensions.
             {
+                constexpr uint32_t kWidthMultiplier = 3;
+                constexpr uint32_t kHeightMultiplier = 8;
                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
                 descriptor.format = format;
-                descriptor.size.width = 12;
-                descriptor.size.height = 32;
-                device.CreateTexture(&descriptor);
-            }
-        }
-    }
-
-    // Test that it is invalid to use a number that is not a multiple of 4 (the compressed block
-    // width and height of all ETC2 formats) as the width or height in ETC2 formats.
-    TEST_F(CompressedTextureFormatsValidationTests, ETC2FormatsTextureSize) {
-        for (wgpu::TextureFormat format : utils::kETC2Formats) {
-            {
-                wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
-                descriptor.format = format;
-                ASSERT_TRUE(descriptor.size.width % 4 == 0 && descriptor.size.height % 4 == 0);
-                device.CreateTexture(&descriptor);
-            }
-
-            {
-                wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
-                descriptor.format = format;
-                descriptor.size.width = 30;
-                ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
-            }
-
-            {
-                wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
-                descriptor.format = format;
-                descriptor.size.height = 30;
-                ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
-            }
-
-            {
-                wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
-                descriptor.format = format;
-                descriptor.size.width = 12;
-                descriptor.size.height = 32;
+                descriptor.size.width = kWidthMultiplier * blockWidth;
+                descriptor.size.height = kHeightMultiplier * blockHeight;
                 device.CreateTexture(&descriptor);
             }
         }
diff --git a/src/utils/TextureUtils.cpp b/src/utils/TextureUtils.cpp
index 8545a9b..4ff7081 100644
--- a/src/utils/TextureUtils.cpp
+++ b/src/utils/TextureUtils.cpp
@@ -83,7 +83,40 @@
     }
 
     bool IsASTCTextureFormat(wgpu::TextureFormat textureFormat) {
-        return false;
+        switch (textureFormat) {
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+                return true;
+
+            default:
+                return false;
+        }
     }
 
     uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat) {
@@ -167,6 +200,36 @@
             case wgpu::TextureFormat::EACRG11Snorm:
                 return 16u;
 
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+                return 16u;
+
             case wgpu::TextureFormat::Depth24Plus:
             case wgpu::TextureFormat::Depth24PlusStencil8:
 
@@ -248,6 +311,41 @@
             case wgpu::TextureFormat::EACRG11Snorm:
                 return 4u;
 
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+                return 4u;
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+                return 5u;
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+                return 6u;
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+                return 8u;
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+                return 10u;
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+                return 12u;
+
             // Block size of a multi-planar format depends on aspect.
             case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
 
@@ -326,6 +424,41 @@
             case wgpu::TextureFormat::EACRG11Snorm:
                 return 4u;
 
+            case wgpu::TextureFormat::ASTC4x4Unorm:
+            case wgpu::TextureFormat::ASTC4x4UnormSrgb:
+            case wgpu::TextureFormat::ASTC5x4Unorm:
+            case wgpu::TextureFormat::ASTC5x4UnormSrgb:
+                return 4u;
+            case wgpu::TextureFormat::ASTC5x5Unorm:
+            case wgpu::TextureFormat::ASTC5x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC6x5Unorm:
+            case wgpu::TextureFormat::ASTC6x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x5Unorm:
+            case wgpu::TextureFormat::ASTC8x5UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x5Unorm:
+            case wgpu::TextureFormat::ASTC10x5UnormSrgb:
+                return 5u;
+            case wgpu::TextureFormat::ASTC6x6Unorm:
+            case wgpu::TextureFormat::ASTC6x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC8x6Unorm:
+            case wgpu::TextureFormat::ASTC8x6UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x6Unorm:
+            case wgpu::TextureFormat::ASTC10x6UnormSrgb:
+                return 6u;
+            case wgpu::TextureFormat::ASTC8x8Unorm:
+            case wgpu::TextureFormat::ASTC8x8UnormSrgb:
+            case wgpu::TextureFormat::ASTC10x8Unorm:
+            case wgpu::TextureFormat::ASTC10x8UnormSrgb:
+                return 8u;
+            case wgpu::TextureFormat::ASTC10x10Unorm:
+            case wgpu::TextureFormat::ASTC10x10UnormSrgb:
+            case wgpu::TextureFormat::ASTC12x10Unorm:
+            case wgpu::TextureFormat::ASTC12x10UnormSrgb:
+                return 10u;
+            case wgpu::TextureFormat::ASTC12x12Unorm:
+            case wgpu::TextureFormat::ASTC12x12UnormSrgb:
+                return 12u;
+
             // Block size of a multi-planar format depends on aspect.
             case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
 
diff --git a/src/utils/TextureUtils.h b/src/utils/TextureUtils.h
index bfd9550..9c570c2 100644
--- a/src/utils/TextureUtils.h
+++ b/src/utils/TextureUtils.h
@@ -22,7 +22,7 @@
 #include "common/Assert.h"
 
 namespace utils {
-    static constexpr std::array<wgpu::TextureFormat, 63> kAllTextureFormats = {
+    static constexpr std::array<wgpu::TextureFormat, 91> kAllTextureFormats = {
         wgpu::TextureFormat::R8Unorm,
         wgpu::TextureFormat::R8Snorm,
         wgpu::TextureFormat::R8Uint,
@@ -85,7 +85,35 @@
         wgpu::TextureFormat::EACR11Unorm,
         wgpu::TextureFormat::EACR11Snorm,
         wgpu::TextureFormat::EACRG11Unorm,
-        wgpu::TextureFormat::EACRG11Snorm};
+        wgpu::TextureFormat::EACRG11Snorm,
+        wgpu::TextureFormat::ASTC4x4Unorm,
+        wgpu::TextureFormat::ASTC4x4UnormSrgb,
+        wgpu::TextureFormat::ASTC5x4Unorm,
+        wgpu::TextureFormat::ASTC5x4UnormSrgb,
+        wgpu::TextureFormat::ASTC5x5Unorm,
+        wgpu::TextureFormat::ASTC5x5UnormSrgb,
+        wgpu::TextureFormat::ASTC6x5Unorm,
+        wgpu::TextureFormat::ASTC6x5UnormSrgb,
+        wgpu::TextureFormat::ASTC6x6Unorm,
+        wgpu::TextureFormat::ASTC6x6UnormSrgb,
+        wgpu::TextureFormat::ASTC8x5Unorm,
+        wgpu::TextureFormat::ASTC8x5UnormSrgb,
+        wgpu::TextureFormat::ASTC8x6Unorm,
+        wgpu::TextureFormat::ASTC8x6UnormSrgb,
+        wgpu::TextureFormat::ASTC8x8Unorm,
+        wgpu::TextureFormat::ASTC8x8UnormSrgb,
+        wgpu::TextureFormat::ASTC10x5Unorm,
+        wgpu::TextureFormat::ASTC10x5UnormSrgb,
+        wgpu::TextureFormat::ASTC10x6Unorm,
+        wgpu::TextureFormat::ASTC10x6UnormSrgb,
+        wgpu::TextureFormat::ASTC10x8Unorm,
+        wgpu::TextureFormat::ASTC10x8UnormSrgb,
+        wgpu::TextureFormat::ASTC10x10Unorm,
+        wgpu::TextureFormat::ASTC10x10UnormSrgb,
+        wgpu::TextureFormat::ASTC12x10Unorm,
+        wgpu::TextureFormat::ASTC12x10UnormSrgb,
+        wgpu::TextureFormat::ASTC12x12Unorm,
+        wgpu::TextureFormat::ASTC12x12UnormSrgb};
 
     static constexpr std::array<wgpu::TextureFormat, 14> kBCFormats = {
         wgpu::TextureFormat::BC1RGBAUnorm,  wgpu::TextureFormat::BC1RGBAUnormSrgb,
@@ -103,10 +131,24 @@
         wgpu::TextureFormat::EACR11Unorm,     wgpu::TextureFormat::EACR11Snorm,
         wgpu::TextureFormat::EACRG11Unorm,    wgpu::TextureFormat::EACRG11Snorm};
 
-    // TODO(crbug.com/dawn/955) Add formats once implemented.
-    static constexpr std::array<wgpu::TextureFormat, 0> kASTCFormats = {};
+    static constexpr std::array<wgpu::TextureFormat, 28> kASTCFormats = {
+        wgpu::TextureFormat::ASTC4x4Unorm,   wgpu::TextureFormat::ASTC4x4UnormSrgb,
+        wgpu::TextureFormat::ASTC5x4Unorm,   wgpu::TextureFormat::ASTC5x4UnormSrgb,
+        wgpu::TextureFormat::ASTC5x5Unorm,   wgpu::TextureFormat::ASTC5x5UnormSrgb,
+        wgpu::TextureFormat::ASTC6x5Unorm,   wgpu::TextureFormat::ASTC6x5UnormSrgb,
+        wgpu::TextureFormat::ASTC6x6Unorm,   wgpu::TextureFormat::ASTC6x6UnormSrgb,
+        wgpu::TextureFormat::ASTC8x5Unorm,   wgpu::TextureFormat::ASTC8x5UnormSrgb,
+        wgpu::TextureFormat::ASTC8x6Unorm,   wgpu::TextureFormat::ASTC8x6UnormSrgb,
+        wgpu::TextureFormat::ASTC8x8Unorm,   wgpu::TextureFormat::ASTC8x8UnormSrgb,
+        wgpu::TextureFormat::ASTC10x5Unorm,  wgpu::TextureFormat::ASTC10x5UnormSrgb,
+        wgpu::TextureFormat::ASTC10x6Unorm,  wgpu::TextureFormat::ASTC10x6UnormSrgb,
+        wgpu::TextureFormat::ASTC10x8Unorm,  wgpu::TextureFormat::ASTC10x8UnormSrgb,
+        wgpu::TextureFormat::ASTC10x10Unorm, wgpu::TextureFormat::ASTC10x10UnormSrgb,
+        wgpu::TextureFormat::ASTC12x10Unorm, wgpu::TextureFormat::ASTC12x10UnormSrgb,
+        wgpu::TextureFormat::ASTC12x12Unorm, wgpu::TextureFormat::ASTC12x12UnormSrgb,
+    };
 
-    static constexpr std::array<wgpu::TextureFormat, 24> kCompressedFormats = {
+    static constexpr std::array<wgpu::TextureFormat, 52> kCompressedFormats = {
         wgpu::TextureFormat::BC1RGBAUnorm,    wgpu::TextureFormat::BC1RGBAUnormSrgb,
         wgpu::TextureFormat::BC2RGBAUnorm,    wgpu::TextureFormat::BC2RGBAUnormSrgb,
         wgpu::TextureFormat::BC3RGBAUnorm,    wgpu::TextureFormat::BC3RGBAUnormSrgb,
@@ -118,7 +160,21 @@
         wgpu::TextureFormat::ETC2RGB8A1Unorm, wgpu::TextureFormat::ETC2RGB8A1UnormSrgb,
         wgpu::TextureFormat::ETC2RGBA8Unorm,  wgpu::TextureFormat::ETC2RGBA8UnormSrgb,
         wgpu::TextureFormat::EACR11Unorm,     wgpu::TextureFormat::EACR11Snorm,
-        wgpu::TextureFormat::EACRG11Unorm,    wgpu::TextureFormat::EACRG11Snorm};
+        wgpu::TextureFormat::EACRG11Unorm,    wgpu::TextureFormat::EACRG11Snorm,
+        wgpu::TextureFormat::ASTC4x4Unorm,    wgpu::TextureFormat::ASTC4x4UnormSrgb,
+        wgpu::TextureFormat::ASTC5x4Unorm,    wgpu::TextureFormat::ASTC5x4UnormSrgb,
+        wgpu::TextureFormat::ASTC5x5Unorm,    wgpu::TextureFormat::ASTC5x5UnormSrgb,
+        wgpu::TextureFormat::ASTC6x5Unorm,    wgpu::TextureFormat::ASTC6x5UnormSrgb,
+        wgpu::TextureFormat::ASTC6x6Unorm,    wgpu::TextureFormat::ASTC6x6UnormSrgb,
+        wgpu::TextureFormat::ASTC8x5Unorm,    wgpu::TextureFormat::ASTC8x5UnormSrgb,
+        wgpu::TextureFormat::ASTC8x6Unorm,    wgpu::TextureFormat::ASTC8x6UnormSrgb,
+        wgpu::TextureFormat::ASTC8x8Unorm,    wgpu::TextureFormat::ASTC8x8UnormSrgb,
+        wgpu::TextureFormat::ASTC10x5Unorm,   wgpu::TextureFormat::ASTC10x5UnormSrgb,
+        wgpu::TextureFormat::ASTC10x6Unorm,   wgpu::TextureFormat::ASTC10x6UnormSrgb,
+        wgpu::TextureFormat::ASTC10x8Unorm,   wgpu::TextureFormat::ASTC10x8UnormSrgb,
+        wgpu::TextureFormat::ASTC10x10Unorm,  wgpu::TextureFormat::ASTC10x10UnormSrgb,
+        wgpu::TextureFormat::ASTC12x10Unorm,  wgpu::TextureFormat::ASTC12x10UnormSrgb,
+        wgpu::TextureFormat::ASTC12x12Unorm,  wgpu::TextureFormat::ASTC12x12UnormSrgb};
     static_assert(kCompressedFormats.size() ==
                       kBCFormats.size() + kETC2Formats.size() + kASTCFormats.size(),
                   "Number of compressed format must equal number of BC, ETC2, and ASTC formats.");