Add dynamic attribute in bind group layout binding

WebGPU remove dynamic-uniform-buffer and dynamic-storage-buffer but add a new attribute in
BindgroupLayoutBinding to record whether a buffer resource is dynamic.
Dawn need to align with this change.

BUG=dawn:180

Change-Id: I873ad2ec75575e72d184f89a6e3698dff6df50d7
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8520
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/dawn.json b/dawn.json
index cfb0db3..4b1f6e2 100644
--- a/dawn.json
+++ b/dawn.json
@@ -55,7 +55,8 @@
         "members": [
             {"name": "binding", "type": "uint32_t"},
             {"name": "visibility", "type": "shader stage bit"},
-            {"name": "type", "type": "binding type"}
+            {"name": "type", "type": "binding type"},
+            {"name": "dynamic", "type": "bool", "default": "false" }
         ]
     },
     "bind group layout descriptor": {
@@ -70,11 +71,9 @@
         "category": "enum",
         "values": [
             {"value": 0, "name": "uniform buffer"},
-            {"value": 1, "name": "sampler"},
-            {"value": 2, "name": "sampled texture"},
-            {"value": 3, "name": "storage buffer"},
-            {"value": 4, "name": "dynamic uniform buffer"},
-            {"value": 5, "name": "dynamic storage buffer"}
+            {"value": 1, "name": "storage buffer"},
+            {"value": 2, "name": "sampler"},
+            {"value": 3, "name": "sampled texture"}
         ]
     },
     "blend descriptor": {
diff --git a/examples/Animometer.cpp b/examples/Animometer.cpp
index da68552..a90546c 100644
--- a/examples/Animometer.cpp
+++ b/examples/Animometer.cpp
@@ -111,7 +111,7 @@
         })");
 
     dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
-        device, {{0, dawn::ShaderStageBit::Vertex, dawn::BindingType::DynamicUniformBuffer}});
+        device, {{0, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer, true}});
 
     utils::ComboRenderPipelineDescriptor descriptor(device);
     descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl);
diff --git a/src/dawn_native/BindGroup.cpp b/src/dawn_native/BindGroup.cpp
index 93af9bf..a6db7cf 100644
--- a/src/dawn_native/BindGroup.cpp
+++ b/src/dawn_native/BindGroup.cpp
@@ -126,18 +126,23 @@
             // Perform binding-type specific validation.
             switch (layoutInfo.types[bindingIndex]) {
                 case dawn::BindingType::UniformBuffer:
-                case dawn::BindingType::DynamicUniformBuffer:
                     DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsageBit::Uniform));
                     break;
                 case dawn::BindingType::StorageBuffer:
-                case dawn::BindingType::DynamicStorageBuffer:
                     DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsageBit::Storage));
                     break;
                 case dawn::BindingType::SampledTexture:
+                    if (layoutInfo.dynamic[bindingIndex]) {
+                        return DAWN_VALIDATION_ERROR(
+                            "SampledTextures are expected to be not dynamic");
+                    }
                     DAWN_TRY(
                         ValidateTextureBinding(device, binding, dawn::TextureUsageBit::Sampled));
                     break;
                 case dawn::BindingType::Sampler:
+                    if (layoutInfo.dynamic[bindingIndex]) {
+                        return DAWN_VALIDATION_ERROR("Samplers are expected to be not dynamic");
+                    }
                     DAWN_TRY(ValidateSamplerBinding(device, binding));
                     break;
             }
@@ -207,10 +212,7 @@
         ASSERT(binding < kMaxBindingsPerGroup);
         ASSERT(mLayout->GetBindingInfo().mask[binding]);
         ASSERT(mLayout->GetBindingInfo().types[binding] == dawn::BindingType::UniformBuffer ||
-               mLayout->GetBindingInfo().types[binding] == dawn::BindingType::StorageBuffer ||
-               mLayout->GetBindingInfo().types[binding] ==
-                   dawn::BindingType::DynamicUniformBuffer ||
-               mLayout->GetBindingInfo().types[binding] == dawn::BindingType::DynamicStorageBuffer);
+               mLayout->GetBindingInfo().types[binding] == dawn::BindingType::StorageBuffer);
         BufferBase* buffer = static_cast<BufferBase*>(mBindings[binding].Get());
         return {buffer, mOffsets[binding], mSizes[binding]};
     }
diff --git a/src/dawn_native/BindGroupLayout.cpp b/src/dawn_native/BindGroupLayout.cpp
index 4e94e9f..9dcdce4 100644
--- a/src/dawn_native/BindGroupLayout.cpp
+++ b/src/dawn_native/BindGroupLayout.cpp
@@ -87,8 +87,8 @@
             mBindingInfo.visibilities[index] = binding.visibility;
             mBindingInfo.types[index] = binding.type;
 
-            if (binding.type == dawn::BindingType::DynamicUniformBuffer ||
-                binding.type == dawn::BindingType::DynamicStorageBuffer) {
+            if (binding.dynamic) {
+                mBindingInfo.dynamic.set(index);
                 mDynamicBufferCount++;
             }
 
diff --git a/src/dawn_native/BindGroupLayout.h b/src/dawn_native/BindGroupLayout.h
index decc68f..c2b5d8c 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::bitset<kMaxBindingsPerGroup> dynamic;
             std::bitset<kMaxBindingsPerGroup> mask;
         };
         const LayoutBindingInfo& GetBindingInfo() const;
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp
index 4a66f23..f306a01 100644
--- a/src/dawn_native/CommandEncoder.cpp
+++ b/src/dawn_native/CommandEncoder.cpp
@@ -588,14 +588,12 @@
                 dawn::BindingType type = layoutInfo.types[i];
 
                 switch (type) {
-                    case dawn::BindingType::UniformBuffer:
-                    case dawn::BindingType::DynamicUniformBuffer: {
+                    case dawn::BindingType::UniformBuffer: {
                         BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
                         tracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Uniform);
                     } break;
 
-                    case dawn::BindingType::StorageBuffer:
-                    case dawn::BindingType::DynamicStorageBuffer: {
+                    case dawn::BindingType::StorageBuffer: {
                         BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
                         tracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Storage);
                     } break;
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index ac025e6..6313eab 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -66,17 +66,6 @@
         return {};
     }
 
-    dawn::BindingType NonDynamicBindingType(dawn::BindingType type) {
-        switch (type) {
-            case dawn::BindingType::DynamicUniformBuffer:
-                return dawn::BindingType::UniformBuffer;
-            case dawn::BindingType::DynamicStorageBuffer:
-                return dawn::BindingType::StorageBuffer;
-            default:
-                return type;
-        }
-    }
-
     // ShaderModuleBase
 
     ShaderModuleBase::ShaderModuleBase(DeviceBase* device,
@@ -247,9 +236,7 @@
                 continue;
             }
 
-            // DynamicUniformBuffer and DynamicStorageBuffer are uniform buffer and
-            // storage buffer in shader. Need to translate them.
-            if (NonDynamicBindingType(layoutBindingType) != moduleInfo.type) {
+            if (layoutBindingType != moduleInfo.type) {
                 return false;
             }
 
diff --git a/src/dawn_native/d3d12/BindGroupD3D12.cpp b/src/dawn_native/d3d12/BindGroupD3D12.cpp
index e81db4d..4c1dbae 100644
--- a/src/dawn_native/d3d12/BindGroupD3D12.cpp
+++ b/src/dawn_native/d3d12/BindGroupD3D12.cpp
@@ -97,10 +97,6 @@
                 } break;
 
                 // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
-                case dawn::BindingType::DynamicUniformBuffer:
-                case dawn::BindingType::DynamicStorageBuffer:
-                    UNREACHABLE();
-                    break;
             }
         }
 
diff --git a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
index f97eebb..ac419ce 100644
--- a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
+++ b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
@@ -38,10 +38,6 @@
                     mBindingOffsets[binding] = mDescriptorCounts[Sampler]++;
                     break;
                 // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
-                case dawn::BindingType::DynamicUniformBuffer:
-                case dawn::BindingType::DynamicStorageBuffer:
-                    UNREACHABLE();
-                    break;
             }
         }
 
@@ -101,10 +97,6 @@
                     mBindingOffsets[binding] += descriptorOffsets[Sampler];
                     break;
                 // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
-                case dawn::BindingType::DynamicUniformBuffer:
-                case dawn::BindingType::DynamicStorageBuffer:
-                    UNREACHABLE();
-                    break;
             }
         }
     }
diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm
index b037285..1970f3e 100644
--- a/src/dawn_native/metal/CommandBufferMTL.mm
+++ b/src/dawn_native/metal/CommandBufferMTL.mm
@@ -235,7 +235,14 @@
                     case dawn::BindingType::StorageBuffer: {
                         BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
                         const id<MTLBuffer> buffer = ToBackend(binding.buffer)->GetMTLBuffer();
-                        const NSUInteger offset = binding.offset;
+                        NSUInteger offset = binding.offset;
+
+                        // TODO(shaobo.yan@intel.com): Record bound buffer status to use
+                        // setBufferOffset to achieve better performance.
+                        if (layout.dynamic[bindingIndex]) {
+                            offset += dynamicOffsets[currentDynamicBufferIndex];
+                            currentDynamicBufferIndex++;
+                        }
 
                         if (hasVertStage) {
                             [render setVertexBuffers:&buffer
@@ -285,34 +292,6 @@
                             [compute setTexture:textureView->GetMTLTexture() atIndex:computeIndex];
                         }
                     } break;
-
-                    // TODO(shaobo.yan@intel.com): Record bound buffer status to use setBufferOffset
-                    // to achieve better performance.
-                    case dawn::BindingType::DynamicUniformBuffer:
-                    case dawn::BindingType::DynamicStorageBuffer: {
-                        ASSERT(currentDynamicBufferIndex < dynamicOffsetCount);
-                        BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
-                        const id<MTLBuffer> buffer = ToBackend(binding.buffer)->GetMTLBuffer();
-                        NSUInteger offset =
-                            binding.offset + dynamicOffsets[currentDynamicBufferIndex];
-                        currentDynamicBufferIndex += 1;
-
-                        if (hasVertStage) {
-                            [render setVertexBuffers:&buffer
-                                             offsets:&offset
-                                           withRange:NSMakeRange(vertIndex, 1)];
-                        }
-                        if (hasFragStage) {
-                            [render setFragmentBuffers:&buffer
-                                               offsets:&offset
-                                             withRange:NSMakeRange(fragIndex, 1)];
-                        }
-                        if (hasComputeStage) {
-                            [compute setBuffers:&buffer
-                                        offsets:&offset
-                                      withRange:NSMakeRange(computeIndex, 1)];
-                        }
-                    } break;
                 }
             }
         }
diff --git a/src/dawn_native/metal/PipelineLayoutMTL.mm b/src/dawn_native/metal/PipelineLayoutMTL.mm
index 640feca..9912f94 100644
--- a/src/dawn_native/metal/PipelineLayoutMTL.mm
+++ b/src/dawn_native/metal/PipelineLayoutMTL.mm
@@ -42,8 +42,6 @@
                     switch (groupInfo.types[binding]) {
                         case dawn::BindingType::UniformBuffer:
                         case dawn::BindingType::StorageBuffer:
-                        case dawn::BindingType::DynamicUniformBuffer:
-                        case dawn::BindingType::DynamicStorageBuffer:
                             mIndexInfo[stage][group][binding] = bufferIndex;
                             bufferIndex++;
                             break;
diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp
index c1a3d45..2b064eb 100644
--- a/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -266,11 +266,7 @@
                                            binding.offset, binding.size);
                     } break;
 
-                    // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
-                    case dawn::BindingType::DynamicUniformBuffer:
-                    case dawn::BindingType::DynamicStorageBuffer:
-                        UNREACHABLE();
-                        break;
+                        // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
                 }
             }
         }
diff --git a/src/dawn_native/opengl/PipelineGL.cpp b/src/dawn_native/opengl/PipelineGL.cpp
index 697ab82..645dac2 100644
--- a/src/dawn_native/opengl/PipelineGL.cpp
+++ b/src/dawn_native/opengl/PipelineGL.cpp
@@ -136,10 +136,6 @@
                         break;
 
                     // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
-                    case dawn::BindingType::DynamicUniformBuffer:
-                    case dawn::BindingType::DynamicStorageBuffer:
-                        UNREACHABLE();
-                        break;
                 }
             }
         }
diff --git a/src/dawn_native/opengl/PipelineLayoutGL.cpp b/src/dawn_native/opengl/PipelineLayoutGL.cpp
index e646fef..d8278a6 100644
--- a/src/dawn_native/opengl/PipelineLayoutGL.cpp
+++ b/src/dawn_native/opengl/PipelineLayoutGL.cpp
@@ -55,10 +55,6 @@
                         break;
 
                     // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset
-                    case dawn::BindingType::DynamicUniformBuffer:
-                    case dawn::BindingType::DynamicStorageBuffer:
-                        UNREACHABLE();
-                        break;
                 }
             }
         }
diff --git a/src/dawn_native/vulkan/BindGroupLayoutVk.cpp b/src/dawn_native/vulkan/BindGroupLayoutVk.cpp
index 83f5838..fb22153 100644
--- a/src/dawn_native/vulkan/BindGroupLayoutVk.cpp
+++ b/src/dawn_native/vulkan/BindGroupLayoutVk.cpp
@@ -39,20 +39,22 @@
 
     }  // anonymous namespace
 
-    VkDescriptorType VulkanDescriptorType(dawn::BindingType type) {
+    VkDescriptorType VulkanDescriptorType(dawn::BindingType type, bool isDynamic) {
         switch (type) {
             case dawn::BindingType::UniformBuffer:
+                if (isDynamic) {
+                    return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+                }
                 return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
             case dawn::BindingType::Sampler:
                 return VK_DESCRIPTOR_TYPE_SAMPLER;
             case dawn::BindingType::SampledTexture:
                 return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
             case dawn::BindingType::StorageBuffer:
+                if (isDynamic) {
+                    return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+                }
                 return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
-            case dawn::BindingType::DynamicUniformBuffer:
-                return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
-            case dawn::BindingType::DynamicStorageBuffer:
-                return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
             default:
                 UNREACHABLE();
         }
@@ -70,7 +72,8 @@
         for (uint32_t bindingIndex : IterateBitSet(info.mask)) {
             auto& binding = bindings[numBindings];
             binding.binding = bindingIndex;
-            binding.descriptorType = VulkanDescriptorType(info.types[bindingIndex]);
+            binding.descriptorType =
+                VulkanDescriptorType(info.types[bindingIndex], info.dynamic[bindingIndex]);
             binding.descriptorCount = 1;
             binding.stageFlags = VulkanShaderStageFlags(info.visibilities[bindingIndex]);
             binding.pImmutableSamplers = nullptr;
@@ -122,14 +125,12 @@
         auto ToDescriptorType = [](dawn::BindingType type) -> DescriptorType {
             switch (type) {
                 case dawn::BindingType::UniformBuffer:
-                case dawn::BindingType::DynamicUniformBuffer:
                     return UNIFORM_BUFFER;
                 case dawn::BindingType::Sampler:
                     return SAMPLER;
                 case dawn::BindingType::SampledTexture:
                     return SAMPLED_IMAGE;
                 case dawn::BindingType::StorageBuffer:
-                case dawn::BindingType::DynamicStorageBuffer:
                     return STORAGE_BUFFER;
                 default:
                     UNREACHABLE();
@@ -145,7 +146,8 @@
 
             if (descriptorTypeIndex[type] == -1) {
                 descriptorTypeIndex[type] = numSizes;
-                result[numSizes].type = VulkanDescriptorType(info.types[bindingIndex]);
+                result[numSizes].type =
+                    VulkanDescriptorType(info.types[bindingIndex], info.dynamic[bindingIndex]);
                 result[numSizes].descriptorCount = 1;
                 numSizes++;
             } else {
diff --git a/src/dawn_native/vulkan/BindGroupLayoutVk.h b/src/dawn_native/vulkan/BindGroupLayoutVk.h
index 6a6d8cd..37cfbc5 100644
--- a/src/dawn_native/vulkan/BindGroupLayoutVk.h
+++ b/src/dawn_native/vulkan/BindGroupLayoutVk.h
@@ -23,7 +23,7 @@
 
     class Device;
 
-    VkDescriptorType VulkanDescriptorType(dawn::BindingType type);
+    VkDescriptorType VulkanDescriptorType(dawn::BindingType type, bool isDynamic);
 
     class BindGroupLayout : public BindGroupLayoutBase {
       public:
diff --git a/src/dawn_native/vulkan/BindGroupVk.cpp b/src/dawn_native/vulkan/BindGroupVk.cpp
index a1ef1c7..f321c68 100644
--- a/src/dawn_native/vulkan/BindGroupVk.cpp
+++ b/src/dawn_native/vulkan/BindGroupVk.cpp
@@ -77,13 +77,12 @@
             write.dstBinding = bindingIndex;
             write.dstArrayElement = 0;
             write.descriptorCount = 1;
-            write.descriptorType = VulkanDescriptorType(layoutInfo.types[bindingIndex]);
+            write.descriptorType = VulkanDescriptorType(layoutInfo.types[bindingIndex],
+                                                        layoutInfo.dynamic[bindingIndex]);
 
             switch (layoutInfo.types[bindingIndex]) {
                 case dawn::BindingType::UniformBuffer:
-                case dawn::BindingType::StorageBuffer:
-                case dawn::BindingType::DynamicUniformBuffer:
-                case dawn::BindingType::DynamicStorageBuffer: {
+                case dawn::BindingType::StorageBuffer: {
                     BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
 
                     writeBufferInfo[numWrites].buffer = ToBackend(binding.buffer)->GetHandle();
diff --git a/src/tests/end2end/DynamicBufferOffsetTests.cpp b/src/tests/end2end/DynamicBufferOffsetTests.cpp
index d880a74..cfb89a0 100644
--- a/src/tests/end2end/DynamicBufferOffsetTests.cpp
+++ b/src/tests/end2end/DynamicBufferOffsetTests.cpp
@@ -47,9 +47,9 @@
 
         mBindGroupLayout = utils::MakeBindGroupLayout(
             device, {{0, dawn::ShaderStageBit::Compute | dawn::ShaderStageBit::Fragment,
-                      dawn::BindingType::DynamicUniformBuffer},
+                      dawn::BindingType::UniformBuffer, true},
                      {1, dawn::ShaderStageBit::Compute | dawn::ShaderStageBit::Fragment,
-                      dawn::BindingType::DynamicStorageBuffer}});
+                      dawn::BindingType::StorageBuffer, true}});
 
         mBindGroup = utils::MakeBindGroup(
             device, mBindGroupLayout,
diff --git a/src/tests/unittests/validation/BindGroupValidationTests.cpp b/src/tests/unittests/validation/BindGroupValidationTests.cpp
index bcccdb5..db7dfd1 100644
--- a/src/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -456,9 +456,9 @@
     void SetUp() override {
         mBindGroupLayout = utils::MakeBindGroupLayout(
             device, {{0, dawn::ShaderStageBit::Compute | dawn::ShaderStageBit::Fragment,
-                      dawn::BindingType::DynamicUniformBuffer},
+                      dawn::BindingType::UniformBuffer, true},
                      {1, dawn::ShaderStageBit::Compute | dawn::ShaderStageBit::Fragment,
-                      dawn::BindingType::DynamicStorageBuffer}});
+                      dawn::BindingType::StorageBuffer, true}});
     }
 
     dawn::Buffer CreateBuffer(uint64_t bufferSize, dawn::BufferUsageBit usage) {