Add BGLBinding::textureComponentType

This is a new compatibility constraint that the texture component type
must match between what's declared in the shader and the bind group.

 - Format is updated to include the component type of the format.
 - Validation and state tracking is updated to reflect the new
BGLBinding member.
 - TextureFormat tests are updated to pass with the added validation and
to remove a redundant enum definition.
 - BGLBinding::multisampled validation is added because it was next to
modified code for the BGLBinding::textureComponentType validation.
 - A redundant BGL caching test was removed.

BUG=dawn:128

Change-Id: I9c4ae92062769c3ecf74caf46f27415344dfad77
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10281
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/dawn.json b/dawn.json
index a2102b3..77ef423 100644
--- a/dawn.json
+++ b/dawn.json
@@ -56,8 +56,9 @@
             {"name": "binding", "type": "uint32_t"},
             {"name": "visibility", "type": "shader stage bit"},
             {"name": "type", "type": "binding type"},
-            {"name": "dynamic", "type": "bool", "default": "false" },
-            {"name": "multisampled", "type": "bool", "default": "false" }
+            {"name": "dynamic", "type": "bool", "default": "false"},
+            {"name": "multisampled", "type": "bool", "default": "false"},
+            {"name": "texture component type", "type": "texture component type", "default": "float"}
         ]
     },
     "bind group layout descriptor": {
@@ -1152,6 +1153,14 @@
             {"value": 2, "name": "depth only"}
         ]
     },
+    "texture component type": {
+        "category": "enum",
+        "values": [
+            {"value": 0, "name": "float"},
+            {"value": 1, "name": "sint"},
+            {"value": 2, "name": "uint"}
+        ]
+    },
     "texture copy view": {
         "category": "structure",
         "extensible": true,
diff --git a/src/dawn_native/BindGroup.cpp b/src/dawn_native/BindGroup.cpp
index da018e1..c2b832b 100644
--- a/src/dawn_native/BindGroup.cpp
+++ b/src/dawn_native/BindGroup.cpp
@@ -63,17 +63,29 @@
 
         MaybeError ValidateTextureBinding(const DeviceBase* device,
                                           const BindGroupBinding& binding,
-                                          dawn::TextureUsageBit requiredUsage) {
+                                          dawn::TextureUsageBit requiredUsage,
+                                          bool multisampledBinding,
+                                          dawn::TextureComponentType requiredComponentType) {
             if (binding.textureView == nullptr || binding.sampler != nullptr ||
                 binding.buffer != nullptr) {
                 return DAWN_VALIDATION_ERROR("expected texture binding");
             }
             DAWN_TRY(device->ValidateObject(binding.textureView));
 
-            if (!(binding.textureView->GetTexture()->GetUsage() & requiredUsage)) {
+            TextureBase* texture = binding.textureView->GetTexture();
+
+            if (!(texture->GetUsage() & requiredUsage)) {
                 return DAWN_VALIDATION_ERROR("texture binding usage mismatch");
             }
 
+            if (texture->IsMultisampledTexture() != multisampledBinding) {
+                return DAWN_VALIDATION_ERROR("texture multisampling mismatch");
+            }
+
+            if (!texture->GetFormat().HasComponentType(requiredComponentType)) {
+                return DAWN_VALIDATION_ERROR("texture component type usage mismatch");
+            }
+
             return {};
         }
 
@@ -134,7 +146,9 @@
                     break;
                 case dawn::BindingType::SampledTexture:
                     DAWN_TRY(
-                        ValidateTextureBinding(device, binding, dawn::TextureUsageBit::Sampled));
+                        ValidateTextureBinding(device, binding, dawn::TextureUsageBit::Sampled,
+                                               layoutInfo.multisampled[bindingIndex],
+                                               layoutInfo.textureComponentTypes[bindingIndex]));
                     break;
                 case dawn::BindingType::Sampler:
                     DAWN_TRY(ValidateSamplerBinding(device, binding));
diff --git a/src/dawn_native/BindGroupLayout.cpp b/src/dawn_native/BindGroupLayout.cpp
index ff9acfa..85e5391 100644
--- a/src/dawn_native/BindGroupLayout.cpp
+++ b/src/dawn_native/BindGroupLayout.cpp
@@ -36,6 +36,7 @@
             const BindGroupLayoutBinding& binding = descriptor->bindings[i];
             DAWN_TRY(ValidateShaderStageBit(binding.visibility));
             DAWN_TRY(ValidateBindingType(binding.type));
+            DAWN_TRY(ValidateTextureComponentType(binding.textureComponentType));
 
             if (binding.binding >= kMaxBindingsPerGroup) {
                 return DAWN_VALIDATION_ERROR("some binding index exceeds the maximum value");
@@ -98,7 +99,8 @@
             HashCombine(&hash, info.dynamic, info.multisampled);
 
             for (uint32_t binding : IterateBitSet(info.mask)) {
-                HashCombine(&hash, info.visibilities[binding], info.types[binding]);
+                HashCombine(&hash, info.visibilities[binding], info.types[binding],
+                            info.textureComponentTypes[binding]);
             }
 
             return hash;
@@ -112,7 +114,8 @@
 
             for (uint32_t binding : IterateBitSet(a.mask)) {
                 if ((a.visibilities[binding] != b.visibilities[binding]) ||
-                    (a.types[binding] != b.types[binding])) {
+                    (a.types[binding] != b.types[binding]) ||
+                    (a.textureComponentTypes[binding] != b.textureComponentTypes[binding])) {
                     return false;
                 }
             }
@@ -133,6 +136,7 @@
             uint32_t index = binding.binding;
             mBindingInfo.visibilities[index] = binding.visibility;
             mBindingInfo.types[index] = binding.type;
+            mBindingInfo.textureComponentTypes[index] = binding.textureComponentType;
 
             if (binding.dynamic) {
                 mBindingInfo.dynamic.set(index);
diff --git a/src/dawn_native/BindGroupLayout.h b/src/dawn_native/BindGroupLayout.h
index 98e912b..b19bf82 100644
--- a/src/dawn_native/BindGroupLayout.h
+++ b/src/dawn_native/BindGroupLayout.h
@@ -42,6 +42,7 @@
         struct LayoutBindingInfo {
             std::array<dawn::ShaderStageBit, kMaxBindingsPerGroup> visibilities;
             std::array<dawn::BindingType, kMaxBindingsPerGroup> types;
+            std::array<dawn::TextureComponentType, kMaxBindingsPerGroup> textureComponentTypes;
             std::bitset<kMaxBindingsPerGroup> dynamic;
             std::bitset<kMaxBindingsPerGroup> multisampled;
             std::bitset<kMaxBindingsPerGroup> mask;
diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp
index c18f57a..0370c89 100644
--- a/src/dawn_native/Format.cpp
+++ b/src/dawn_native/Format.cpp
@@ -38,6 +38,25 @@
         return aspect != Color;
     }
 
+    bool Format::HasComponentType(dawn::TextureComponentType componentType) const {
+        // Depth stencil textures need to be special cased but we don't support sampling them yet.
+        if (aspect != Color) {
+            return false;
+        }
+
+        // Check that Type is correctly mirrors TextureComponentType except for "Other".
+        static_assert(static_cast<dawn::TextureComponentType>(Type::Float) ==
+                          dawn::TextureComponentType::Float,
+                      "");
+        static_assert(
+            static_cast<dawn::TextureComponentType>(Type::Sint) == dawn::TextureComponentType::Sint,
+            "");
+        static_assert(
+            static_cast<dawn::TextureComponentType>(Type::Uint) == dawn::TextureComponentType::Uint,
+            "");
+        return static_cast<dawn::TextureComponentType>(type) == componentType;
+    }
+
     size_t Format::GetIndex() const {
         return ComputeFormatIndex(format);
     }
@@ -54,6 +73,9 @@
         FormatTable table;
         std::bitset<kKnownFormatCount> formatsSet;
 
+        using Type = Format::Type;
+        using Aspect = Format::Aspect;
+
         auto AddFormat = [&table, &formatsSet](Format format) {
             size_t index = ComputeFormatIndex(format.format);
             ASSERT(index < table.size());
@@ -67,13 +89,14 @@
         };
 
         auto AddColorFormat = [&AddFormat](dawn::TextureFormat format, bool renderable,
-                                           uint32_t byteSize) {
+                                           uint32_t byteSize, Type type) {
             Format internalFormat;
             internalFormat.format = format;
             internalFormat.isRenderable = renderable;
             internalFormat.isCompressed = false;
             internalFormat.isSupported = true;
-            internalFormat.aspect = Format::Aspect::Color;
+            internalFormat.aspect = Aspect::Color;
+            internalFormat.type = type;
             internalFormat.blockByteSize = byteSize;
             internalFormat.blockWidth = 1;
             internalFormat.blockHeight = 1;
@@ -88,6 +111,7 @@
             internalFormat.isCompressed = false;
             internalFormat.isSupported = true;
             internalFormat.aspect = aspect;
+            internalFormat.type = Type::Other;
             internalFormat.blockByteSize = byteSize;
             internalFormat.blockWidth = 1;
             internalFormat.blockHeight = 1;
@@ -101,7 +125,8 @@
             internalFormat.isRenderable = false;
             internalFormat.isCompressed = true;
             internalFormat.isSupported = isSupported;
-            internalFormat.aspect = Format::Aspect::Color;
+            internalFormat.aspect = Aspect::Color;
+            internalFormat.type = Type::Float;
             internalFormat.blockByteSize = byteSize;
             internalFormat.blockWidth = width;
             internalFormat.blockHeight = height;
@@ -111,57 +136,57 @@
         // clang-format off
 
         // 1 byte color formats
-        AddColorFormat(dawn::TextureFormat::R8Unorm, true, 1);
-        AddColorFormat(dawn::TextureFormat::R8Snorm, false, 1);
-        AddColorFormat(dawn::TextureFormat::R8Uint, true, 1);
-        AddColorFormat(dawn::TextureFormat::R8Sint, true, 1);
+        AddColorFormat(dawn::TextureFormat::R8Unorm, true, 1, Type::Float);
+        AddColorFormat(dawn::TextureFormat::R8Snorm, false, 1, Type::Float);
+        AddColorFormat(dawn::TextureFormat::R8Uint, true, 1, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::R8Sint, true, 1, Type::Sint);
 
         // 2 bytes color formats
-        AddColorFormat(dawn::TextureFormat::R16Uint, true, 2);
-        AddColorFormat(dawn::TextureFormat::R16Sint, true, 2);
-        AddColorFormat(dawn::TextureFormat::R16Float, true, 2);
-        AddColorFormat(dawn::TextureFormat::RG8Unorm, true, 2);
-        AddColorFormat(dawn::TextureFormat::RG8Snorm, false, 2);
-        AddColorFormat(dawn::TextureFormat::RG8Uint, true, 2);
-        AddColorFormat(dawn::TextureFormat::RG8Sint, true, 2);
+        AddColorFormat(dawn::TextureFormat::R16Uint, true, 2, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::R16Sint, true, 2, Type::Sint);
+        AddColorFormat(dawn::TextureFormat::R16Float, true, 2, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RG8Unorm, true, 2, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RG8Snorm, false, 2, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RG8Uint, true, 2, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::RG8Sint, true, 2, Type::Sint);
 
         // 4 bytes color formats
-        AddColorFormat(dawn::TextureFormat::R32Uint, true, 4);
-        AddColorFormat(dawn::TextureFormat::R32Sint, true, 4);
-        AddColorFormat(dawn::TextureFormat::R32Float, true, 4);
-        AddColorFormat(dawn::TextureFormat::RG16Uint, true, 4);
-        AddColorFormat(dawn::TextureFormat::RG16Sint, true, 4);
-        AddColorFormat(dawn::TextureFormat::RG16Float, true, 4);
-        AddColorFormat(dawn::TextureFormat::RGBA8Unorm, true, 4);
-        AddColorFormat(dawn::TextureFormat::RGBA8UnormSrgb, true, 4);
-        AddColorFormat(dawn::TextureFormat::RGBA8Snorm, false, 4);
-        AddColorFormat(dawn::TextureFormat::RGBA8Uint, true, 4);
-        AddColorFormat(dawn::TextureFormat::RGBA8Sint, true, 4);
-        AddColorFormat(dawn::TextureFormat::BGRA8Unorm, true, 4);
-        AddColorFormat(dawn::TextureFormat::BGRA8UnormSrgb, true, 4);
-        AddColorFormat(dawn::TextureFormat::RGB10A2Unorm, true, 4);
+        AddColorFormat(dawn::TextureFormat::R32Uint, true, 4, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::R32Sint, true, 4, Type::Sint);
+        AddColorFormat(dawn::TextureFormat::R32Float, true, 4, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RG16Uint, true, 4, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::RG16Sint, true, 4, Type::Sint);
+        AddColorFormat(dawn::TextureFormat::RG16Float, true, 4, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RGBA8Unorm, true, 4, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RGBA8UnormSrgb, true, 4, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RGBA8Snorm, false, 4, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RGBA8Uint, true, 4, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::RGBA8Sint, true, 4, Type::Sint);
+        AddColorFormat(dawn::TextureFormat::BGRA8Unorm, true, 4, Type::Float);
+        AddColorFormat(dawn::TextureFormat::BGRA8UnormSrgb, true, 4, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RGB10A2Unorm, true, 4, Type::Float);
 
-        AddColorFormat(dawn::TextureFormat::RG11B10Float, false, 4);
+        AddColorFormat(dawn::TextureFormat::RG11B10Float, false, 4, Type::Float);
 
         // 8 bytes color formats
-        AddColorFormat(dawn::TextureFormat::RG32Uint, true, 8);
-        AddColorFormat(dawn::TextureFormat::RG32Sint, true, 8);
-        AddColorFormat(dawn::TextureFormat::RG32Float, true, 8);
-        AddColorFormat(dawn::TextureFormat::RGBA16Uint, true, 8);
-        AddColorFormat(dawn::TextureFormat::RGBA16Sint, true, 8);
-        AddColorFormat(dawn::TextureFormat::RGBA16Float, true, 8);
+        AddColorFormat(dawn::TextureFormat::RG32Uint, true, 8, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::RG32Sint, true, 8, Type::Sint);
+        AddColorFormat(dawn::TextureFormat::RG32Float, true, 8, Type::Float);
+        AddColorFormat(dawn::TextureFormat::RGBA16Uint, true, 8, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::RGBA16Sint, true, 8, Type::Sint);
+        AddColorFormat(dawn::TextureFormat::RGBA16Float, true, 8, Type::Float);
 
         // 16 bytes color formats
-        AddColorFormat(dawn::TextureFormat::RGBA32Uint, true, 16);
-        AddColorFormat(dawn::TextureFormat::RGBA32Sint, true, 16);
-        AddColorFormat(dawn::TextureFormat::RGBA32Float, true, 16);
+        AddColorFormat(dawn::TextureFormat::RGBA32Uint, true, 16, Type::Uint);
+        AddColorFormat(dawn::TextureFormat::RGBA32Sint, true, 16, Type::Sint);
+        AddColorFormat(dawn::TextureFormat::RGBA32Float, true, 16, Type::Float);
 
         // Depth stencil formats
-        AddDepthStencilFormat(dawn::TextureFormat::Depth32Float, Format::Aspect::Depth, 4);
-        AddDepthStencilFormat(dawn::TextureFormat::Depth24Plus, Format::Aspect::Depth, 4);
+        AddDepthStencilFormat(dawn::TextureFormat::Depth32Float, Aspect::Depth, 4);
+        AddDepthStencilFormat(dawn::TextureFormat::Depth24Plus, Aspect::Depth, 4);
         // TODO(cwallez@chromium.org): It isn't clear if this format should be copyable
         // because its size isn't well defined, is it 4, 5 or 8?
-        AddDepthStencilFormat(dawn::TextureFormat::Depth24PlusStencil8, Format::Aspect::DepthStencil, 4);
+        AddDepthStencilFormat(dawn::TextureFormat::Depth24PlusStencil8, Aspect::DepthStencil, 4);
 
         // BC compressed formats
         bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
diff --git a/src/dawn_native/Format.h b/src/dawn_native/Format.h
index 39776d7..4ec19b8 100644
--- a/src/dawn_native/Format.h
+++ b/src/dawn_native/Format.h
@@ -38,12 +38,20 @@
             DepthStencil,
         };
 
+        enum Type {
+            Float,
+            Sint,
+            Uint,
+            Other,
+        };
+
         dawn::TextureFormat format;
         bool isRenderable;
         bool isCompressed;
         // A format can be known but not supported because it is part of a disabled extension.
         bool isSupported;
         Aspect aspect;
+        Type type;
 
         uint32_t blockByteSize;
         uint32_t blockWidth;
@@ -53,6 +61,7 @@
         bool HasDepth() const;
         bool HasStencil() const;
         bool HasDepthOrStencil() const;
+        bool HasComponentType(dawn::TextureComponentType componentType) const;
 
         // The index of the format in the list of all known formats: a unique number for each format
         // in [0, kKnownFormatCount)
diff --git a/src/tests/end2end/ObjectCachingTests.cpp b/src/tests/end2end/ObjectCachingTests.cpp
index c96b3ad..1d35fc9 100644
--- a/src/tests/end2end/ObjectCachingTests.cpp
+++ b/src/tests/end2end/ObjectCachingTests.cpp
@@ -32,7 +32,7 @@
     EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire());
 }
 
-// Test that two similar bind group layouts won't refer to the same one.
+// Test that two similar bind group layouts won't refer to the same one if they differ by dynamic.
 TEST_P(ObjectCachingTest, BindGroupLayoutDynamic) {
     dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
         device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer, true}});
@@ -45,6 +45,23 @@
     EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire());
 }
 
+// Test that two similar bind group layouts won't refer to the same one if they differ by
+// textureComponentType
+TEST_P(ObjectCachingTest, BindGroupLayoutTextureComponentType) {
+    dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
+        device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture, false,
+                  false, dawn::TextureComponentType::Float}});
+    dawn::BindGroupLayout sameBgl = utils::MakeBindGroupLayout(
+        device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture, false,
+                  false, dawn::TextureComponentType::Float}});
+    dawn::BindGroupLayout otherBgl = utils::MakeBindGroupLayout(
+        device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture, false,
+                  false, dawn::TextureComponentType::Uint}});
+
+    EXPECT_NE(bgl.Get(), otherBgl.Get());
+    EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire());
+}
+
 // Test that an error object doesn't try to uncache itself
 TEST_P(ObjectCachingTest, ErrorObjectDoesntUncache) {
     ASSERT_DEVICE_ERROR(
diff --git a/src/tests/end2end/TextureFormatTests.cpp b/src/tests/end2end/TextureFormatTests.cpp
index 2567fde..b530c696 100644
--- a/src/tests/end2end/TextureFormatTests.cpp
+++ b/src/tests/end2end/TextureFormatTests.cpp
@@ -113,25 +113,13 @@
   protected:
     void SetUp() {
         DawnTest::SetUp();
-
-        mSampleBGL = utils::MakeBindGroupLayout(
-            device, {{0, dawn::ShaderStageBit::Fragment, dawn::BindingType::Sampler},
-                     {1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture}});
     }
 
-    // Describes what the "decompressed" data type for a texture format is. For example normalized
-    // formats are stored as integers but interpreted to produce floating point values.
-    enum ComponentType {
-        Uint,
-        Sint,
-        Float,
-    };
-
     // Structure containing all the information that tests need to know about the format.
     struct FormatTestInfo {
         dawn::TextureFormat format;
         uint32_t texelByteSize;
-        ComponentType type;
+        dawn::TextureComponentType type;
         uint32_t componentCount;
     };
 
@@ -161,13 +149,13 @@
         ASSERT(formatInfo.componentCount > 0 && formatInfo.componentCount <= 4);
         dawn::TextureFormat format;
         switch (formatInfo.type) {
-            case Float:
+            case dawn::TextureComponentType::Float:
                 format = floatFormats[formatInfo.componentCount - 1];
                 break;
-            case Sint:
+            case dawn::TextureComponentType::Sint:
                 format = sintFormats[formatInfo.componentCount - 1];
                 break;
-            case Uint:
+            case dawn::TextureComponentType::Uint:
                 format = uintFormats[formatInfo.componentCount - 1];
                 break;
             default:
@@ -181,7 +169,8 @@
     // Return a pipeline that can be used in a full-texture draw to sample from the texture in the
     // bindgroup and output its decompressed values to the render target.
     dawn::RenderPipeline CreateSamplePipeline(FormatTestInfo sampleFormatInfo,
-                                              FormatTestInfo renderFormatInfo) {
+                                              FormatTestInfo renderFormatInfo,
+                                              dawn::BindGroupLayout bgl) {
         utils::ComboRenderPipelineDescriptor desc(device);
 
         dawn::ShaderModule vsModule =
@@ -199,13 +188,13 @@
         // Compute the prefix needed for GLSL types that handle our texture's data.
         const char* prefix = nullptr;
         switch (sampleFormatInfo.type) {
-            case Float:
+            case dawn::TextureComponentType::Float:
                 prefix = "";
                 break;
-            case Sint:
+            case dawn::TextureComponentType::Sint:
                 prefix = "i";
                 break;
-            case Uint:
+            case dawn::TextureComponentType::Uint:
                 prefix = "u";
                 break;
             default:
@@ -229,7 +218,7 @@
 
         desc.cVertexStage.module = vsModule;
         desc.cFragmentStage.module = fsModule;
-        desc.layout = utils::MakeBasicPipelineLayout(device, &mSampleBGL);
+        desc.layout = utils::MakeBasicPipelineLayout(device, &bgl);
         desc.cColorStates[0]->format = renderFormatInfo.format;
 
         return device.CreateRenderPipeline(&desc);
@@ -281,12 +270,19 @@
         readbackBufferDesc.size = 4 * width * sampleFormatInfo.componentCount;
         dawn::Buffer readbackBuffer = device.CreateBuffer(&readbackBufferDesc);
 
+        // Create the bind group layout for sampling the texture
+        dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
+            device, {{0, dawn::ShaderStageBit::Fragment, dawn::BindingType::Sampler},
+                     {1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture, false,
+                      false, sampleFormatInfo.type}});
+
         // Prepare objects needed to sample from texture in the renderpass
-        dawn::RenderPipeline pipeline = CreateSamplePipeline(sampleFormatInfo, renderFormatInfo);
+        dawn::RenderPipeline pipeline =
+            CreateSamplePipeline(sampleFormatInfo, renderFormatInfo, bgl);
         dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
         dawn::Sampler sampler = device.CreateSampler(&samplerDesc);
         dawn::BindGroup bindGroup = utils::MakeBindGroup(
-            device, mSampleBGL, {{0, sampler}, {1, sampleTexture.CreateDefaultView()}});
+            device, bgl, {{0, sampler}, {1, sampleTexture.CreateDefaultView()}});
 
         // Encode commands for the test that fill texture, sample it to render to renderTarget then
         // copy renderTarget in a buffer so we can read it easily.
@@ -372,7 +368,7 @@
     void DoUnormTest(FormatTestInfo formatInfo) {
         static_assert(!std::is_signed<T>::value && std::is_integral<T>::value, "");
         ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
-        ASSERT(formatInfo.type == Float);
+        ASSERT(formatInfo.type == dawn::TextureComponentType::Float);
 
         T maxValue = std::numeric_limits<T>::max();
         std::vector<T> textureData = {0, 1, maxValue, maxValue};
@@ -386,7 +382,7 @@
     void DoSnormTest(FormatTestInfo formatInfo) {
         static_assert(std::is_signed<T>::value && std::is_integral<T>::value, "");
         ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
-        ASSERT(formatInfo.type == Float);
+        ASSERT(formatInfo.type == dawn::TextureComponentType::Float);
 
         T maxValue = std::numeric_limits<T>::max();
         T minValue = std::numeric_limits<T>::min();
@@ -401,7 +397,7 @@
     void DoUintTest(FormatTestInfo formatInfo) {
         static_assert(!std::is_signed<T>::value && std::is_integral<T>::value, "");
         ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
-        ASSERT(formatInfo.type == Uint);
+        ASSERT(formatInfo.type == dawn::TextureComponentType::Uint);
 
         T maxValue = std::numeric_limits<T>::max();
         std::vector<T> textureData = {0, 1, maxValue, maxValue};
@@ -415,7 +411,7 @@
     void DoSintTest(FormatTestInfo formatInfo) {
         static_assert(std::is_signed<T>::value && std::is_integral<T>::value, "");
         ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
-        ASSERT(formatInfo.type == Sint);
+        ASSERT(formatInfo.type == dawn::TextureComponentType::Sint);
 
         T maxValue = std::numeric_limits<T>::max();
         T minValue = std::numeric_limits<T>::min();
@@ -428,7 +424,7 @@
 
     void DoFloat32Test(FormatTestInfo formatInfo) {
         ASSERT(sizeof(float) * formatInfo.componentCount == formatInfo.texelByteSize);
-        ASSERT(formatInfo.type == Float);
+        ASSERT(formatInfo.type == dawn::TextureComponentType::Float);
 
         std::vector<float> textureData = {+0.0f,  -0.0f, 1.0f,     1.0e-29f,
                                           1.0e29f, NAN,   INFINITY, -INFINITY};
@@ -440,7 +436,7 @@
 
     void DoFloat16Test(FormatTestInfo formatInfo) {
         ASSERT(sizeof(int16_t) * formatInfo.componentCount == formatInfo.texelByteSize);
-        ASSERT(formatInfo.type == Float);
+        ASSERT(formatInfo.type == dawn::TextureComponentType::Float);
 
         std::vector<float> uncompressedData = {+0.0f,  -0.0f, 1.0f,     1.01e-4f,
                                                1.0e4f, NAN,   INFINITY, -INFINITY};
@@ -455,24 +451,22 @@
         DoFormatRenderingTest(formatInfo, uncompressedData, textureData,
                               new ExpectFloat16(textureData));
     }
-
-  private:
-    dawn::BindGroupLayout mSampleBGL;
 };
 
 // Test the R8Unorm format
 TEST_P(TextureFormatTest, R8Unorm) {
-    DoUnormTest<uint8_t>({dawn::TextureFormat::R8Unorm, 1, Float, 1});
+    DoUnormTest<uint8_t>({dawn::TextureFormat::R8Unorm, 1, dawn::TextureComponentType::Float, 1});
 }
 
 // Test the RG8Unorm format
 TEST_P(TextureFormatTest, RG8Unorm) {
-    DoUnormTest<uint8_t>({dawn::TextureFormat::RG8Unorm, 2, Float, 2});
+    DoUnormTest<uint8_t>({dawn::TextureFormat::RG8Unorm, 2, dawn::TextureComponentType::Float, 2});
 }
 
 // Test the RGBA8Unorm format
 TEST_P(TextureFormatTest, RGBA8Unorm) {
-    DoUnormTest<uint8_t>({dawn::TextureFormat::RGBA8Unorm, 4, Float, 4});
+    DoUnormTest<uint8_t>(
+        {dawn::TextureFormat::RGBA8Unorm, 4, dawn::TextureComponentType::Float, 4});
 }
 
 // Test the BGRA8Unorm format
@@ -480,25 +474,26 @@
     uint8_t maxValue = std::numeric_limits<uint8_t>::max();
     std::vector<uint8_t> textureData = {maxValue, 1, 0, maxValue};
     std::vector<float> uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f};
-    DoFormatSamplingTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, textureData,
-                         uncompressedData);
-    DoFormatRenderingTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, uncompressedData,
-                          textureData);
+    DoFormatSamplingTest({dawn::TextureFormat::BGRA8Unorm, 4, dawn::TextureComponentType::Float, 4},
+                         textureData, uncompressedData);
+    DoFormatRenderingTest(
+        {dawn::TextureFormat::BGRA8Unorm, 4, dawn::TextureComponentType::Float, 4},
+        uncompressedData, textureData);
 }
 
 // Test the R8Snorm format
 TEST_P(TextureFormatTest, R8Snorm) {
-    DoSnormTest<int8_t>({dawn::TextureFormat::R8Snorm, 1, Float, 1});
+    DoSnormTest<int8_t>({dawn::TextureFormat::R8Snorm, 1, dawn::TextureComponentType::Float, 1});
 }
 
 // Test the RG8Snorm format
 TEST_P(TextureFormatTest, RG8Snorm) {
-    DoSnormTest<int8_t>({dawn::TextureFormat::RG8Snorm, 2, Float, 2});
+    DoSnormTest<int8_t>({dawn::TextureFormat::RG8Snorm, 2, dawn::TextureComponentType::Float, 2});
 }
 
 // Test the RGBA8Snorm format
 TEST_P(TextureFormatTest, RGBA8Snorm) {
-    DoSnormTest<int8_t>({dawn::TextureFormat::RGBA8Snorm, 4, Float, 4});
+    DoSnormTest<int8_t>({dawn::TextureFormat::RGBA8Snorm, 4, dawn::TextureComponentType::Float, 4});
 }
 
 // Test the R8Uint format
@@ -506,7 +501,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint8_t>({dawn::TextureFormat::R8Uint, 1, Uint, 1});
+    DoUintTest<uint8_t>({dawn::TextureFormat::R8Uint, 1, dawn::TextureComponentType::Uint, 1});
 }
 
 // Test the RG8Uint format
@@ -514,7 +509,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint8_t>({dawn::TextureFormat::RG8Uint, 2, Uint, 2});
+    DoUintTest<uint8_t>({dawn::TextureFormat::RG8Uint, 2, dawn::TextureComponentType::Uint, 2});
 }
 
 // Test the RGBA8Uint format
@@ -522,7 +517,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint8_t>({dawn::TextureFormat::RGBA8Uint, 4, Uint, 4});
+    DoUintTest<uint8_t>({dawn::TextureFormat::RGBA8Uint, 4, dawn::TextureComponentType::Uint, 4});
 }
 
 // Test the R16Uint format
@@ -530,7 +525,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint16_t>({dawn::TextureFormat::R16Uint, 2, Uint, 1});
+    DoUintTest<uint16_t>({dawn::TextureFormat::R16Uint, 2, dawn::TextureComponentType::Uint, 1});
 }
 
 // Test the RG16Uint format
@@ -538,7 +533,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint16_t>({dawn::TextureFormat::RG16Uint, 4, Uint, 2});
+    DoUintTest<uint16_t>({dawn::TextureFormat::RG16Uint, 4, dawn::TextureComponentType::Uint, 2});
 }
 
 // Test the RGBA16Uint format
@@ -546,7 +541,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint16_t>({dawn::TextureFormat::RGBA16Uint, 8, Uint, 4});
+    DoUintTest<uint16_t>({dawn::TextureFormat::RGBA16Uint, 8, dawn::TextureComponentType::Uint, 4});
 }
 
 // Test the R32Uint format
@@ -554,7 +549,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint32_t>({dawn::TextureFormat::R32Uint, 4, Uint, 1});
+    DoUintTest<uint32_t>({dawn::TextureFormat::R32Uint, 4, dawn::TextureComponentType::Uint, 1});
 }
 
 // Test the RG32Uint format
@@ -562,7 +557,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint32_t>({dawn::TextureFormat::RG32Uint, 8, Uint, 2});
+    DoUintTest<uint32_t>({dawn::TextureFormat::RG32Uint, 8, dawn::TextureComponentType::Uint, 2});
 }
 
 // Test the RGBA32Uint format
@@ -570,7 +565,8 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoUintTest<uint32_t>({dawn::TextureFormat::RGBA32Uint, 16, Uint, 4});
+    DoUintTest<uint32_t>(
+        {dawn::TextureFormat::RGBA32Uint, 16, dawn::TextureComponentType::Uint, 4});
 }
 
 // Test the R8Sint format
@@ -578,7 +574,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int8_t>({dawn::TextureFormat::R8Sint, 1, Sint, 1});
+    DoSintTest<int8_t>({dawn::TextureFormat::R8Sint, 1, dawn::TextureComponentType::Sint, 1});
 }
 
 // Test the RG8Sint format
@@ -586,7 +582,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int8_t>({dawn::TextureFormat::RG8Sint, 2, Sint, 2});
+    DoSintTest<int8_t>({dawn::TextureFormat::RG8Sint, 2, dawn::TextureComponentType::Sint, 2});
 }
 
 // Test the RGBA8Sint format
@@ -594,7 +590,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int8_t>({dawn::TextureFormat::RGBA8Sint, 4, Sint, 4});
+    DoSintTest<int8_t>({dawn::TextureFormat::RGBA8Sint, 4, dawn::TextureComponentType::Sint, 4});
 }
 
 // Test the R16Sint format
@@ -602,7 +598,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int16_t>({dawn::TextureFormat::R16Sint, 2, Sint, 1});
+    DoSintTest<int16_t>({dawn::TextureFormat::R16Sint, 2, dawn::TextureComponentType::Sint, 1});
 }
 
 // Test the RG16Sint format
@@ -610,7 +606,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int16_t>({dawn::TextureFormat::RG16Sint, 4, Sint, 2});
+    DoSintTest<int16_t>({dawn::TextureFormat::RG16Sint, 4, dawn::TextureComponentType::Sint, 2});
 }
 
 // Test the RGBA16Sint format
@@ -618,7 +614,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int16_t>({dawn::TextureFormat::RGBA16Sint, 8, Sint, 4});
+    DoSintTest<int16_t>({dawn::TextureFormat::RGBA16Sint, 8, dawn::TextureComponentType::Sint, 4});
 }
 
 // Test the R32Sint format
@@ -626,7 +622,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int32_t>({dawn::TextureFormat::R32Sint, 4, Sint, 1});
+    DoSintTest<int32_t>({dawn::TextureFormat::R32Sint, 4, dawn::TextureComponentType::Sint, 1});
 }
 
 // Test the RG32Sint format
@@ -634,7 +630,7 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int32_t>({dawn::TextureFormat::RG32Sint, 8, Sint, 2});
+    DoSintTest<int32_t>({dawn::TextureFormat::RG32Sint, 8, dawn::TextureComponentType::Sint, 2});
 }
 
 // Test the RGBA32Sint format
@@ -642,37 +638,37 @@
     // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why.
     DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel());
 
-    DoSintTest<int32_t>({dawn::TextureFormat::RGBA32Sint, 16, Sint, 4});
+    DoSintTest<int32_t>({dawn::TextureFormat::RGBA32Sint, 16, dawn::TextureComponentType::Sint, 4});
 }
 
 // Test the R32Float format
 TEST_P(TextureFormatTest, R32Float) {
-    DoFloat32Test({dawn::TextureFormat::R32Float, 4, Float, 1});
+    DoFloat32Test({dawn::TextureFormat::R32Float, 4, dawn::TextureComponentType::Float, 1});
 }
 
 // Test the RG32Float format
 TEST_P(TextureFormatTest, RG32Float) {
-    DoFloat32Test({dawn::TextureFormat::RG32Float, 8, Float, 2});
+    DoFloat32Test({dawn::TextureFormat::RG32Float, 8, dawn::TextureComponentType::Float, 2});
 }
 
 // Test the RGBA32Float format
 TEST_P(TextureFormatTest, RGBA32Float) {
-    DoFloat32Test({dawn::TextureFormat::RGBA32Float, 16, Float, 4});
+    DoFloat32Test({dawn::TextureFormat::RGBA32Float, 16, dawn::TextureComponentType::Float, 4});
 }
 
 // Test the R16Float format
 TEST_P(TextureFormatTest, R16Float) {
-    DoFloat16Test({dawn::TextureFormat::R16Float, 2, Float, 1});
+    DoFloat16Test({dawn::TextureFormat::R16Float, 2, dawn::TextureComponentType::Float, 1});
 }
 
 // Test the RG16Float format
 TEST_P(TextureFormatTest, RG16Float) {
-    DoFloat16Test({dawn::TextureFormat::RG16Float, 4, Float, 2});
+    DoFloat16Test({dawn::TextureFormat::RG16Float, 4, dawn::TextureComponentType::Float, 2});
 }
 
 // Test the RGBA16Float format
 TEST_P(TextureFormatTest, RGBA16Float) {
-    DoFloat16Test({dawn::TextureFormat::RGBA16Float, 8, Float, 4});
+    DoFloat16Test({dawn::TextureFormat::RGBA16Float, 8, dawn::TextureComponentType::Float, 4});
 }
 
 // Test the RGBA8Unorm format
@@ -689,10 +685,12 @@
         uncompressedData.push_back(textureData[i + 3] / float(maxValue));
     }
 
-    DoFloatFormatSamplingTest({dawn::TextureFormat::RGBA8UnormSrgb, 4, Float, 4}, textureData,
-                              uncompressedData, 1.0e-3);
-    DoFormatRenderingTest({dawn::TextureFormat::RGBA8UnormSrgb, 4, Float, 4}, uncompressedData,
-                          textureData);
+    DoFloatFormatSamplingTest(
+        {dawn::TextureFormat::RGBA8UnormSrgb, 4, dawn::TextureComponentType::Float, 4}, textureData,
+        uncompressedData, 1.0e-3);
+    DoFormatRenderingTest(
+        {dawn::TextureFormat::RGBA8UnormSrgb, 4, dawn::TextureComponentType::Float, 4},
+        uncompressedData, textureData);
 }
 
 // Test the BGRA8UnormSrgb format
@@ -714,10 +712,12 @@
         uncompressedData.push_back(textureData[i + 3] / float(maxValue));
     }
 
-    DoFloatFormatSamplingTest({dawn::TextureFormat::BGRA8UnormSrgb, 4, Float, 4}, textureData,
-                              uncompressedData, 1.0e-3);
-    DoFormatRenderingTest({dawn::TextureFormat::BGRA8UnormSrgb, 4, Float, 4}, uncompressedData,
-                          textureData);
+    DoFloatFormatSamplingTest(
+        {dawn::TextureFormat::BGRA8UnormSrgb, 4, dawn::TextureComponentType::Float, 4}, textureData,
+        uncompressedData, 1.0e-3);
+    DoFormatRenderingTest(
+        {dawn::TextureFormat::BGRA8UnormSrgb, 4, dawn::TextureComponentType::Float, 4},
+        uncompressedData, textureData);
 }
 
 // Test the RGB10A2Unorm format
@@ -741,10 +741,12 @@
     };
     // clang-format on
 
-    DoFloatFormatSamplingTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, textureData,
-                              uncompressedData, 1.0e-5);
-    DoFormatRenderingTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, uncompressedData,
-                          textureData);
+    DoFloatFormatSamplingTest(
+        {dawn::TextureFormat::RGB10A2Unorm, 4, dawn::TextureComponentType::Float, 4}, textureData,
+        uncompressedData, 1.0e-5);
+    DoFormatRenderingTest(
+        {dawn::TextureFormat::RGB10A2Unorm, 4, dawn::TextureComponentType::Float, 4},
+        uncompressedData, textureData);
 }
 
 // Test the RG11B10Float format
@@ -786,8 +788,9 @@
     };
     // clang-format on
 
-    DoFloatFormatSamplingTest({dawn::TextureFormat::RG11B10Float, 4, Float, 4}, textureData,
-                              uncompressedData);
+    DoFloatFormatSamplingTest(
+        {dawn::TextureFormat::RG11B10Float, 4, dawn::TextureComponentType::Float, 4}, textureData,
+        uncompressedData);
     // This format is not renderable.
 }
 
diff --git a/src/tests/unittests/validation/BindGroupValidationTests.cpp b/src/tests/unittests/validation/BindGroupValidationTests.cpp
index 24d6c8f..423dff1 100644
--- a/src/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -306,6 +306,30 @@
     ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, outputTextureView}}));
 }
 
+// Check that a texture must have the correct component type
+TEST_F(BindGroupValidationTest, TextureComponentType) {
+    dawn::BindGroupLayout layout = utils::MakeBindGroupLayout(
+        device, {{0, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture, false,
+                  false, dawn::TextureComponentType::Float}});
+
+    // Control case: setting a Float typed texture view works.
+    utils::MakeBindGroup(device, layout, {{0, mSampledTextureView}});
+
+    // Make an output attachment texture and try to set it for a SampledTexture binding
+    dawn::TextureDescriptor descriptor;
+    descriptor.dimension = dawn::TextureDimension::e2D;
+    descriptor.size = {16, 16, 1};
+    descriptor.arrayLayerCount = 1;
+    descriptor.sampleCount = 1;
+    descriptor.format = dawn::TextureFormat::RGBA8Uint;
+    descriptor.mipLevelCount = 1;
+    descriptor.usage = dawn::TextureUsageBit::Sampled;
+    dawn::Texture uintTexture = device.CreateTexture(&descriptor);
+    dawn::TextureView uintTextureView = uintTexture.CreateDefaultView();
+
+    ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, uintTextureView}}));
+}
+
 // Check that a UBO must have the correct usage
 TEST_F(BindGroupValidationTest, BufferUsageUBO) {
     dawn::BindGroupLayout layout = utils::MakeBindGroupLayout(device, {
@@ -482,24 +506,6 @@
                 }));
 }
 
-// This test verifies that the BindGroupLayout cache is successfully caching/deduplicating objects.
-//
-// NOTE: This test only works currently because unittests are run without the wire - so the returned
-// BindGroupLayout pointers are actually visibly equivalent. With the wire, this would not be true.
-TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutCache) {
-    auto layout1 = utils::MakeBindGroupLayout(
-        device, {
-                    {0, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer},
-                });
-    auto layout2 = utils::MakeBindGroupLayout(
-        device, {
-                    {0, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer},
-                });
-
-    // Caching should cause these to be the same.
-    ASSERT_EQ(layout1.Get(), layout2.Get());
-}
-
 // This test verifies that visibility of bindings in BindGroupLayout can't be none
 TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutVisibilityNone) {
     utils::MakeBindGroupLayout(
diff --git a/src/tests/unittests/wire/WireArgumentTests.cpp b/src/tests/unittests/wire/WireArgumentTests.cpp
index c0cce5c..e59fe24 100644
--- a/src/tests/unittests/wire/WireArgumentTests.cpp
+++ b/src/tests/unittests/wire/WireArgumentTests.cpp
@@ -332,12 +332,14 @@
 TEST_F(WireArgumentTests, StructureOfStructureArrayArgument) {
     static constexpr int NUM_BINDINGS = 3;
     DawnBindGroupLayoutBinding bindings[NUM_BINDINGS]{
-        {0, DAWN_SHADER_STAGE_BIT_VERTEX, DAWN_BINDING_TYPE_SAMPLER, false, false},
-        {1, DAWN_SHADER_STAGE_BIT_VERTEX, DAWN_BINDING_TYPE_SAMPLED_TEXTURE, false, false},
+        {0, DAWN_SHADER_STAGE_BIT_VERTEX, DAWN_BINDING_TYPE_SAMPLER, false, false,
+         DAWN_TEXTURE_COMPONENT_TYPE_FLOAT},
+        {1, DAWN_SHADER_STAGE_BIT_VERTEX, DAWN_BINDING_TYPE_SAMPLED_TEXTURE, false, false,
+         DAWN_TEXTURE_COMPONENT_TYPE_FLOAT},
         {2,
          static_cast<DawnShaderStageBit>(DAWN_SHADER_STAGE_BIT_VERTEX |
                                          DAWN_SHADER_STAGE_BIT_FRAGMENT),
-         DAWN_BINDING_TYPE_UNIFORM_BUFFER, false, false},
+         DAWN_BINDING_TYPE_UNIFORM_BUFFER, false, false, DAWN_TEXTURE_COMPONENT_TYPE_FLOAT},
     };
     DawnBindGroupLayoutDescriptor bglDescriptor;
     bglDescriptor.bindingCount = NUM_BINDINGS;