Test all formats used as readonly storage texture in StorageTextureTests

This patch changes all the tests related to read-only storage textures
in dawn_end2end_tests StorageTextureTests to make them test all the
texture formats that support being used as storage textures in WebGPU.

BUG=dawn:267
TEST=dawn_end2end_tests

Change-Id: I4d6ddbee638a787a2dcfc626bd4963a9b9043772
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22640
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/tests/end2end/CompressedTextureFormatTests.cpp b/src/tests/end2end/CompressedTextureFormatTests.cpp
index b29729a..0845ad8 100644
--- a/src/tests/end2end/CompressedTextureFormatTests.cpp
+++ b/src/tests/end2end/CompressedTextureFormatTests.cpp
@@ -18,6 +18,7 @@
 #include "common/Constants.h"
 #include "common/Math.h"
 #include "utils/ComboRenderPipelineDescriptor.h"
+#include "utils/TextureFormatUtils.h"
 #include "utils/WGPUHelpers.h"
 
 // The helper struct to configure the copies between buffers and textures.
@@ -66,7 +67,7 @@
         } else {
             bufferRowPitchInBytes =
                 copyWidthInBlockAtLevel *
-                CompressedFormatBlockSizeInBytes(copyConfig.textureDescriptor.format);
+                utils::GetTexelBlockSizeInBytes(copyConfig.textureDescriptor.format);
         }
         uint32_t uploadBufferSize =
             copyConfig.bufferOffset + bufferRowPitchInBytes * copyHeightInBlockAtLevel;
@@ -259,31 +260,6 @@
         return dstTexture;
     }
 
-    // Return the BC block size in bytes.
-    static uint32_t CompressedFormatBlockSizeInBytes(wgpu::TextureFormat format) {
-        switch (format) {
-            case wgpu::TextureFormat::BC1RGBAUnorm:
-            case wgpu::TextureFormat::BC1RGBAUnormSrgb:
-            case wgpu::TextureFormat::BC4RSnorm:
-            case wgpu::TextureFormat::BC4RUnorm:
-                return 8;
-            case wgpu::TextureFormat::BC2RGBAUnorm:
-            case wgpu::TextureFormat::BC2RGBAUnormSrgb:
-            case wgpu::TextureFormat::BC3RGBAUnorm:
-            case wgpu::TextureFormat::BC3RGBAUnormSrgb:
-            case wgpu::TextureFormat::BC5RGSnorm:
-            case wgpu::TextureFormat::BC5RGUnorm:
-            case wgpu::TextureFormat::BC6HRGBSfloat:
-            case wgpu::TextureFormat::BC6HRGBUfloat:
-            case wgpu::TextureFormat::BC7RGBAUnorm:
-            case wgpu::TextureFormat::BC7RGBAUnormSrgb:
-                return 16;
-            default:
-                UNREACHABLE();
-                return 0;
-        }
-    }
-
     // Return the pre-prepared one-block BC texture data.
     static std::vector<uint8_t> GetOneBlockBCFormatTextureData(wgpu::TextureFormat bcFormat) {
         switch (bcFormat) {
@@ -841,7 +817,7 @@
     for (wgpu::TextureFormat format : kBCFormats) {
         config.textureDescriptor.format = format;
 
-        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
+        const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
         const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
 
         config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes;
@@ -877,7 +853,7 @@
     for (wgpu::TextureFormat format : kBCFormats) {
         config.textureDescriptor.format = format;
 
-        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
+        const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
         const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
 
         config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes +
@@ -911,7 +887,7 @@
     for (wgpu::TextureFormat format : kBCFormats) {
         config.textureDescriptor.format = format;
 
-        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
+        const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
         const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
         config.bufferOffset =
             (blockCountPerRowPitch - blockCountPerRow + kExceedRowBlockCount) * blockSizeInBytes;
@@ -941,7 +917,7 @@
     for (wgpu::TextureFormat format : kBCFormats) {
         config.textureDescriptor.format = format;
 
-        const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format);
+        const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
         const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
 
         config.bufferOffset =
diff --git a/src/tests/end2end/StorageTextureTests.cpp b/src/tests/end2end/StorageTextureTests.cpp
index 799f9ec..1cd8fe1 100644
--- a/src/tests/end2end/StorageTextureTests.cpp
+++ b/src/tests/end2end/StorageTextureTests.cpp
@@ -16,17 +16,309 @@
 
 #include "common/Assert.h"
 #include "common/Constants.h"
+#include "common/Math.h"
 #include "utils/ComboRenderPipelineDescriptor.h"
+#include "utils/TextureFormatUtils.h"
 #include "utils/WGPUHelpers.h"
 
 class StorageTextureTests : public DawnTest {
   public:
-    // TODO(jiawei.shao@intel.com): support all formats that can be used in storage textures.
-    static std::vector<uint32_t> GetExpectedData(uint32_t arrayLayerCount = 1) {
-        constexpr size_t kDataCountPerLayer = kWidth * kHeight;
-        std::vector<uint32_t> outputData(kDataCountPerLayer * arrayLayerCount);
-        for (uint32_t i = 0; i < outputData.size(); ++i) {
-            outputData[i] = i + 1u;
+    static void FillExpectedData(void* pixelValuePtr,
+                                 wgpu::TextureFormat format,
+                                 uint32_t x,
+                                 uint32_t y,
+                                 uint32_t arrayLayer) {
+        const uint32_t pixelValue = 1 + x + kWidth * (y + kHeight * arrayLayer);
+        ASSERT(pixelValue <= 255u / 4);
+
+        switch (format) {
+            // 32-bit unsigned integer formats
+            case wgpu::TextureFormat::R32Uint: {
+                uint32_t* valuePtr = static_cast<uint32_t*>(pixelValuePtr);
+                *valuePtr = pixelValue;
+                break;
+            }
+
+            case wgpu::TextureFormat::RG32Uint: {
+                uint32_t* valuePtr = static_cast<uint32_t*>(pixelValuePtr);
+                valuePtr[0] = pixelValue;
+                valuePtr[1] = pixelValue * 2;
+                break;
+            }
+
+            case wgpu::TextureFormat::RGBA32Uint: {
+                uint32_t* valuePtr = static_cast<uint32_t*>(pixelValuePtr);
+                valuePtr[0] = pixelValue;
+                valuePtr[1] = pixelValue * 2;
+                valuePtr[2] = pixelValue * 3;
+                valuePtr[3] = pixelValue * 4;
+                break;
+            }
+
+            // 32-bit signed integer formats
+            case wgpu::TextureFormat::R32Sint: {
+                int32_t* valuePtr = static_cast<int32_t*>(pixelValuePtr);
+                *valuePtr = static_cast<int32_t>(pixelValue);
+                break;
+            }
+
+            case wgpu::TextureFormat::RG32Sint: {
+                int32_t* valuePtr = static_cast<int32_t*>(pixelValuePtr);
+                valuePtr[0] = static_cast<int32_t>(pixelValue);
+                valuePtr[1] = -static_cast<int32_t>(pixelValue);
+                break;
+            }
+
+            case wgpu::TextureFormat::RGBA32Sint: {
+                int32_t* valuePtr = static_cast<int32_t*>(pixelValuePtr);
+                valuePtr[0] = static_cast<int32_t>(pixelValue);
+                valuePtr[1] = -static_cast<int32_t>(pixelValue);
+                valuePtr[2] = static_cast<int32_t>(pixelValue * 2);
+                valuePtr[3] = -static_cast<int32_t>(pixelValue * 2);
+                break;
+            }
+
+            // 32-bit float formats
+            case wgpu::TextureFormat::R32Float: {
+                float_t* valuePtr = static_cast<float_t*>(pixelValuePtr);
+                *valuePtr = static_cast<float_t>(pixelValue * 1.1f);
+                break;
+            }
+
+            case wgpu::TextureFormat::RG32Float: {
+                float_t* valuePtr = static_cast<float_t*>(pixelValuePtr);
+                valuePtr[0] = static_cast<float_t>(pixelValue * 1.1f);
+                valuePtr[1] = -static_cast<float_t>(pixelValue * 2.2f);
+                break;
+            }
+
+            case wgpu::TextureFormat::RGBA32Float: {
+                float_t* valuePtr = static_cast<float_t*>(pixelValuePtr);
+                valuePtr[0] = static_cast<float_t>(pixelValue * 1.1f);
+                valuePtr[1] = -static_cast<float_t>(pixelValue * 1.1f);
+                valuePtr[2] = static_cast<float_t>(pixelValue * 2.2f);
+                valuePtr[3] = -static_cast<float_t>(pixelValue * 2.2f);
+                break;
+            }
+
+            // 16-bit (unsigned integer, signed integer and float) 4-component formats
+            case wgpu::TextureFormat::RGBA16Uint: {
+                uint16_t* valuePtr = static_cast<uint16_t*>(pixelValuePtr);
+                valuePtr[0] = static_cast<uint16_t>(pixelValue);
+                valuePtr[1] = static_cast<uint16_t>(pixelValue * 2);
+                valuePtr[2] = static_cast<uint16_t>(pixelValue * 3);
+                valuePtr[3] = static_cast<uint16_t>(pixelValue * 4);
+                break;
+            }
+            case wgpu::TextureFormat::RGBA16Sint: {
+                int16_t* valuePtr = static_cast<int16_t*>(pixelValuePtr);
+                valuePtr[0] = static_cast<int16_t>(pixelValue);
+                valuePtr[1] = -static_cast<int16_t>(pixelValue);
+                valuePtr[2] = static_cast<int16_t>(pixelValue * 2);
+                valuePtr[3] = -static_cast<int16_t>(pixelValue * 2);
+                break;
+            }
+
+            case wgpu::TextureFormat::RGBA16Float: {
+                uint16_t* valuePtr = static_cast<uint16_t*>(pixelValuePtr);
+                valuePtr[0] = Float32ToFloat16(static_cast<float_t>(pixelValue));
+                valuePtr[1] = Float32ToFloat16(-static_cast<float_t>(pixelValue));
+                valuePtr[2] = Float32ToFloat16(static_cast<float_t>(pixelValue * 2));
+                valuePtr[3] = Float32ToFloat16(-static_cast<float_t>(pixelValue * 2));
+                break;
+            }
+
+            // 8-bit (normalized/non-normalized signed/unsigned integer) 4-component formats
+            case wgpu::TextureFormat::RGBA8Unorm:
+            case wgpu::TextureFormat::RGBA8Uint: {
+                RGBA8* valuePtr = static_cast<RGBA8*>(pixelValuePtr);
+                *valuePtr = RGBA8(pixelValue, pixelValue * 2, pixelValue * 3, pixelValue * 4);
+                break;
+            }
+
+            case wgpu::TextureFormat::RGBA8Snorm:
+            case wgpu::TextureFormat::RGBA8Sint: {
+                int8_t* valuePtr = static_cast<int8_t*>(pixelValuePtr);
+                valuePtr[0] = static_cast<int8_t>(pixelValue);
+                valuePtr[1] = -static_cast<int8_t>(pixelValue);
+                valuePtr[2] = static_cast<int8_t>(pixelValue) * 2;
+                valuePtr[3] = -static_cast<int8_t>(pixelValue) * 2;
+                break;
+            }
+
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+
+    std::string GetGLSLImageDeclaration(wgpu::TextureFormat format,
+                                        std::string accessQualifier,
+                                        bool is2DArray) {
+        std::ostringstream ostream;
+        ostream << "layout(set = 0, binding = 0, " << utils::GetGLSLImageFormatQualifier(format)
+                << ") uniform " << accessQualifier << " "
+                << utils::GetColorTextureComponentTypePrefix(format) << "image2D";
+        if (is2DArray) {
+            ostream << "Array";
+        }
+        ostream << " storageImage;";
+        return ostream.str();
+    }
+
+    const char* GetExpectedPixelValue(wgpu::TextureFormat format) {
+        switch (format) {
+            // non-normalized unsigned integer formats
+            case wgpu::TextureFormat::R32Uint:
+                return "uvec4(value, 0, 0, 1u)";
+
+            case wgpu::TextureFormat::RG32Uint:
+                return "uvec4(value, value * 2, 0, 1);";
+
+            case wgpu::TextureFormat::RGBA8Uint:
+            case wgpu::TextureFormat::RGBA16Uint:
+            case wgpu::TextureFormat::RGBA32Uint:
+                return "uvec4(value, value * 2, value * 3, value * 4);";
+
+            // non-normalized signed integer formats
+            case wgpu::TextureFormat::R32Sint:
+                return "ivec4(value, 0, 0, 1)";
+
+            case wgpu::TextureFormat::RG32Sint:
+                return "ivec4(value, -value, 0, 1);";
+
+            case wgpu::TextureFormat::RGBA8Sint:
+            case wgpu::TextureFormat::RGBA16Sint:
+            case wgpu::TextureFormat::RGBA32Sint:
+                return "ivec4(value, -value, value * 2, -value * 2);";
+
+            // float formats
+            case wgpu::TextureFormat::R32Float:
+                return "vec4(value * 1.1f, 0, 0, 1);";
+
+            case wgpu::TextureFormat::RG32Float:
+                return "vec4(value * 1.1f, -(value * 2.2f), 0, 1);";
+
+            case wgpu::TextureFormat::RGBA16Float:
+                return "vec4(value, -float(value), float(value * 2), -float(value * 2));";
+
+            case wgpu::TextureFormat::RGBA32Float:
+                return "vec4(value * 1.1f, -(value * 1.1f), value * 2.2f, -(value * 2.2f));";
+
+            // normalized signed/unsigned integer formats
+            case wgpu::TextureFormat::RGBA8Unorm:
+                return "vec4(value / 255.0, value / 255.0 * 2, value / 255.0 * 3, value / 255.0 * "
+                       "4);";
+
+            case wgpu::TextureFormat::RGBA8Snorm:
+                return "vec4(value / 127.0, -(value / 127.0), (value * 2 / 127.0), -(value * 2 / "
+                       "127.0));";
+
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+
+    const char* GetGLSLComparisonFunction(wgpu::TextureFormat format) {
+        switch (format) {
+            // non-normalized unsigned integer formats
+            case wgpu::TextureFormat::R32Uint:
+            case wgpu::TextureFormat::RG32Uint:
+            case wgpu::TextureFormat::RGBA8Uint:
+            case wgpu::TextureFormat::RGBA16Uint:
+            case wgpu::TextureFormat::RGBA32Uint:
+                return R"(bool IsEqualTo(uvec4 pixel, uvec4 expected) {
+                              return pixel == expected;
+                       })";
+
+            // non-normalized signed integer formats
+            case wgpu::TextureFormat::R32Sint:
+            case wgpu::TextureFormat::RG32Sint:
+            case wgpu::TextureFormat::RGBA8Sint:
+            case wgpu::TextureFormat::RGBA16Sint:
+            case wgpu::TextureFormat::RGBA32Sint:
+                return R"(bool IsEqualTo(ivec4 pixel, ivec4 expected) {
+                              return pixel == expected;
+                       })";
+
+            // float formats
+            case wgpu::TextureFormat::R32Float:
+            case wgpu::TextureFormat::RG32Float:
+            case wgpu::TextureFormat::RGBA16Float:
+            case wgpu::TextureFormat::RGBA32Float:
+                return R"(bool IsEqualTo(vec4 pixel, vec4 expected) {
+                              return pixel == expected;
+                       })";
+
+            // normalized signed/unsigned integer formats
+            case wgpu::TextureFormat::RGBA8Unorm:
+            case wgpu::TextureFormat::RGBA8Snorm:
+                // On Windows Intel drivers the tests will fail if tolerance <= 0.00000001f.
+                return R"(bool IsEqualTo(vec4 pixel, vec4 expected) {
+                              const float tolerance = 0.0000001f;
+                              return all(lessThan(abs(pixel - expected), vec4(tolerance)));
+                       })";
+
+            default:
+                UNREACHABLE();
+                break;
+        }
+
+        return "";
+    }
+
+    std::string CommonReadOnlyTestCode(wgpu::TextureFormat format, bool is2DArray = false) {
+        std::ostringstream ostream;
+
+        const char* prefix = utils::GetColorTextureComponentTypePrefix(format);
+
+        ostream << GetGLSLImageDeclaration(format, "readonly", is2DArray) << "\n"
+                << GetGLSLComparisonFunction(format) << "bool doTest() {\n";
+        if (is2DArray) {
+            ostream << R"(ivec3 size = imageSize(storageImage);
+                          const uint layerCount = size.z;)";
+        } else {
+            ostream << R"(ivec2 size = imageSize(storageImage);
+                          const uint layerCount = 1;)";
+        }
+        ostream << R"(for (uint layer = 0; layer < layerCount; ++layer) {
+                          for (uint y = 0; y < size.y; ++y) {
+                              for (uint x = 0; x < size.x; ++x) {
+                                  uint value = 1 + x + size.x * (y + size.y * layer);
+                     )"
+                << prefix << "vec4 expected = " << GetExpectedPixelValue(format) << ";\n"
+                << prefix << R"(vec4 pixel = imageLoad(storageImage, )";
+        if (is2DArray) {
+            ostream << "ivec3(x, y, layer));";
+        } else {
+            ostream << "ivec2(x, y));";
+        }
+        ostream << R"(
+                                  if (!IsEqualTo(pixel, expected)) {
+                                      return false;
+                                  }
+                              }
+                          }
+                      }
+                      return true;
+                   })";
+
+        return ostream.str();
+    }
+
+    static std::vector<uint8_t> GetExpectedData(wgpu::TextureFormat format,
+                                                uint32_t arrayLayerCount = 1) {
+        const uint32_t texelSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
+
+        std::vector<uint8_t> outputData(texelSizeInBytes * kWidth * kHeight * arrayLayerCount);
+
+        for (uint32_t i = 0; i < outputData.size() / texelSizeInBytes; ++i) {
+            uint8_t* pixelValuePtr = &outputData[i * texelSizeInBytes];
+            const uint32_t x = i % kWidth;
+            const uint32_t y = (i % (kWidth * kHeight)) / kWidth;
+            const uint32_t arrayLayer = i / (kWidth * kHeight);
+            FillExpectedData(pixelValuePtr, format, x, y, arrayLayer);
         }
 
         return outputData;
@@ -55,24 +347,27 @@
         return device.CreateBuffer(&descriptor);
     }
 
-    // TODO(jiawei.shao@intel.com): support all formats that can be used in storage textures.
-    wgpu::Texture CreateTextureWithTestData(const std::vector<uint32_t>& initialTextureData,
-                                            uint32_t texelSize) {
+    wgpu::Texture CreateTextureWithTestData(const std::vector<uint8_t>& initialTextureData,
+                                            wgpu::TextureFormat format) {
+        uint32_t texelSize = utils::GetTexelBlockSizeInBytes(format);
         ASSERT(kWidth * texelSize <= kTextureBytesPerRowAlignment);
 
+        const uint32_t bytesPerTextureRow = texelSize * kWidth;
         const uint32_t arrayLayerCount =
-            static_cast<uint32_t>(initialTextureData.size() / (kWidth * kHeight));
+            static_cast<uint32_t>(initialTextureData.size() / texelSize / (kWidth * kHeight));
         const size_t uploadBufferSize =
-            kTextureBytesPerRowAlignment * (kHeight * arrayLayerCount - 1) + kWidth * texelSize;
+            kTextureBytesPerRowAlignment * (kHeight * arrayLayerCount - 1) +
+            kWidth * bytesPerTextureRow;
 
-        std::vector<uint32_t> uploadBufferData(uploadBufferSize / texelSize);
-        const size_t texelCountPerRow = kTextureBytesPerRowAlignment / texelSize;
+        std::vector<uint8_t> uploadBufferData(uploadBufferSize);
         for (uint32_t layer = 0; layer < arrayLayerCount; ++layer) {
-            const size_t initialDataOffset = kWidth * kHeight * layer;
+            const size_t initialDataOffset = bytesPerTextureRow * kHeight * layer;
             for (size_t y = 0; y < kHeight; ++y) {
-                for (size_t x = 0; x < kWidth; ++x) {
-                    uint32_t data = initialTextureData[initialDataOffset + kWidth * y + x];
-                    size_t indexInUploadBuffer = (kHeight * layer + y) * texelCountPerRow + x;
+                for (size_t x = 0; x < bytesPerTextureRow; ++x) {
+                    uint8_t data =
+                        initialTextureData[initialDataOffset + bytesPerTextureRow * y + x];
+                    size_t indexInUploadBuffer =
+                        (kHeight * layer + y) * kTextureBytesPerRowAlignment + x;
                     uploadBufferData[indexInUploadBuffer] = data;
                 }
             }
@@ -81,9 +376,9 @@
             utils::CreateBufferFromData(device, uploadBufferData.data(), uploadBufferSize,
                                         wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
 
-        wgpu::Texture outputTexture = CreateTexture(
-            wgpu::TextureFormat::R32Uint, wgpu::TextureUsage::Storage | wgpu::TextureUsage::CopyDst,
-            kWidth, kHeight, arrayLayerCount);
+        wgpu::Texture outputTexture =
+            CreateTexture(format, wgpu::TextureUsage::Storage | wgpu::TextureUsage::CopyDst, kWidth,
+                          kHeight, arrayLayerCount);
 
         const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1};
 
@@ -235,10 +530,10 @@
 
     void CheckOutputStorageTexture(wgpu::Texture writeonlyStorageTexture,
                                    uint32_t texelSize,
-                                   const std::vector<uint32_t>& expectedData) {
+                                   const std::vector<uint8_t>& expectedData) {
         // Copy the content from the write-only storage texture to the result buffer.
         const uint32_t arrayLayerCount =
-            static_cast<uint32_t>(expectedData.size() / (kWidth * kHeight));
+            static_cast<uint32_t>(expectedData.size() / texelSize / (kWidth * kHeight));
         wgpu::Buffer resultBuffer = CreateEmptyBufferForTextureCopy(texelSize, arrayLayerCount);
 
         const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1};
@@ -266,9 +561,10 @@
             for (size_t y = 0; y < kHeight; ++y) {
                 const size_t resultBufferOffset =
                     kTextureBytesPerRowAlignment * (kHeight * layer + y);
-                const size_t expectedDataOffset = kWidth * (kHeight * layer + y);
-                EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data() + expectedDataOffset, resultBuffer,
-                                           resultBufferOffset, kWidth);
+                const size_t expectedDataOffset = texelSize * kWidth * (kHeight * layer + y);
+                EXPECT_BUFFER_U32_RANGE_EQ(
+                    reinterpret_cast<const uint32_t*>(expectedData.data() + expectedDataOffset),
+                    resultBuffer, resultBufferOffset, kWidth);
             }
         }
     }
@@ -284,20 +580,6 @@
             gl_PointSize = 1.0f;
         })";
 
-    const char* kCommonReadOnlyTestCode_uimage2D = R"(
-        bool doTest() {
-            for (uint y = 0; y < 4; ++y) {
-                for (uint x = 0; x < 4; ++x) {
-                    uvec4 expected = uvec4(1u + x + y * 4u, 0, 0, 1u);
-                    uvec4 pixel = imageLoad(srcImage, ivec2(x, y));
-                    if (pixel != expected) {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        })";
-
     const char* kCommonWriteOnlyTestCode_uimage2D = R"(
         #version 450
         layout(set = 0, binding = 0, r32ui) uniform writeonly uimage2D dstImage;
@@ -348,23 +630,27 @@
     // bug in spvc parser is fixed.
     DAWN_SKIP_TEST_IF(IsD3D12() && IsSpvcParserBeingUsed());
 
-    // Prepare the read-only storage texture and fill it with the expected data.
-    // TODO(jiawei.shao@intel.com): test more texture formats.
-    constexpr uint32_t kTexelSizeR32Uint = 4u;
-    const std::vector<uint32_t> kInitialTextureData = GetExpectedData();
-    wgpu::Texture readonlyStorageTexture =
-        CreateTextureWithTestData(kInitialTextureData, kTexelSizeR32Uint);
+    for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
+        if (!utils::TextureFormatSupportsStorageTexture(format)) {
+            continue;
+        }
 
-    // Create a compute shader that reads the pixels from the read-only storage texture and writes 1
-    // to DstBuffer if they all have to expected value.
-    const std::string kComputeShader = std::string(R"(
-        #version 450
-        layout (set = 0, binding = 0, r32ui) uniform readonly uimage2D srcImage;
-        layout (set = 0, binding = 1, std430) buffer DstBuffer {
-            uint result;
-        } dstBuffer;)") + kCommonReadOnlyTestCode_uimage2D +
-                                       R"(
-        void main() {
+        // Prepare the read-only storage texture and fill it with the expected data.
+        const std::vector<uint8_t> kInitialTextureData = GetExpectedData(format);
+        wgpu::Texture readonlyStorageTexture =
+            CreateTextureWithTestData(kInitialTextureData, format);
+
+        // Create a compute shader that reads the pixels from the read-only storage texture and
+        // writes 1 to DstBuffer if they all have to expected value.
+        std::ostringstream csStream;
+        csStream << R"(
+            #version 450
+            layout(set = 0, binding = 1, std430) buffer DstBuffer {
+                uint result;
+            } dstBuffer;
+         )" << CommonReadOnlyTestCode(format)
+                 << R"(
+            void main() {
             if (doTest()) {
                 dstBuffer.result = 1;
             } else {
@@ -372,7 +658,8 @@
             }
         })";
 
-    CheckResultInStorageBuffer(readonlyStorageTexture, kComputeShader);
+        CheckResultInStorageBuffer(readonlyStorageTexture, csStream.str());
+    }
 }
 
 // Test that read-only storage textures are supported in vertex shader.
@@ -383,20 +670,24 @@
     // bug in spvc parser is fixed.
     DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed());
 
-    // Prepare the read-only storage texture and fill it with the expected data.
-    // TODO(jiawei.shao@intel.com): test more texture formats
-    constexpr uint32_t kTexelSizeR32Uint = 4u;
-    const std::vector<uint32_t> kInitialTextureData = GetExpectedData();
-    wgpu::Texture readonlyStorageTexture =
-        CreateTextureWithTestData(kInitialTextureData, kTexelSizeR32Uint);
+    for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
+        if (!utils::TextureFormatSupportsStorageTexture(format)) {
+            continue;
+        }
 
-    // Create a rendering pipeline that reads the pixels from the read-only storage texture and uses
-    // green as the output color, otherwise uses red instead.
-    const std::string kVertexShader = std::string(R"(
+        // Prepare the read-only storage texture and fill it with the expected data.
+        const std::vector<uint8_t> kInitialTextureData = GetExpectedData(format);
+        wgpu::Texture readonlyStorageTexture =
+            CreateTextureWithTestData(kInitialTextureData, format);
+
+        // Create a rendering pipeline that reads the pixels from the read-only storage texture and
+        // uses green as the output color, otherwise uses red instead.
+        std::ostringstream vsStream;
+        vsStream << R"(
             #version 450
-            layout(set = 0, binding = 0, r32ui) uniform readonly uimage2D srcImage;
-            layout(location = 0) out vec4 o_color;)") +
-                                      kCommonReadOnlyTestCode_uimage2D + R"(
+            layout(location = 0) out vec4 o_color;
+        )" << CommonReadOnlyTestCode(format)
+                 << R"(
             void main() {
                 gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
                 if (doTest()) {
@@ -406,14 +697,15 @@
                 }
                 gl_PointSize = 1.0f;
             })";
-    const char* kFragmentShader = R"(
+        const char* kFragmentShader = R"(
             #version 450
             layout(location = 0) in vec4 o_color;
             layout(location = 0) out vec4 fragColor;
             void main() {
                 fragColor = o_color;
             })";
-    CheckDrawsGreen(kVertexShader.c_str(), kFragmentShader, readonlyStorageTexture);
+        CheckDrawsGreen(vsStream.str().c_str(), kFragmentShader, readonlyStorageTexture);
+    }
 }
 
 // Test that read-only storage textures are supported in fragment shader.
@@ -424,21 +716,25 @@
     // bug in spvc parser is fixed.
     DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed());
 
-    // Prepare the read-only storage texture and fill it with the expected data.
-    // TODO(jiawei.shao@intel.com): test more texture formats
-    constexpr uint32_t kTexelSizeR32Uint = 4u;
-    const std::vector<uint32_t> kInitialTextureData = GetExpectedData();
-    wgpu::Texture readonlyStorageTexture =
-        CreateTextureWithTestData(kInitialTextureData, kTexelSizeR32Uint);
+    for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
+        if (!utils::TextureFormatSupportsStorageTexture(format)) {
+            continue;
+        }
 
-    // Create a rendering pipeline that reads the pixels from the read-only storage texture and uses
-    // green as the output color if the pixel value is expected, otherwise uses red instead.
-    const char* kVertexShader = kSimpleVertexShader;
-    const std::string kFragmentShader = std::string(R"(
+        // Prepare the read-only storage texture and fill it with the expected data.
+        const std::vector<uint8_t> kInitialTextureData = GetExpectedData(format);
+        wgpu::Texture readonlyStorageTexture =
+            CreateTextureWithTestData(kInitialTextureData, format);
+
+        // Create a rendering pipeline that reads the pixels from the read-only storage texture and
+        // uses green as the output color if the pixel value is expected, otherwise uses red
+        // instead.
+        std::ostringstream fsStream;
+        fsStream << R"(
             #version 450
-            layout(set = 0, binding = 0, r32ui) uniform readonly uimage2D srcImage;
-            layout(location = 0) out vec4 o_color;)") +
-                                        kCommonReadOnlyTestCode_uimage2D + R"(
+            layout(location = 0) out vec4 o_color;
+        )" << CommonReadOnlyTestCode(format)
+                 << R"(
             void main() {
                 if (doTest()) {
                     o_color = vec4(0.f, 1.f, 0.f, 1.f);
@@ -446,7 +742,8 @@
                     o_color = vec4(1.f, 0.f, 0.f, 1.f);
                 }
             })";
-    CheckDrawsGreen(kVertexShader, kFragmentShader.c_str(), readonlyStorageTexture);
+        CheckDrawsGreen(kSimpleVertexShader, fsStream.str().c_str(), readonlyStorageTexture);
+    }
 }
 
 // Test that write-only storage textures are supported in compute shader.
@@ -465,7 +762,8 @@
 
     WriteIntoStorageTextureInComputePass(writeonlyStorageTexture,
                                          kCommonWriteOnlyTestCode_uimage2D);
-    CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint, GetExpectedData());
+    CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint,
+                              GetExpectedData(wgpu::TextureFormat::R32Uint));
 }
 
 // Test that write-only storage textures are supported in fragment shader.
@@ -484,7 +782,8 @@
 
     WriteIntoStorageTextureInRenderPass(writeonlyStorageTexture, kSimpleVertexShader,
                                         kCommonWriteOnlyTestCode_uimage2D);
-    CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint, GetExpectedData());
+    CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint,
+                              GetExpectedData(wgpu::TextureFormat::R32Uint));
 }
 
 // Verify 2D array read-only storage texture works correctly.
@@ -497,34 +796,23 @@
 
     constexpr uint32_t kArrayLayerCount = 3u;
 
-    constexpr uint32_t kTexelSizeR32Uint = 4u;
-    const std::vector<uint32_t> initialTextureData = GetExpectedData(kArrayLayerCount);
+    constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
+
+    const std::vector<uint8_t> initialTextureData =
+        GetExpectedData(kTextureFormat, kArrayLayerCount);
     wgpu::Texture readonlyStorageTexture =
-        CreateTextureWithTestData(initialTextureData, kTexelSizeR32Uint);
+        CreateTextureWithTestData(initialTextureData, kTextureFormat);
 
     // Create a compute shader that reads the pixels from the read-only storage texture and writes 1
     // to DstBuffer if they all have to expected value.
-    const char* kComputeShader = R"(
+    std::ostringstream csStream;
+    csStream << R"(
         #version 450
-        layout (set = 0, binding = 0, r32ui) uniform readonly uimage2DArray srcImage;
         layout (set = 0, binding = 1, std430) buffer DstBuffer {
             uint result;
         } dstBuffer;
-        bool doTest() {
-            ivec3 size = imageSize(srcImage);
-            for (uint layer = 0; layer < size.z; ++layer) {
-                for (uint y = 0; y < size.y; ++y) {
-                    for (uint x = 0; x < size.x; ++x) {
-                        uint expected = 1u + x + size.x * (y + size.y * layer);
-                        uvec4 pixel = imageLoad(srcImage, ivec3(x, y, layer));
-                        if (pixel != uvec4(expected, 0, 0, 1u)) {
-                            return false;
-                        }
-                    }
-                }
-            }
-            return true;
-        }
+    )" << CommonReadOnlyTestCode(kTextureFormat, true)
+             << R"(
         void main() {
             if (doTest()) {
                 dstBuffer.result = 1;
@@ -533,7 +821,7 @@
             }
         })";
 
-    CheckResultInStorageBuffer(readonlyStorageTexture, kComputeShader);
+    CheckResultInStorageBuffer(readonlyStorageTexture, csStream.str());
 }
 
 // Verify 2D array write-only storage texture works correctly.
@@ -570,7 +858,7 @@
 
     constexpr uint32_t kTexelSizeR32Uint = 4u;
     CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint,
-                              GetExpectedData(kArrayLayerCount));
+                              GetExpectedData(wgpu::TextureFormat::R32Uint, kArrayLayerCount));
 }
 
 DAWN_INSTANTIATE_TEST(StorageTextureTests,
@@ -581,10 +869,16 @@
 
 class StorageTextureZeroInitTests : public StorageTextureTests {
   public:
-    static std::vector<uint32_t> GetExpectedData() {
-        constexpr size_t kDataCount = kWidth * kHeight;
-        std::vector<uint32_t> outputData(kDataCount, 0);
-        outputData[0] = 1u;
+    static std::vector<uint8_t> GetExpectedData() {
+        constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
+
+        const uint32_t texelSizeInBytes = utils::GetTexelBlockSizeInBytes(kTextureFormat);
+        const size_t kDataCount = texelSizeInBytes * kWidth * kHeight;
+        std::vector<uint8_t> outputData(kDataCount, 0);
+
+        uint32_t* outputDataPtr = reinterpret_cast<uint32_t*>(&outputData[0]);
+        *outputDataPtr = 1u;
+
         return outputData;
     }
 
diff --git a/src/tests/unittests/validation/StorageTextureValidationTests.cpp b/src/tests/unittests/validation/StorageTextureValidationTests.cpp
index 22d6734..52f0f85 100644
--- a/src/tests/unittests/validation/StorageTextureValidationTests.cpp
+++ b/src/tests/unittests/validation/StorageTextureValidationTests.cpp
@@ -20,78 +20,6 @@
 
 class StorageTextureValidationTests : public ValidationTest {
   protected:
-    static const char* GetGLSLImageFormatQualifier(wgpu::TextureFormat textureFormat) {
-        switch (textureFormat) {
-            case wgpu::TextureFormat::R8Unorm:
-                return "r8";
-            case wgpu::TextureFormat::R8Snorm:
-                return "r8_snorm";
-            case wgpu::TextureFormat::R8Uint:
-                return "r8ui";
-            case wgpu::TextureFormat::R8Sint:
-                return "r8i";
-            case wgpu::TextureFormat::R16Uint:
-                return "r16ui";
-            case wgpu::TextureFormat::R16Sint:
-                return "r16i";
-            case wgpu::TextureFormat::R16Float:
-                return "r16f";
-            case wgpu::TextureFormat::RG8Unorm:
-                return "rg8";
-            case wgpu::TextureFormat::RG8Snorm:
-                return "rg8_snorm";
-            case wgpu::TextureFormat::RG8Uint:
-                return "rg8ui";
-            case wgpu::TextureFormat::RG8Sint:
-                return "rg8i";
-            case wgpu::TextureFormat::R32Float:
-                return "r32f";
-            case wgpu::TextureFormat::R32Uint:
-                return "r32ui";
-            case wgpu::TextureFormat::R32Sint:
-                return "r32i";
-            case wgpu::TextureFormat::RG16Uint:
-                return "rg16ui";
-            case wgpu::TextureFormat::RG16Sint:
-                return "rg16i";
-            case wgpu::TextureFormat::RG16Float:
-                return "rg16f";
-            case wgpu::TextureFormat::RGBA8Unorm:
-                return "rgba8";
-            case wgpu::TextureFormat::RGBA8Snorm:
-                return "rgba8_snorm";
-            case wgpu::TextureFormat::RGBA8Uint:
-                return "rgba8ui";
-            case wgpu::TextureFormat::RGBA8Sint:
-                return "rgba8i";
-            case wgpu::TextureFormat::RGB10A2Unorm:
-                return "rgb10_a2";
-            case wgpu::TextureFormat::RG11B10Float:
-                return "r11f_g11f_b10f";
-            case wgpu::TextureFormat::RG32Float:
-                return "rg32f";
-            case wgpu::TextureFormat::RG32Uint:
-                return "rg32ui";
-            case wgpu::TextureFormat::RG32Sint:
-                return "rg32i";
-            case wgpu::TextureFormat::RGBA16Uint:
-                return "rgba16ui";
-            case wgpu::TextureFormat::RGBA16Sint:
-                return "rgba16i";
-            case wgpu::TextureFormat::RGBA16Float:
-                return "rgba16f";
-            case wgpu::TextureFormat::RGBA32Float:
-                return "rgba32f";
-            case wgpu::TextureFormat::RGBA32Uint:
-                return "rgba32ui";
-            case wgpu::TextureFormat::RGBA32Sint:
-                return "rgba32i";
-            default:
-                UNREACHABLE();
-                return "";
-        }
-    }
-
     static const char* GetGLSLFloatImageTypeDeclaration(wgpu::TextureViewDimension dimension) {
         switch (dimension) {
             case wgpu::TextureViewDimension::e1D:
@@ -117,7 +45,7 @@
         wgpu::BindingType storageTextureBindingType,
         wgpu::TextureFormat textureFormat,
         wgpu::TextureViewDimension textureViewDimension = wgpu::TextureViewDimension::e2D) {
-        const char* glslImageFormatQualifier = GetGLSLImageFormatQualifier(textureFormat);
+        const char* glslImageFormatQualifier = utils::GetGLSLImageFormatQualifier(textureFormat);
         const char* textureComponentTypePrefix =
             utils::GetColorTextureComponentTypePrefix(textureFormat);
         return CreateComputeShaderWithStorageTexture(
diff --git a/src/utils/TextureFormatUtils.cpp b/src/utils/TextureFormatUtils.cpp
index 634417c..795d1f9 100644
--- a/src/utils/TextureFormatUtils.cpp
+++ b/src/utils/TextureFormatUtils.cpp
@@ -86,4 +86,172 @@
                 return false;
         }
     }
+
+    uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat) {
+        switch (textureFormat) {
+            case wgpu::TextureFormat::R8Unorm:
+            case wgpu::TextureFormat::R8Snorm:
+            case wgpu::TextureFormat::R8Uint:
+            case wgpu::TextureFormat::R8Sint:
+                return 1u;
+
+            case wgpu::TextureFormat::R16Uint:
+            case wgpu::TextureFormat::R16Sint:
+            case wgpu::TextureFormat::R16Float:
+            case wgpu::TextureFormat::RG8Unorm:
+            case wgpu::TextureFormat::RG8Snorm:
+            case wgpu::TextureFormat::RG8Uint:
+            case wgpu::TextureFormat::RG8Sint:
+                return 2u;
+
+            case wgpu::TextureFormat::R32Float:
+            case wgpu::TextureFormat::R32Uint:
+            case wgpu::TextureFormat::R32Sint:
+            case wgpu::TextureFormat::RG16Uint:
+            case wgpu::TextureFormat::RG16Sint:
+            case wgpu::TextureFormat::RG16Float:
+            case wgpu::TextureFormat::RGBA8Unorm:
+            case wgpu::TextureFormat::RGBA8UnormSrgb:
+            case wgpu::TextureFormat::RGBA8Snorm:
+            case wgpu::TextureFormat::RGBA8Uint:
+            case wgpu::TextureFormat::RGBA8Sint:
+            case wgpu::TextureFormat::BGRA8Unorm:
+            case wgpu::TextureFormat::BGRA8UnormSrgb:
+            case wgpu::TextureFormat::RGB10A2Unorm:
+            case wgpu::TextureFormat::RG11B10Float:
+                return 4u;
+
+            case wgpu::TextureFormat::RG32Float:
+            case wgpu::TextureFormat::RG32Uint:
+            case wgpu::TextureFormat::RG32Sint:
+            case wgpu::TextureFormat::RGBA16Uint:
+            case wgpu::TextureFormat::RGBA16Sint:
+            case wgpu::TextureFormat::RGBA16Float:
+                return 8u;
+
+            case wgpu::TextureFormat::RGBA32Float:
+            case wgpu::TextureFormat::RGBA32Uint:
+            case wgpu::TextureFormat::RGBA32Sint:
+                return 16u;
+
+            case wgpu::TextureFormat::BC1RGBAUnorm:
+            case wgpu::TextureFormat::BC1RGBAUnormSrgb:
+            case wgpu::TextureFormat::BC4RUnorm:
+            case wgpu::TextureFormat::BC4RSnorm:
+                return 8u;
+
+            case wgpu::TextureFormat::BC2RGBAUnorm:
+            case wgpu::TextureFormat::BC2RGBAUnormSrgb:
+            case wgpu::TextureFormat::BC3RGBAUnorm:
+            case wgpu::TextureFormat::BC3RGBAUnormSrgb:
+            case wgpu::TextureFormat::BC5RGUnorm:
+            case wgpu::TextureFormat::BC5RGSnorm:
+            case wgpu::TextureFormat::BC6HRGBUfloat:
+            case wgpu::TextureFormat::BC6HRGBSfloat:
+            case wgpu::TextureFormat::BC7RGBAUnorm:
+            case wgpu::TextureFormat::BC7RGBAUnormSrgb:
+                return 16u;
+
+            case wgpu::TextureFormat::Depth32Float:
+            case wgpu::TextureFormat::Depth24Plus:
+            case wgpu::TextureFormat::Depth24PlusStencil8:
+            case wgpu::TextureFormat::Undefined:
+            default:
+                UNREACHABLE();
+                return 0u;
+        }
+    }
+
+    const char* GetGLSLImageFormatQualifier(wgpu::TextureFormat textureFormat) {
+        switch (textureFormat) {
+            case wgpu::TextureFormat::R8Unorm:
+                return "r8";
+            case wgpu::TextureFormat::R8Snorm:
+                return "r8_snorm";
+            case wgpu::TextureFormat::R8Uint:
+                return "r8ui";
+            case wgpu::TextureFormat::R8Sint:
+                return "r8i";
+            case wgpu::TextureFormat::R16Uint:
+                return "r16ui";
+            case wgpu::TextureFormat::R16Sint:
+                return "r16i";
+            case wgpu::TextureFormat::R16Float:
+                return "r16f";
+            case wgpu::TextureFormat::RG8Unorm:
+                return "rg8";
+            case wgpu::TextureFormat::RG8Snorm:
+                return "rg8_snorm";
+            case wgpu::TextureFormat::RG8Uint:
+                return "rg8ui";
+            case wgpu::TextureFormat::RG8Sint:
+                return "rg8i";
+            case wgpu::TextureFormat::R32Float:
+                return "r32f";
+            case wgpu::TextureFormat::R32Uint:
+                return "r32ui";
+            case wgpu::TextureFormat::R32Sint:
+                return "r32i";
+            case wgpu::TextureFormat::RG16Uint:
+                return "rg16ui";
+            case wgpu::TextureFormat::RG16Sint:
+                return "rg16i";
+            case wgpu::TextureFormat::RG16Float:
+                return "rg16f";
+            case wgpu::TextureFormat::RGBA8Unorm:
+                return "rgba8";
+            case wgpu::TextureFormat::RGBA8Snorm:
+                return "rgba8_snorm";
+            case wgpu::TextureFormat::RGBA8Uint:
+                return "rgba8ui";
+            case wgpu::TextureFormat::RGBA8Sint:
+                return "rgba8i";
+            case wgpu::TextureFormat::RGB10A2Unorm:
+                return "rgb10_a2";
+            case wgpu::TextureFormat::RG11B10Float:
+                return "r11f_g11f_b10f";
+            case wgpu::TextureFormat::RG32Float:
+                return "rg32f";
+            case wgpu::TextureFormat::RG32Uint:
+                return "rg32ui";
+            case wgpu::TextureFormat::RG32Sint:
+                return "rg32i";
+            case wgpu::TextureFormat::RGBA16Uint:
+                return "rgba16ui";
+            case wgpu::TextureFormat::RGBA16Sint:
+                return "rgba16i";
+            case wgpu::TextureFormat::RGBA16Float:
+                return "rgba16f";
+            case wgpu::TextureFormat::RGBA32Float:
+                return "rgba32f";
+            case wgpu::TextureFormat::RGBA32Uint:
+                return "rgba32ui";
+            case wgpu::TextureFormat::RGBA32Sint:
+                return "rgba32i";
+
+            case wgpu::TextureFormat::RGBA8UnormSrgb:
+            case wgpu::TextureFormat::BGRA8Unorm:
+            case wgpu::TextureFormat::BGRA8UnormSrgb:
+            case wgpu::TextureFormat::BC1RGBAUnorm:
+            case wgpu::TextureFormat::BC1RGBAUnormSrgb:
+            case wgpu::TextureFormat::BC4RUnorm:
+            case wgpu::TextureFormat::BC4RSnorm:
+            case wgpu::TextureFormat::BC2RGBAUnorm:
+            case wgpu::TextureFormat::BC2RGBAUnormSrgb:
+            case wgpu::TextureFormat::BC3RGBAUnorm:
+            case wgpu::TextureFormat::BC3RGBAUnormSrgb:
+            case wgpu::TextureFormat::BC5RGUnorm:
+            case wgpu::TextureFormat::BC5RGSnorm:
+            case wgpu::TextureFormat::BC6HRGBUfloat:
+            case wgpu::TextureFormat::BC6HRGBSfloat:
+            case wgpu::TextureFormat::BC7RGBAUnorm:
+            case wgpu::TextureFormat::BC7RGBAUnormSrgb:
+            case wgpu::TextureFormat::Depth32Float:
+            case wgpu::TextureFormat::Depth24Plus:
+            case wgpu::TextureFormat::Depth24PlusStencil8:
+            case wgpu::TextureFormat::Undefined:
+                UNREACHABLE();
+                return "";
+        }
+    }
 }  // namespace utils
diff --git a/src/utils/TextureFormatUtils.h b/src/utils/TextureFormatUtils.h
index bbd5f0c..2976e94 100644
--- a/src/utils/TextureFormatUtils.h
+++ b/src/utils/TextureFormatUtils.h
@@ -53,6 +53,9 @@
 
     const char* GetColorTextureComponentTypePrefix(wgpu::TextureFormat textureFormat);
     bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
+
+    uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat);
+    const char* GetGLSLImageFormatQualifier(wgpu::TextureFormat textureFormat);
 }  // namespace utils
 
 #endif