Convert LayoutBindingInfo to an array of BindingInfos

This makes accessing per-index data simpler, and now that dynamic
buffer bindings are packed at the front, the old IterateBitset on
the dynamic buffer binding mask can be replaced with a simple loop
over the beginning bindings.

Bug: dawn:354
Change-Id: I1adf371c3228690758f90ab1f0de88ad8d0f950d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/17681
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/d3d12/BindGroupD3D12.cpp b/src/dawn_native/d3d12/BindGroupD3D12.cpp
index 6ef4bc2..92a1445 100644
--- a/src/dawn_native/d3d12/BindGroupD3D12.cpp
+++ b/src/dawn_native/d3d12/BindGroupD3D12.cpp
@@ -81,21 +81,21 @@
         mLastUsageSerial = pendingSerial;
         mHeapSerial = allocator->GetShaderVisibleHeapsSerial();
 
-        const BindGroupLayoutBase::LayoutBindingInfo& layout = bgl->GetBindingInfo();
-
         const auto& bindingOffsets = bgl->GetBindingOffsets();
 
         ID3D12Device* d3d12Device = device->GetD3D12Device().Get();
 
-        for (BindingIndex bindingIndex = 0; bindingIndex < layout.bindingCount; ++bindingIndex) {
+        for (BindingIndex bindingIndex = 0; bindingIndex < bgl->GetBindingCount(); ++bindingIndex) {
+            const BindGroupLayoutBase::BindingInfo& bindingInfo = bgl->GetBindingInfo(bindingIndex);
+
             // It's not necessary to create descriptors in descriptor heap for dynamic
             // resources. So skip allocating descriptors in descriptor heaps for dynamic
             // buffers.
-            if (layout.hasDynamicOffset[bindingIndex]) {
+            if (bindingInfo.hasDynamicOffset) {
                 continue;
             }
 
-            switch (layout.types[bindingIndex]) {
+            switch (bindingInfo.type) {
                 case wgpu::BindingType::UniformBuffer: {
                     BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
 
diff --git a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
index 50a4b03..7d07611 100644
--- a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
+++ b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
@@ -45,18 +45,17 @@
         : BindGroupLayoutBase(device, descriptor),
           mDescriptorCounts{},
           mBindGroupAllocator(MakeFrontendBindGroupAllocator<BindGroup>(4096)) {
-        const BindGroupLayoutBase::LayoutBindingInfo& groupInfo = GetBindingInfo();
+        for (BindingIndex bindingIndex = GetDynamicBufferCount(); bindingIndex < GetBindingCount();
+             ++bindingIndex) {
+            const BindGroupLayoutBase::BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
 
-        for (BindingIndex bindingIndex = 0; bindingIndex < groupInfo.bindingCount; ++bindingIndex) {
             // For dynamic resources, Dawn uses root descriptor in D3D12 backend.
-            // So there is no need to allocate the descriptor from descriptor heap. Skip counting
-            // dynamic resources for calculating size of descriptor heap.
-            if (groupInfo.hasDynamicOffset[bindingIndex]) {
-                continue;
-            }
+            // So there is no need to allocate the descriptor from descriptor heap.
+            // This loop starts after the dynamic buffer indices to skip counting
+            // dynamic resources in calculating the size of the descriptor heap.
+            ASSERT(!bindingInfo.hasDynamicOffset);
 
-            DescriptorType descriptorType =
-                WGPUBindingTypeToDescriptorType(groupInfo.types[bindingIndex]);
+            DescriptorType descriptorType = WGPUBindingTypeToDescriptorType(bindingInfo.type);
             mBindingOffsets[bindingIndex] = mDescriptorCounts[descriptorType]++;
         }
 
@@ -101,12 +100,14 @@
                            D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER);
         descriptorOffsets[Sampler] = 0;
 
-        for (BindingIndex bindingIndex = 0; bindingIndex < groupInfo.bindingCount; ++bindingIndex) {
-            if (groupInfo.hasDynamicOffset[bindingIndex]) {
+        for (BindingIndex bindingIndex = 0; bindingIndex < GetBindingCount(); ++bindingIndex) {
+            const BindGroupLayoutBase::BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
+
+            if (bindingInfo.hasDynamicOffset) {
                 // Dawn is using values in mBindingOffsets to decide register number in HLSL.
                 // Root descriptor needs to set this value to set correct register number in
                 // generated HLSL shader.
-                switch (groupInfo.types[bindingIndex]) {
+                switch (bindingInfo.type) {
                     case wgpu::BindingType::UniformBuffer:
                     case wgpu::BindingType::StorageBuffer:
                     case wgpu::BindingType::ReadonlyStorageBuffer:
@@ -124,8 +125,7 @@
             }
 
             // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
-            DescriptorType descriptorType =
-                WGPUBindingTypeToDescriptorType(groupInfo.types[bindingIndex]);
+            DescriptorType descriptorType = WGPUBindingTypeToDescriptorType(bindingInfo.type);
             mBindingOffsets[bindingIndex] += descriptorOffsets[descriptorType];
         }
     }
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index 385cbda..646a96e 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -196,28 +196,27 @@
                             BindGroup* group,
                             uint32_t dynamicOffsetCount,
                             const uint64_t* dynamicOffsets) {
+            ASSERT(dynamicOffsetCount == group->GetLayout()->GetDynamicBufferCount());
+
             // Usually, the application won't set the same offsets many times,
             // so always try to apply dynamic offsets even if the offsets stay the same
-            if (dynamicOffsetCount) {
-                // Update dynamic offsets
-                const BindGroupLayout::LayoutBindingInfo& layout =
-                    group->GetLayout()->GetBindingInfo();
-                uint32_t currentDynamicBufferIndex = 0;
-
-                for (uint32_t bindingIndex : IterateBitSet(layout.hasDynamicOffset)) {
-                    ASSERT(dynamicOffsetCount > 0);
+            if (dynamicOffsetCount != 0) {
+                // Update dynamic offsets.
+                // Dynamic buffer bindings are packed at the beginning of the layout.
+                for (BindingIndex bindingIndex = 0; bindingIndex < dynamicOffsetCount;
+                     ++bindingIndex) {
                     uint32_t parameterIndex =
                         pipelineLayout->GetDynamicRootParameterIndex(index, bindingIndex);
                     BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
 
                     // Calculate buffer locations that root descriptors links to. The location
                     // is (base buffer location + initial offset + dynamic offset)
-                    uint64_t dynamicOffset = dynamicOffsets[currentDynamicBufferIndex];
+                    uint64_t dynamicOffset = dynamicOffsets[bindingIndex];
                     uint64_t offset = binding.offset + dynamicOffset;
                     D3D12_GPU_VIRTUAL_ADDRESS bufferLocation =
                         ToBackend(binding.buffer)->GetVA() + offset;
 
-                    switch (layout.types[bindingIndex]) {
+                    switch (group->GetLayout()->GetBindingInfo(bindingIndex).type) {
                         case wgpu::BindingType::UniformBuffer:
                             if (mInCompute) {
                                 commandList->SetComputeRootConstantBufferView(parameterIndex,
@@ -253,8 +252,6 @@
                             UNREACHABLE();
                             break;
                     }
-
-                    ++currentDynamicBufferIndex;
                 }
             }
 
diff --git a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp
index 7afadc7..14e71f5 100644
--- a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp
+++ b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp
@@ -89,7 +89,6 @@
 
         for (uint32_t group : IterateBitSet(GetBindGroupLayoutsMask())) {
             const BindGroupLayout* bindGroupLayout = ToBackend(GetBindGroupLayout(group));
-            const BindGroupLayout::LayoutBindingInfo& groupInfo = bindGroupLayout->GetBindingInfo();
 
             // Set the root descriptor table parameter and copy ranges. Ranges are offset by the
             // bind group index Returns whether or not the parameter was set. A root parameter is
@@ -129,25 +128,30 @@
             // Get calculated shader register for root descriptors
             const auto& shaderRegisters = bindGroupLayout->GetBindingOffsets();
 
-            // Init root descriptors in root signatures.
-            for (uint32_t dynamicBinding : IterateBitSet(groupInfo.hasDynamicOffset)) {
+            // Init root descriptors in root signatures for dynamic buffer bindings.
+            // These are packed at the beginning of the layout binding info.
+            for (BindingIndex dynamicBindingIndex = 0;
+                 dynamicBindingIndex < bindGroupLayout->GetDynamicBufferCount();
+                 ++dynamicBindingIndex) {
+                const BindGroupLayoutBase::BindingInfo& bindingInfo =
+                    bindGroupLayout->GetBindingInfo(dynamicBindingIndex);
+
                 D3D12_ROOT_PARAMETER* rootParameter = &rootParameters[parameterIndex];
 
                 // Setup root descriptor.
                 D3D12_ROOT_DESCRIPTOR rootDescriptor;
-                rootDescriptor.ShaderRegister = shaderRegisters[dynamicBinding];
+                rootDescriptor.ShaderRegister = shaderRegisters[dynamicBindingIndex];
                 rootDescriptor.RegisterSpace = group;
 
                 // Set root descriptors in root signatures.
                 rootParameter->Descriptor = rootDescriptor;
-                mDynamicRootParameterIndices[group][dynamicBinding] = parameterIndex++;
+                mDynamicRootParameterIndices[group][dynamicBindingIndex] = parameterIndex++;
 
                 // Set parameter types according to bind group layout descriptor.
-                rootParameter->ParameterType = RootParameterType(groupInfo.types[dynamicBinding]);
+                rootParameter->ParameterType = RootParameterType(bindingInfo.type);
 
                 // Set visibilities according to bind group layout descriptor.
-                rootParameter->ShaderVisibility =
-                    ShaderVisibilityType(groupInfo.visibilities[dynamicBinding]);
+                rootParameter->ShaderVisibility = ShaderVisibilityType(bindingInfo.visibility);
             }
         }
 
@@ -186,10 +190,11 @@
         return mRootSignature;
     }
 
-    uint32_t PipelineLayout::GetDynamicRootParameterIndex(uint32_t group, uint32_t binding) const {
+    uint32_t PipelineLayout::GetDynamicRootParameterIndex(uint32_t group,
+                                                          BindingIndex bindingIndex) const {
         ASSERT(group < kMaxBindGroups);
-        ASSERT(binding < kMaxBindingsPerGroup);
-        ASSERT(GetBindGroupLayout(group)->GetBindingInfo().hasDynamicOffset[binding]);
-        return mDynamicRootParameterIndices[group][binding];
+        ASSERT(bindingIndex < kMaxBindingsPerGroup);
+        ASSERT(GetBindGroupLayout(group)->GetBindingInfo(bindingIndex).hasDynamicOffset);
+        return mDynamicRootParameterIndices[group][bindingIndex];
     }
 }}  // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/PipelineLayoutD3D12.h b/src/dawn_native/d3d12/PipelineLayoutD3D12.h
index 1d6c7e5..bbe3659 100644
--- a/src/dawn_native/d3d12/PipelineLayoutD3D12.h
+++ b/src/dawn_native/d3d12/PipelineLayoutD3D12.h
@@ -15,8 +15,8 @@
 #ifndef DAWNNATIVE_D3D12_PIPELINELAYOUTD3D12_H_
 #define DAWNNATIVE_D3D12_PIPELINELAYOUTD3D12_H_
 
+#include "dawn_native/IntegerTypes.h"
 #include "dawn_native/PipelineLayout.h"
-
 #include "dawn_native/d3d12/d3d12_platform.h"
 
 namespace dawn_native { namespace d3d12 {
@@ -32,7 +32,7 @@
         uint32_t GetSamplerRootParameterIndex(uint32_t group) const;
 
         // Returns the index of the root parameter reserved for a dynamic buffer binding
-        uint32_t GetDynamicRootParameterIndex(uint32_t group, uint32_t binding) const;
+        uint32_t GetDynamicRootParameterIndex(uint32_t group, BindingIndex bindingIndex) const;
 
         ComPtr<ID3D12RootSignature> GetRootSignature() const;