D3D11: assign separate native binding index for each stage.
Previously we used the same D3D binding index counter for all stages
even if some resources are not used in some stages.
For example. a BindGroup with 3 buffers:
- buffer A, visibility=Fragment
- buffer B, visibility=Vertex
- buffer C, visibility=Fragment
They would be assigned to:
- buffer A: PS slot 0.
- VS slot 0 is skipped.
- buffer B: VS slot 1.
- PS slot 1 is skipped.
- buffer C: PS slot 2.
- VS slot 2 is skipped.
It resulted in:
- VS slot 0 and 2 would be wasted and wouldn't be used by any resource.
- PS slot 1 would be wasted.
This CL changes the binding indices' assignment logic such that each
stage has its own counter. Thus, the above buffers would be assigned to:
- buffer A: PS slot 0.
- buffer B: VS slot 0.
- buffer C: PS slot 1.
This will also make the resources' stage specific indices continuous.
It makes it possible to bind all resources in one D3D call if we want
to in future.
Bug: 42240704
Change-Id: Ib70c5f32ccbbdff03212bc2b7d3cc1b76154fc9c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/234974
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
index fd5e671..a5d0566 100644
--- a/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
+++ b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
@@ -300,13 +300,25 @@
BindGroupBase* group = mBindGroups[index];
const ityp::vector<BindingIndex, uint64_t>& dynamicOffsets = mDynamicOffsets[index];
- const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[index];
+ const auto& indices = ToBackend(mPipelineLayout)->GetBindingTableIndexMap()[index];
for (BindingIndex bindingIndex : Range(group->GetLayout()->GetBindingCount())) {
const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
- const uint32_t bindingSlot = indices[bindingIndex];
const auto bindingVisibility = bindingInfo.visibility & kVisibleStage;
+ uint32_t bindingSlotVS;
+ uint32_t bindingSlotPS;
+ uint32_t bindingSlotCS;
+ if (bindingVisibility & kVisibleVertex) {
+ bindingSlotVS = indices[bindingIndex][SingleShaderStage::Vertex];
+ }
+ if (bindingVisibility & kVisibleFragment) {
+ bindingSlotPS = indices[bindingIndex][SingleShaderStage::Fragment];
+ }
+ if (bindingVisibility & kVisibleCompute) {
+ bindingSlotCS = indices[bindingIndex][SingleShaderStage::Compute];
+ }
+
DAWN_TRY(MatchVariant(
bindingInfo.bindingLayout,
[&](const BufferBindingInfo& layout) -> MaybeError {
@@ -335,15 +347,15 @@
binding.buffer->GetAllocatedSize());
if (bindingVisibility & kVisibleVertex) {
- this->VSSetConstantBuffer(bindingSlot, d3d11Buffer, firstConstant,
+ this->VSSetConstantBuffer(bindingSlotVS, d3d11Buffer, firstConstant,
numConstants);
}
if (bindingVisibility & kVisibleFragment) {
- this->PSSetConstantBuffer(bindingSlot, d3d11Buffer, firstConstant,
+ this->PSSetConstantBuffer(bindingSlotPS, d3d11Buffer, firstConstant,
numConstants);
}
if (bindingVisibility & kVisibleCompute) {
- this->CSSetConstantBuffer(bindingSlot, d3d11Buffer, firstConstant,
+ this->CSSetConstantBuffer(bindingSlotCS, d3d11Buffer, firstConstant,
numConstants);
}
break;
@@ -358,7 +370,7 @@
DAWN_TRY_ASSIGN(d3d11UAV,
ToGPUUsableBuffer(binding.buffer)
->UseAsUAV(mCommandContext, offset, binding.size));
- this->CSSetUnorderedAccessView(bindingSlot, d3d11UAV);
+ this->CSSetUnorderedAccessView(bindingSlotCS, d3d11UAV);
}
break;
}
@@ -369,13 +381,13 @@
ToGPUUsableBuffer(binding.buffer)
->UseAsSRV(mCommandContext, offset, binding.size));
if (bindingVisibility & kVisibleVertex) {
- this->VSSetShaderResource(bindingSlot, d3d11SRV);
+ this->VSSetShaderResource(bindingSlotVS, d3d11SRV);
}
if (bindingVisibility & kVisibleFragment) {
- this->PSSetShaderResource(bindingSlot, d3d11SRV);
+ this->PSSetShaderResource(bindingSlotPS, d3d11SRV);
}
if (bindingVisibility & kVisibleCompute) {
- this->CSSetShaderResource(bindingSlot, d3d11SRV);
+ this->CSSetShaderResource(bindingSlotCS, d3d11SRV);
}
break;
}
@@ -395,13 +407,13 @@
Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
ID3D11SamplerState* d3d11SamplerState = sampler->GetD3D11SamplerState();
if (bindingVisibility & kVisibleVertex) {
- this->VSSetSampler(bindingSlot, d3d11SamplerState);
+ this->VSSetSampler(bindingSlotVS, d3d11SamplerState);
}
if (bindingVisibility & kVisibleFragment) {
- this->PSSetSampler(bindingSlot, d3d11SamplerState);
+ this->PSSetSampler(bindingSlotPS, d3d11SamplerState);
}
if (bindingVisibility & kVisibleCompute) {
- this->CSSetSampler(bindingSlot, d3d11SamplerState);
+ this->CSSetSampler(bindingSlotCS, d3d11SamplerState);
}
return {};
},
@@ -416,13 +428,13 @@
DAWN_TRY_ASSIGN(srv, view->GetOrCreateD3D11ShaderResourceView());
}
if (bindingVisibility & kVisibleVertex) {
- this->VSSetShaderResource(bindingSlot, srv);
+ this->VSSetShaderResource(bindingSlotVS, srv);
}
if (bindingVisibility & kVisibleFragment) {
- this->PSSetShaderResource(bindingSlot, srv);
+ this->PSSetShaderResource(bindingSlotPS, srv);
}
if (bindingVisibility & kVisibleCompute) {
- this->CSSetShaderResource(bindingSlot, srv);
+ this->CSSetShaderResource(bindingSlotCS, srv);
}
return {};
},
@@ -437,7 +449,7 @@
if (bindingVisibility & kVisibleCompute) {
ID3D11UnorderedAccessView* d3d11UAV = nullptr;
DAWN_TRY_ASSIGN(d3d11UAV, view->GetOrCreateD3D11UnorderedAccessView());
- this->CSSetUnorderedAccessView(bindingSlot, d3d11UAV);
+ this->CSSetUnorderedAccessView(bindingSlotCS, d3d11UAV);
}
break;
}
@@ -445,13 +457,13 @@
ID3D11ShaderResourceView* d3d11SRV = nullptr;
DAWN_TRY_ASSIGN(d3d11SRV, view->GetOrCreateD3D11ShaderResourceView());
if (bindingVisibility & kVisibleVertex) {
- this->VSSetShaderResource(bindingSlot, d3d11SRV);
+ this->VSSetShaderResource(bindingSlotVS, d3d11SRV);
}
if (bindingVisibility & kVisibleFragment) {
- this->PSSetShaderResource(bindingSlot, d3d11SRV);
+ this->PSSetShaderResource(bindingSlotPS, d3d11SRV);
}
if (bindingVisibility & kVisibleCompute) {
- this->CSSetShaderResource(bindingSlot, d3d11SRV);
+ this->CSSetShaderResource(bindingSlotCS, d3d11SRV);
}
break;
}
@@ -481,11 +493,11 @@
void ComputePassBindGroupTracker::UnapplyComputeBindings(BindGroupIndex index) {
const BindGroupLayoutInternalBase* groupLayout =
mLastAppliedPipelineLayout->GetBindGroupLayout(index);
- const auto& indices = ToBackend(mLastAppliedPipelineLayout)->GetBindingIndexInfo()[index];
+ const auto& indices = ToBackend(mLastAppliedPipelineLayout)->GetBindingTableIndexMap()[index];
for (BindingIndex bindingIndex : Range(groupLayout->GetBindingCount())) {
const BindingInfo& bindingInfo = groupLayout->GetBindingInfo(bindingIndex);
- const uint32_t bindingSlot = indices[bindingIndex];
+ const uint32_t bindingSlot = indices[bindingIndex][SingleShaderStage::Compute];
if (!(bindingInfo.visibility & wgpu::ShaderStage::Compute)) {
continue;
}
@@ -586,28 +598,26 @@
// As D3d11 requires to bind all UAVs slots at the same time for pixel shaders, we record
// all UAV slot assignments in the bind groups, and then bind them all together.
- // TODO(crbug.com/366291600): Clean up D3D11 logic, replace following getters with
- // GetUAVCount() and GetUAVStartSlot(). Clean up related validations.
const BindGroupMask uavBindGroups = ToBackend(mPipelineLayout)->GetUAVBindGroupLayoutsMask();
- const uint32_t uavSlotCount = ToBackend(mPipelineLayout)->GetTotalUAVBindingCount();
const uint32_t plsSlotCount = ToBackend(mPipelineLayout)->GetPLSSlotCount();
- const uint32_t unusedUavCount = ToBackend(mPipelineLayout)->GetUnusedUAVBindingCount();
+ const uint32_t uavStartSlot =
+ ToBackend(mPipelineLayout)->GetUAVStartIndex(SingleShaderStage::Fragment);
+ const uint32_t uavCount = ToBackend(mPipelineLayout)->GetUAVCount(SingleShaderStage::Fragment);
- DAWN_ASSERT(uavSlotCount >= unusedUavCount + plsSlotCount);
- const uint32_t usedUavCount = uavSlotCount - unusedUavCount - plsSlotCount;
+ DAWN_ASSERT(uavCount >= plsSlotCount);
+ const uint32_t usedUavCount = uavCount - plsSlotCount;
- const uint32_t uavStartSlot = unusedUavCount;
- std::vector<ComPtr<ID3D11UnorderedAccessView>> uavsInBindGroup(usedUavCount);
+ absl::InlinedVector<ComPtr<ID3D11UnorderedAccessView>, 1> uavsInBindGroup(usedUavCount);
for (BindGroupIndex index : IterateBitSet(uavBindGroups)) {
BindGroupBase* group = mBindGroups[index];
const ityp::vector<BindingIndex, uint64_t>& dynamicOffsets = mDynamicOffsets[index];
- const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[index];
+ const auto& indices = ToBackend(mPipelineLayout)->GetBindingTableIndexMap()[index];
// D3D11 uav slot allocated in reverse order.
for (BindingIndex bindingIndex : Range(group->GetLayout()->GetBindingCount())) {
const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
- uint32_t pos = indices[bindingIndex] - uavStartSlot;
+ uint32_t pos = indices[bindingIndex][SingleShaderStage::Fragment] - uavStartSlot;
DAWN_TRY(MatchVariant(
bindingInfo.bindingLayout,
[&](const BufferBindingInfo& layout) -> MaybeError {
diff --git a/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp b/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp
index 1c3dde3..f83cbd2 100644
--- a/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp
+++ b/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp
@@ -44,82 +44,117 @@
}
MaybeError PipelineLayout::Initialize(Device* device) {
- unsigned int constantBufferIndex = 0;
- unsigned int samplerIndex = 0;
- unsigned int shaderResourceViewIndex = 0;
+ const PerStage<uint32_t> kInvalidSlots = PerStage<uint32_t>(PipelineLayout::kInvalidSlot);
+
+ PerStage<uint32_t> constantBufferCounter(0);
+ PerStage<uint32_t> samplerCounter(0);
+ PerStage<uint32_t> shaderResourceViewCounter(0);
+
// For d3d11 pixel shaders, the render targets and unordered-access views share the same
// resource slots when being written out. So we assign UAV binding index decreasingly here.
// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews
// TODO(dawn:1818): Support testing on both FL11_0 and FL11_1.
- mTotalUAVBindingCount = device->GetUAVSlotCount();
+ const uint32_t kUAVSlotCount = device->GetUAVSlotCount();
+ PerStage<uint32_t> uavBindingCounter(kUAVSlotCount);
// Reserve last several UAV slots for Pixel Local Storage attachments.
- uint32_t unorderedAccessViewIndex =
- mTotalUAVBindingCount - static_cast<uint32_t>(GetStorageAttachmentSlots().size());
+ uavBindingCounter[SingleShaderStage::Fragment] -=
+ static_cast<uint32_t>(GetStorageAttachmentSlots().size());
+
+ constexpr auto CountIncreasingIndex = [](wgpu::ShaderStage visibility,
+ PerStage<uint32_t>* counters) {
+ PerStage<uint32_t> nativeIndex(kInvalidSlot);
+ for (SingleShaderStage stage : IterateStages(visibility)) {
+ nativeIndex[stage] = (*counters)[stage]++;
+ }
+ return nativeIndex;
+ };
+
+ constexpr auto CountDecreasingIndex = [](wgpu::ShaderStage visibility,
+ PerStage<uint32_t>* counters) {
+ PerStage<uint32_t> nativeIndex(kInvalidSlot);
+ for (SingleShaderStage stage : IterateStages(visibility)) {
+ nativeIndex[stage] = --(*counters)[stage];
+ }
+ return nativeIndex;
+ };
+
for (BindGroupIndex group : IterateBitSet(GetBindGroupLayoutsMask())) {
const BindGroupLayoutInternalBase* bgl = GetBindGroupLayout(group);
- mIndexInfo[group].resize(bgl->GetBindingCount());
+ mBindingTableIndexMap[group].resize(bgl->GetBindingCount());
for (BindingIndex bindingIndex{0}; bindingIndex < bgl->GetBindingCount(); ++bindingIndex) {
const BindingInfo& bindingInfo = bgl->GetBindingInfo(bindingIndex);
- MatchVariant(
+
+ mBindingTableIndexMap[group][bindingIndex] = MatchVariant(
bindingInfo.bindingLayout,
- [&](const BufferBindingInfo& layout) {
+ [&](const BufferBindingInfo& layout) -> PerStage<uint32_t> {
switch (layout.type) {
case wgpu::BufferBindingType::Uniform:
- mIndexInfo[group][bindingIndex] = constantBufferIndex++;
- break;
+ return CountIncreasingIndex(bindingInfo.visibility,
+ &constantBufferCounter);
case wgpu::BufferBindingType::Storage:
case kInternalStorageBufferBinding:
- mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
mUAVBindGroups.set(group);
- break;
+ return CountDecreasingIndex(bindingInfo.visibility, &uavBindingCounter);
case wgpu::BufferBindingType::ReadOnlyStorage:
case kInternalReadOnlyStorageBufferBinding:
- mIndexInfo[group][bindingIndex] = shaderResourceViewIndex++;
- break;
+ return CountIncreasingIndex(bindingInfo.visibility,
+ &shaderResourceViewCounter);
case wgpu::BufferBindingType::BindingNotUsed:
case wgpu::BufferBindingType::Undefined:
DAWN_UNREACHABLE();
}
+ return kInvalidSlots;
},
- [&](const SamplerBindingInfo&) {
- mIndexInfo[group][bindingIndex] = samplerIndex++;
+ [&](const SamplerBindingInfo&) -> PerStage<uint32_t> {
+ return CountIncreasingIndex(bindingInfo.visibility, &samplerCounter);
},
- [&](const StaticSamplerBindingInfo&) {
+ [&](const StaticSamplerBindingInfo&) -> PerStage<uint32_t> {
// Static samplers are implemented in the frontend on
// D3D11.
DAWN_UNREACHABLE();
+ return kInvalidSlots;
},
- [&](const TextureBindingInfo&) {
- mIndexInfo[group][bindingIndex] = shaderResourceViewIndex++;
+ [&](const TextureBindingInfo&) -> PerStage<uint32_t> {
+ return CountIncreasingIndex(bindingInfo.visibility, &shaderResourceViewCounter);
},
- [&](const StorageTextureBindingInfo& layout) {
+ [&](const StorageTextureBindingInfo& layout) -> PerStage<uint32_t> {
switch (layout.access) {
case wgpu::StorageTextureAccess::ReadWrite:
case wgpu::StorageTextureAccess::WriteOnly:
- mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
mUAVBindGroups.set(group);
- break;
+ return CountDecreasingIndex(bindingInfo.visibility, &uavBindingCounter);
case wgpu::StorageTextureAccess::ReadOnly:
- mIndexInfo[group][bindingIndex] = shaderResourceViewIndex++;
- break;
+ return CountIncreasingIndex(bindingInfo.visibility,
+ &shaderResourceViewCounter);
case wgpu::StorageTextureAccess::BindingNotUsed:
case wgpu::StorageTextureAccess::Undefined:
DAWN_UNREACHABLE();
}
+ return kInvalidSlots;
},
- [](const InputAttachmentBindingInfo&) { DAWN_UNREACHABLE(); });
+ [&](const InputAttachmentBindingInfo&) -> PerStage<uint32_t> {
+ DAWN_UNREACHABLE();
+ return kInvalidSlots;
+ });
}
}
- mUnusedUAVBindingCount = unorderedAccessViewIndex;
- DAWN_ASSERT(constantBufferIndex <= kReservedConstantBufferSlot);
+
+ mUAVStartIndex = uavBindingCounter;
+ for (SingleShaderStage stage : IterateStages(kAllStages)) {
+ mUAVCount[stage] = kUAVSlotCount - mUAVStartIndex[stage];
+ }
+
+ for (SingleShaderStage stage : IterateStages(kAllStages)) {
+ DAWN_ASSERT(constantBufferCounter[stage] <= kReservedConstantBufferSlot);
+ }
return {};
}
-const PipelineLayout::BindingIndexInfo& PipelineLayout::GetBindingIndexInfo() const {
- return mIndexInfo;
+const PipelineLayout::BindingTableIndexMap& PipelineLayout::GetBindingTableIndexMap() const {
+ return mBindingTableIndexMap;
}
const BindGroupMask& PipelineLayout::GetUAVBindGroupLayoutsMask() const {
diff --git a/src/dawn/native/d3d11/PipelineLayoutD3D11.h b/src/dawn/native/d3d11/PipelineLayoutD3D11.h
index d735575..9950c12 100644
--- a/src/dawn/native/d3d11/PipelineLayoutD3D11.h
+++ b/src/dawn/native/d3d11/PipelineLayoutD3D11.h
@@ -33,6 +33,7 @@
#include "dawn/common/ityp_array.h"
#include "dawn/common/ityp_vector.h"
#include "dawn/native/BindingInfo.h"
+#include "dawn/native/PerStage.h"
#include "dawn/native/d3d/d3d_platform.h"
namespace dawn::native::d3d11 {
@@ -59,15 +60,18 @@
static constexpr uint32_t kReservedConstantsBindGroupIndex = kMaxBindGroups;
static constexpr uint32_t kFirstIndexOffsetBindingNumber = 0u;
+ static constexpr uint32_t kInvalidSlot = 0xffffffff;
+
static ResultOrError<Ref<PipelineLayout>> Create(
Device* device,
const UnpackedPtr<PipelineLayoutDescriptor>& descriptor);
- using BindingIndexInfo = PerBindGroup<ityp::vector<BindingIndex, uint32_t>>;
- const BindingIndexInfo& GetBindingIndexInfo() const;
+ // BindingTableIndexMap is a mapping from BindingIndex to D3D binding table's index.
+ using BindingTableIndexMap = PerBindGroup<ityp::vector<BindingIndex, PerStage<uint32_t>>>;
+ const BindingTableIndexMap& GetBindingTableIndexMap() const;
- uint32_t GetUnusedUAVBindingCount() const { return mUnusedUAVBindingCount; }
- uint32_t GetTotalUAVBindingCount() const { return mTotalUAVBindingCount; }
+ uint32_t GetUAVStartIndex(SingleShaderStage stage) const { return mUAVStartIndex[stage]; }
+ uint32_t GetUAVCount(SingleShaderStage stage) const { return mUAVCount[stage]; }
uint32_t GetPLSSlotCount() const {
return static_cast<uint32_t>(GetStorageAttachmentSlots().size());
}
@@ -82,10 +86,10 @@
MaybeError Initialize(Device* device);
- BindingIndexInfo mIndexInfo;
+ BindingTableIndexMap mBindingTableIndexMap;
- uint32_t mUnusedUAVBindingCount = 0u;
- uint32_t mTotalUAVBindingCount = 0u;
+ PerStage<uint32_t> mUAVStartIndex = PerStage<uint32_t>(0u);
+ PerStage<uint32_t> mUAVCount = PerStage<uint32_t>(0u);
BindGroupMask mUAVBindGroups = 0;
};
diff --git a/src/dawn/native/d3d11/RenderPipelineD3D11.cpp b/src/dawn/native/d3d11/RenderPipelineD3D11.cpp
index a4cdcd5..31472f5 100644
--- a/src/dawn/native/d3d11/RenderPipelineD3D11.cpp
+++ b/src/dawn/native/d3d11/RenderPipelineD3D11.cpp
@@ -243,14 +243,14 @@
// slots.
uint32_t colorAttachments =
static_cast<uint8_t>(GetHighestBitIndexPlusOne(GetColorAttachmentsMask()));
- uint32_t unusedUAVs = ToBackend(GetLayout())->GetUnusedUAVBindingCount();
- uint32_t usedUAVs = ToBackend(GetLayout())->GetTotalUAVBindingCount() - unusedUAVs;
+ uint32_t startUAVIndex = ToBackend(GetLayout())->GetUAVStartIndex(SingleShaderStage::Fragment);
+ uint32_t usedUAVs = ToBackend(GetLayout())->GetUAVCount(SingleShaderStage::Fragment);
// TODO(dawn:1814): Move the validation to the frontend, if we eventually regard it as a compat
// restriction.
- DAWN_INVALID_IF(colorAttachments > unusedUAVs,
+ DAWN_INVALID_IF(colorAttachments > startUAVIndex,
"The pipeline uses up to color attachment %u, but there are only %u remaining "
"slots because the pipeline uses %u UAVs",
- colorAttachments, unusedUAVs, usedUAVs);
+ colorAttachments, startUAVIndex, usedUAVs);
SetLabelImpl();
return {};
@@ -485,14 +485,15 @@
if (GetAttachmentState()->HasPixelLocalStorage()) {
const std::vector<wgpu::TextureFormat>& storageAttachmentSlots =
GetAttachmentState()->GetStorageAttachmentSlots();
- DAWN_ASSERT(ToBackend(GetLayout())->GetTotalUAVBindingCount() >
- storageAttachmentSlots.size());
+ const uint32_t uavEndIndex =
+ ToBackend(GetLayout())->GetUAVStartIndex(SingleShaderStage::Fragment) +
+ ToBackend(GetLayout())->GetUAVCount(SingleShaderStage::Fragment);
+ DAWN_ASSERT(uavEndIndex > storageAttachmentSlots.size());
// Currently all the pixel local storage UAVs are allocated at the last several UAV
// slots. For example, when there are 4 pixel local storage attachments, we will
// allocate register u60 to u63 for them.
- uint32_t basePixelLocalAttachmentIndex =
- ToBackend(GetLayout())->GetTotalUAVBindingCount() -
- static_cast<uint32_t>(storageAttachmentSlots.size());
+ const uint32_t basePixelLocalAttachmentIndex =
+ uavEndIndex - static_cast<uint32_t>(storageAttachmentSlots.size());
for (size_t i = 0; i < storageAttachmentSlots.size(); i++) {
auto& attachment = pixelLocalOptions->attachments[i];
attachment.index = basePixelLocalAttachmentIndex + i;
diff --git a/src/dawn/native/d3d11/ShaderModuleD3D11.cpp b/src/dawn/native/d3d11/ShaderModuleD3D11.cpp
index fd49b2f..2bab7a1 100644
--- a/src/dawn/native/d3d11/ShaderModuleD3D11.cpp
+++ b/src/dawn/native/d3d11/ShaderModuleD3D11.cpp
@@ -122,14 +122,16 @@
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
const BindGroupLayout* bgl = ToBackend(layout->GetBindGroupLayout(group));
- const auto& indices = layout->GetBindingIndexInfo()[group];
+ const auto& indices = layout->GetBindingTableIndexMap()[group];
const BindingGroupInfoMap& moduleGroupBindingInfo = moduleBindingInfo[group];
for (const auto& [binding, shaderBindingInfo] : moduleGroupBindingInfo) {
BindingIndex bindingIndex = bgl->GetBindingIndex(binding);
tint::BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
static_cast<uint32_t>(binding)};
- tint::BindingPoint dstBindingPoint{0u, indices[bindingIndex]};
+ tint::BindingPoint dstBindingPoint{0u, indices[bindingIndex][stage]};
+ DAWN_ASSERT(dstBindingPoint.binding != PipelineLayout::kInvalidSlot);
+
auto* const bufferBindingInfo =
std::get_if<BufferBindingInfo>(&shaderBindingInfo.bindingInfo);
@@ -174,11 +176,11 @@
const auto& bindingExpansion = expansion->second;
tint::hlsl::writer::binding::BindingInfo plane0{
- 0u, indices[bgl->GetBindingIndex(bindingExpansion.plane0)]};
+ 0u, indices[bgl->GetBindingIndex(bindingExpansion.plane0)][stage]};
tint::hlsl::writer::binding::BindingInfo plane1{
- 0u, indices[bgl->GetBindingIndex(bindingExpansion.plane1)]};
+ 0u, indices[bgl->GetBindingIndex(bindingExpansion.plane1)][stage]};
tint::hlsl::writer::binding::BindingInfo metadata{
- 0u, indices[bgl->GetBindingIndex(bindingExpansion.params)]};
+ 0u, indices[bgl->GetBindingIndex(bindingExpansion.params)][stage]};
bindings.external_texture.emplace(
srcBindingPoint,
tint::hlsl::writer::binding::ExternalTexture{metadata, plane0, plane1});