Validate effective storage or read-only storage buffer size be multiple of 4

This patch adds a validation that the effective buffer size must be a multiple
of 4 when the binding type is storage or read-only storage to match the latest
WebGPU SPEC.

This patch also fixes some typos in BindGroupValidationTests.

Bug: dawn:1542
Test: dawn_unittest
Change-Id: I30234bcf718be0d82d4a09b9980127a98ebe8172
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105101
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/BindGroup.cpp b/src/dawn/native/BindGroup.cpp
index 8ac9d20..b2d8948 100644
--- a/src/dawn/native/BindGroup.cpp
+++ b/src/dawn/native/BindGroup.cpp
@@ -49,30 +49,6 @@
 
     ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);
 
-    wgpu::BufferUsage requiredUsage;
-    uint64_t maxBindingSize;
-    uint64_t requiredBindingAlignment;
-    switch (bindingInfo.buffer.type) {
-        case wgpu::BufferBindingType::Uniform:
-            requiredUsage = wgpu::BufferUsage::Uniform;
-            maxBindingSize = device->GetLimits().v1.maxUniformBufferBindingSize;
-            requiredBindingAlignment = device->GetLimits().v1.minUniformBufferOffsetAlignment;
-            break;
-        case wgpu::BufferBindingType::Storage:
-        case wgpu::BufferBindingType::ReadOnlyStorage:
-            requiredUsage = wgpu::BufferUsage::Storage;
-            maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
-            requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
-            break;
-        case kInternalStorageBufferBinding:
-            requiredUsage = kInternalStorageBuffer;
-            maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
-            requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
-            break;
-        case wgpu::BufferBindingType::Undefined:
-            UNREACHABLE();
-    }
-
     uint64_t bufferSize = entry.buffer->GetSize();
 
     // Handle wgpu::WholeSize, avoiding overflows.
@@ -95,6 +71,33 @@
                     "Binding range (offset: %u, size: %u) doesn't fit in the size (%u) of %s.",
                     entry.offset, bufferSize, bindingSize, entry.buffer);
 
+    wgpu::BufferUsage requiredUsage;
+    uint64_t maxBindingSize;
+    uint64_t requiredBindingAlignment;
+    switch (bindingInfo.buffer.type) {
+        case wgpu::BufferBindingType::Uniform:
+            requiredUsage = wgpu::BufferUsage::Uniform;
+            maxBindingSize = device->GetLimits().v1.maxUniformBufferBindingSize;
+            requiredBindingAlignment = device->GetLimits().v1.minUniformBufferOffsetAlignment;
+            break;
+        case wgpu::BufferBindingType::Storage:
+        case wgpu::BufferBindingType::ReadOnlyStorage:
+            requiredUsage = wgpu::BufferUsage::Storage;
+            maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
+            requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
+            DAWN_INVALID_IF(bindingSize % 4 != 0,
+                            "Binding size (%u) isn't a multiple of 4 when binding type is (%s).",
+                            bindingSize, bindingInfo.buffer.type);
+            break;
+        case kInternalStorageBufferBinding:
+            requiredUsage = kInternalStorageBuffer;
+            maxBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
+            requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
+            break;
+        case wgpu::BufferBindingType::Undefined:
+            UNREACHABLE();
+    }
+
     DAWN_INVALID_IF(!IsAligned(entry.offset, requiredBindingAlignment),
                     "Offset (%u) does not satisfy the minimum %s alignment (%u).", entry.offset,
                     bindingInfo.buffer.type, requiredBindingAlignment);
diff --git a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
index e687209..81886c6 100644
--- a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -1041,7 +1041,7 @@
 
     // Success case, this is one less than the limit (check it is not an alignment constraint)
     utils::MakeBindGroup(device, uniformLayout,
-                         {{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize - 1}});
+                         {{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize - 4}});
 
     wgpu::BindGroupLayout doubleUniformLayout = utils::MakeBindGroupLayout(
         device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage},
@@ -1055,7 +1055,51 @@
 
     // Error case, this is above the limit
     ASSERT_DEVICE_ERROR(utils::MakeBindGroup(
-        device, uniformLayout, {{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize + 1}}));
+        device, uniformLayout, {{0, buffer, 0, supportedLimits.maxStorageBufferBindingSize + 4}}));
+}
+
+// Test constraints to be sure the effective storage and read-only storage buffer binding size must
+// be a multiple of 4.
+TEST_F(BindGroupValidationTest, EffectiveStorageBufferBindingSize) {
+    wgpu::BufferDescriptor descriptor;
+    descriptor.size = 262;
+    descriptor.usage = wgpu::BufferUsage::Storage;
+    wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
+
+    constexpr std::array<wgpu::BufferBindingType, 2> kStorageBufferBindingTypes = {
+        {wgpu::BufferBindingType::Storage, wgpu::BufferBindingType::ReadOnlyStorage}};
+
+    for (wgpu::BufferBindingType bufferBindingType : kStorageBufferBindingTypes) {
+        wgpu::BindGroupLayout layout = utils::MakeBindGroupLayout(
+            device, {{0, wgpu::ShaderStage::Compute, bufferBindingType}});
+
+        // Error case, as the effective buffer binding size (262) isn't a multiple of 4.
+        {
+            constexpr uint32_t kOffset = 0;
+            ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, kOffset}}));
+        }
+
+        // Error case, as the effective buffer binding size (6) isn't a multiple of 4.
+        {
+            constexpr uint32_t kOffset = 256;
+            ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, kOffset}}));
+        }
+
+        // Error case, as the effective buffer binding size (2) isn't a multiple of 4.
+        {
+            constexpr uint32_t kOffset = 0;
+            constexpr uint32_t kBindingSize = 2;
+            ASSERT_DEVICE_ERROR(
+                utils::MakeBindGroup(device, layout, {{0, buffer, kOffset, kBindingSize}}));
+        }
+
+        // Success case, as the effective buffer binding size (4) is a multiple of 4.
+        {
+            constexpr uint32_t kOffset = 0;
+            constexpr uint32_t kBindingSize = 4;
+            utils::MakeBindGroup(device, layout, {{0, buffer, kOffset, kBindingSize}});
+        }
+    }
 }
 
 // Test what happens when the layout is an error.
@@ -1626,7 +1670,7 @@
                                });
 }
 
-constexpr uint32_t kBindingSize = 9;
+constexpr uint32_t kBindingSize = 8;
 
 class SetBindGroupValidationTest : public ValidationTest {
   public:
@@ -1919,17 +1963,19 @@
 
 // Test cases that test dynamic uniform buffer out of bound situation because of binding size.
 TEST_F(SetBindGroupValidationTest, BindingSizeOutOfBoundDynamicUniformBuffer) {
-    // Set up bind group, but binding size is larger than
+    // Set up bind group, but binding size is larger than (mBufferSize - DynamicOffset).
     wgpu::Buffer uniformBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Uniform);
     wgpu::Buffer storageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
     wgpu::Buffer readonlyStorageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
-    wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
-                                                     {{0, uniformBuffer, 0, kBindingSize},
-                                                      {1, uniformBuffer, 0, kBindingSize},
-                                                      {2, storageBuffer, 0, kBindingSize},
-                                                      {3, readonlyStorageBuffer, 0, kBindingSize}});
+    constexpr uint32_t kLargeBindingSize = kBindingSize + 4u;
+    wgpu::BindGroup bindGroup =
+        utils::MakeBindGroup(device, mBindGroupLayout,
+                             {{0, uniformBuffer, 0, kLargeBindingSize},
+                              {1, uniformBuffer, 0, kLargeBindingSize},
+                              {2, storageBuffer, 0, kLargeBindingSize},
+                              {3, readonlyStorageBuffer, 0, kLargeBindingSize}});
 
-    // Dynamic offset + offset isn't larger than buffer size.
+    // c + offset isn't larger than buffer size.
     // But with binding size, it will trigger OOB error.
     std::array<uint32_t, 3> offsets = {768, 256, 0};
 
@@ -1943,11 +1989,13 @@
     wgpu::Buffer uniformBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Uniform);
     wgpu::Buffer storageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
     wgpu::Buffer readonlyStorageBuffer = CreateBuffer(mBufferSize, wgpu::BufferUsage::Storage);
-    wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, mBindGroupLayout,
-                                                     {{0, uniformBuffer, 0, kBindingSize},
-                                                      {1, uniformBuffer, 0, kBindingSize},
-                                                      {2, storageBuffer, 0, kBindingSize},
-                                                      {3, readonlyStorageBuffer, 0, kBindingSize}});
+    constexpr uint32_t kLargeBindingSize = kBindingSize + 4u;
+    wgpu::BindGroup bindGroup =
+        utils::MakeBindGroup(device, mBindGroupLayout,
+                             {{0, uniformBuffer, 0, kLargeBindingSize},
+                              {1, uniformBuffer, 0, kLargeBindingSize},
+                              {2, storageBuffer, 0, kLargeBindingSize},
+                              {3, readonlyStorageBuffer, 0, kLargeBindingSize}});
     // Dynamic offset + offset isn't larger than buffer size.
     // But with binding size, it will trigger OOB error.
     std::array<uint32_t, 3> offsets = {0, 256, 768};
@@ -2593,7 +2641,7 @@
 
 // Test that it is invalid to set a pipeline layout that doesn't have all necessary bindings
 // required by the pipeline.
-TEST_F(BindingsValidationTest, PipelineLayoutWithLessBindingsThanPipeline) {
+TEST_F(BindingsValidationTest, PipelineLayoutWithFewerBindingsThanPipeline) {
     // Set up bind group layout.
     wgpu::BindGroupLayout bgl0 = utils::MakeBindGroupLayout(
         device, {{0, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
@@ -2672,7 +2720,7 @@
 // Test that it is invalid to set bind groups that don't have all necessary bindings required
 // by the pipeline layout. Note that both pipeline layout and bind group have enough bindings for
 // pipeline in the following test.
-TEST_F(BindingsValidationTest, BindGroupsWithLessBindingsThanPipelineLayout) {
+TEST_F(BindingsValidationTest, BindGroupsWithFewerBindingsThanPipelineLayout) {
     // Set up bind group layouts, buffers, bind groups, pipeline layouts and pipelines.
     std::array<wgpu::BindGroupLayout, kBindingNum> bgl;
     std::array<wgpu::BindGroup, kBindingNum> bg;
diff --git a/src/dawn/tests/unittests/validation/MinimumBufferSizeValidationTests.cpp b/src/dawn/tests/unittests/validation/MinimumBufferSizeValidationTests.cpp
index b8fbcde..dbd07c2 100644
--- a/src/dawn/tests/unittests/validation/MinimumBufferSizeValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/MinimumBufferSizeValidationTests.cpp
@@ -55,18 +55,19 @@
 template <typename F>
 void CheckSizeBounds(const std::vector<uint64_t>& correctSizes, F func) {
     // To validate size:
-    // Check invalid with bind group with one less
+    // Check invalid with bind group with 4 less (the effective storage / read-only storage buffer
+    // size must be a multiple of 4).
     // Check valid with bind group with correct size
 
-    // Make sure (every size - 1) produces an error
-    WithEachSizeOffsetBy(-1, correctSizes,
+    // Make sure (every size - 4) produces an error
+    WithEachSizeOffsetBy(-4, correctSizes,
                          [&](const std::vector<uint64_t>& sizes) { func(sizes, false); });
 
     // Make sure correct sizes work
     func(correctSizes, true);
 
-    // Make sure (every size + 1) works
-    WithEachSizeOffsetBy(1, correctSizes,
+    // Make sure (every size + 4) works
+    WithEachSizeOffsetBy(4, correctSizes,
                          [&](const std::vector<uint64_t>& sizes) { func(sizes, true); });
 }
 
@@ -324,8 +325,8 @@
 
 // Pipeline can be created if minimum buffer size in layout is specified as 0
 TEST_F(MinBufferSizePipelineCreationTests, ZeroMinBufferSize) {
-    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8},
-                                               {0, 1, "c : f32,", "f32", "c", 4}};
+    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
+                                               {0, 1, "d : f32, e : f32", "f32", "d", 8}};
 
     std::string computeShader = CreateComputeShaderWithBindings(bindings);
     std::string vertexShader = CreateVertexShaderWithBindings({});
@@ -338,14 +339,14 @@
 
 // Fail if layout given has non-zero minimum sizes smaller than shader requirements
 TEST_F(MinBufferSizePipelineCreationTests, LayoutSizesTooSmall) {
-    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8},
-                                               {0, 1, "c : f32,", "f32", "c", 4}};
+    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c: f32", "f32", "a", 12},
+                                               {0, 1, "d : f32, e : f32", "f32", "d", 8}};
 
     std::string computeShader = CreateComputeShaderWithBindings(bindings);
     std::string vertexShader = CreateVertexShaderWithBindings({});
     std::string fragShader = CreateFragmentShaderWithBindings(bindings);
 
-    CheckSizeBounds({8, 4}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
+    CheckSizeBounds({12, 8}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
         wgpu::BindGroupLayout layout = CreateBindGroupLayout(bindings, sizes);
         if (expectation) {
             CreateRenderPipeline({layout}, vertexShader, fragShader);
@@ -359,18 +360,19 @@
 
 // Fail if layout given has non-zero minimum sizes smaller than shader requirements
 TEST_F(MinBufferSizePipelineCreationTests, LayoutSizesTooSmallMultipleGroups) {
-    std::vector<BindingDescriptor> bg0Bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8},
-                                                  {0, 1, "c : f32,", "f32", "c", 4}};
+    std::vector<BindingDescriptor> bg0Bindings = {
+        {0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
+        {0, 1, "d : f32, e : f32", "f32", "d", 8}};
     std::vector<BindingDescriptor> bg1Bindings = {
-        {1, 0, "d : f32, e : f32, f : f32,", "f32", "e", 12},
-        {1, 1, "g : mat2x2<f32>,", "mat2x2<f32>", "g", 16}};
+        {1, 0, "f : f32, g : f32, h : f32,", "f32", "f", 12},
+        {1, 1, "i : mat2x2<f32>,", "mat2x2<f32>", "i", 16}};
     std::vector<BindingDescriptor> bindings = CombineBindings({bg0Bindings, bg1Bindings});
 
     std::string computeShader = CreateComputeShaderWithBindings(bindings);
     std::string vertexShader = CreateVertexShaderWithBindings({});
     std::string fragShader = CreateFragmentShaderWithBindings(bindings);
 
-    CheckSizeBounds({8, 4, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
+    CheckSizeBounds({12, 8, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
         wgpu::BindGroupLayout layout0 = CreateBindGroupLayout(bg0Bindings, {sizes[0], sizes[1]});
         wgpu::BindGroupLayout layout1 = CreateBindGroupLayout(bg1Bindings, {sizes[2], sizes[3]});
         if (expectation) {
@@ -388,11 +390,11 @@
 
 // Fail if a binding is smaller than minimum buffer size
 TEST_F(MinBufferSizeBindGroupCreationTests, BindingTooSmall) {
-    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8},
-                                               {0, 1, "c : f32,", "f32", "c", 4}};
-    wgpu::BindGroupLayout layout = CreateBindGroupLayout(bindings, {8, 4});
+    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
+                                               {0, 1, "d : f32, e : f32", "f32", "d", 8}};
+    wgpu::BindGroupLayout layout = CreateBindGroupLayout(bindings, {12, 8});
 
-    CheckSizeBounds({8, 4}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
+    CheckSizeBounds({12, 8}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
         if (expectation) {
             CreateBindGroup(layout, bindings, sizes);
         } else {
@@ -422,8 +424,8 @@
 
 // Fail if binding sizes are too small at draw time
 TEST_F(MinBufferSizeDrawTimeValidationTests, ZeroMinSizeAndTooSmallBinding) {
-    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8},
-                                               {0, 1, "c : f32,", "f32", "c", 4}};
+    std::vector<BindingDescriptor> bindings = {{0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
+                                               {0, 1, "d : f32, e : f32", "f32", "d", 8}};
 
     std::string computeShader = CreateComputeShaderWithBindings(bindings);
     std::string vertexShader = CreateVertexShaderWithBindings({});
@@ -434,7 +436,7 @@
     wgpu::ComputePipeline computePipeline = CreateComputePipeline({layout}, computeShader);
     wgpu::RenderPipeline renderPipeline = CreateRenderPipeline({layout}, vertexShader, fragShader);
 
-    CheckSizeBounds({8, 4}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
+    CheckSizeBounds({12, 8}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
         wgpu::BindGroup bindGroup = CreateBindGroup(layout, bindings, sizes);
         TestDispatch(computePipeline, {bindGroup}, expectation);
         TestDraw(renderPipeline, {bindGroup}, expectation);
@@ -445,8 +447,8 @@
 TEST_F(MinBufferSizeDrawTimeValidationTests, UnorderedBindings) {
     std::vector<BindingDescriptor> bindings = {
         {0, 2, "a : f32, b : f32,", "f32", "a", 8},
-        {0, 0, "c : f32,", "f32", "c", 4},
-        {0, 4, "d : f32, e : f32, f : f32,", "f32", "e", 12}};
+        {0, 0, "c : f32, d : f32, e : f32", "f32", "c", 12},
+        {0, 4, "f : f32, g : f32, h : f32, i : f32", "f32", "f", 16}};
 
     std::string computeShader = CreateComputeShaderWithBindings(bindings);
     std::string vertexShader = CreateVertexShaderWithBindings({});
@@ -457,7 +459,7 @@
     wgpu::ComputePipeline computePipeline = CreateComputePipeline({layout}, computeShader);
     wgpu::RenderPipeline renderPipeline = CreateRenderPipeline({layout}, vertexShader, fragShader);
 
-    CheckSizeBounds({8, 4, 12}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
+    CheckSizeBounds({8, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
         wgpu::BindGroup bindGroup = CreateBindGroup(layout, bindings, sizes);
         TestDispatch(computePipeline, {bindGroup}, expectation);
         TestDraw(renderPipeline, {bindGroup}, expectation);
@@ -466,11 +468,12 @@
 
 // Draw time validation works for multiple bind groups
 TEST_F(MinBufferSizeDrawTimeValidationTests, MultipleGroups) {
-    std::vector<BindingDescriptor> bg0Bindings = {{0, 0, "a : f32, b : f32,", "f32", "a", 8},
-                                                  {0, 1, "c : f32,", "f32", "c", 4}};
+    std::vector<BindingDescriptor> bg0Bindings = {
+        {0, 0, "a : f32, b : f32, c : f32", "f32", "a", 12},
+        {0, 1, "d : f32, e : f32", "f32", "d", 8}};
     std::vector<BindingDescriptor> bg1Bindings = {
-        {1, 0, "d : f32, e : f32, f : f32,", "f32", "e", 12},
-        {1, 1, "g : mat2x2<f32>,", "mat2x2<f32>", "g", 16}};
+        {1, 0, "f : f32, g : f32, h : f32,", "f32", "f", 12},
+        {1, 1, "i : mat2x2<f32>,", "mat2x2<f32>", "i", 16}};
     std::vector<BindingDescriptor> bindings = CombineBindings({bg0Bindings, bg1Bindings});
 
     std::string computeShader = CreateComputeShaderWithBindings(bindings);
@@ -485,7 +488,7 @@
     wgpu::RenderPipeline renderPipeline =
         CreateRenderPipeline({layout0, layout1}, vertexShader, fragShader);
 
-    CheckSizeBounds({8, 4, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
+    CheckSizeBounds({12, 8, 12, 16}, [&](const std::vector<uint64_t>& sizes, bool expectation) {
         wgpu::BindGroup bindGroup0 = CreateBindGroup(layout0, bg0Bindings, {sizes[0], sizes[1]});
         wgpu::BindGroup bindGroup1 = CreateBindGroup(layout0, bg0Bindings, {sizes[2], sizes[3]});
         TestDispatch(computePipeline, {bindGroup0, bindGroup1}, expectation);
diff --git a/webgpu-cts/expectations.txt b/webgpu-cts/expectations.txt
index 3eed0b2..7889042 100644
--- a/webgpu-cts/expectations.txt
+++ b/webgpu-cts/expectations.txt
@@ -770,6 +770,16 @@
 crbug.com/dawn/1539 [ ubuntu ] webgpu:api,validation,render_pipeline,fragment_state:pipeline_output_targets:isAsync=true;* [ Failure ]
 
 ################################################################################
+# storage buffer binding size failures
+################################################################################
+crbug.com/dawn/1542 webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="read-only-storage" [ Failure ]
+crbug.com/dawn/1542 webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="storage" [ Failure ]
+crbug.com/dawn/1542 webgpu:api,validation,createBindGroup:minBindingSize: [ Failure ]
+crbug.com/dawn/1542 webgpu:api,validation,encoding,cmds,setBindGroup:buffer_dynamic_offsets:type="read-only-storage";* [ Failure ]
+crbug.com/dawn/1542 webgpu:api,validation,encoding,cmds,setBindGroup:buffer_dynamic_offsets:type="storage";* [ Failure ]
+crbug.com/dawn/1542 webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_match_expectations_in_pass_encoder:* [ Failure ]
+
+################################################################################
 # untriaged failures
 # KEEP
 ################################################################################
@@ -788,8 +798,6 @@
 # New failures. Please triage:
 crbug.com/dawn/0000 [ intel-gen-9 win10 ] webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="2d" [ Failure ]
 crbug.com/dawn/0000 webgpu:api,validation,compute_pipeline:overrides,workgroup_size,limits,* [ Failure ]
-crbug.com/dawn/0000 [ win10 ] webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="read-only-storage" [ Failure ]
-crbug.com/dawn/0000 [ win10 ] webgpu:api,validation,createBindGroup:buffer,resource_binding_size:type="storage" [ Failure ]
 crbug.com/dawn/0000 webgpu:api,validation,createBindGroupLayout:multisampled_validation:viewDimension="2d" [ Failure ]
 crbug.com/dawn/0000 webgpu:api,validation,createBindGroupLayout:multisampled_validation:viewDimension="_undef_" [ Failure ]
 crbug.com/dawn/0000 [ nvidia-0x2184 target-cpu-32 webgpu-adapter-default win10 ] webgpu:shader,execution,shader_io,compute_builtins:inputs:method="mixed";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1} [ Failure ]