fix(rhi): honor firstSet in set-aware d3d12 bindings

This commit is contained in:
2026-03-26 14:43:51 +08:00
parent 476a56724f
commit 9218ea20b5
6 changed files with 529 additions and 103 deletions

View File

@@ -17,6 +17,13 @@ class D3D12Device;
class D3D12PipelineLayout : public RHIPipelineLayout {
public:
struct SetRootParameterMapping {
std::unordered_map<uint32_t, uint32_t> constantBufferRootIndices;
uint32_t shaderResourceTableRootIndex = UINT32_MAX;
uint32_t unorderedAccessTableRootIndex = UINT32_MAX;
uint32_t samplerTableRootIndex = UINT32_MAX;
};
D3D12PipelineLayout();
~D3D12PipelineLayout() override;
@@ -27,6 +34,9 @@ public:
void* GetNativeHandle() override { return m_rootSignature.Get(); }
ID3D12RootSignature* GetRootSignature() const { return m_rootSignature.Get(); }
bool UsesSetLayouts() const { return m_desc.setLayoutCount > 0 && m_desc.setLayouts != nullptr; }
uint32_t GetSetLayoutCount() const { return m_desc.setLayoutCount; }
bool HasConstantBufferBinding(uint32_t binding) const;
uint32_t GetConstantBufferRootParameterIndex(uint32_t binding) const;
bool HasShaderResourceTable() const;
@@ -35,10 +45,21 @@ public:
uint32_t GetUnorderedAccessTableRootParameterIndex() const;
bool HasSamplerTable() const;
uint32_t GetSamplerTableRootParameterIndex() const;
bool HasConstantBufferBinding(uint32_t setIndex, uint32_t binding) const;
uint32_t GetConstantBufferRootParameterIndex(uint32_t setIndex, uint32_t binding) const;
bool HasShaderResourceTable(uint32_t setIndex) const;
uint32_t GetShaderResourceTableRootParameterIndex(uint32_t setIndex) const;
bool HasUnorderedAccessTable(uint32_t setIndex) const;
uint32_t GetUnorderedAccessTableRootParameterIndex(uint32_t setIndex) const;
bool HasSamplerTable(uint32_t setIndex) const;
uint32_t GetSamplerTableRootParameterIndex(uint32_t setIndex) const;
const RHIPipelineLayoutDesc& GetDesc() const { return m_desc; }
private:
bool InitializeInternal(D3D12Device* device, const RHIPipelineLayoutDesc& desc);
bool InitializeSetAwareRootSignature();
bool InitializeFlatRootSignature();
ComPtr<ID3D12RootSignature> m_rootSignature;
D3D12Device* m_device;
@@ -47,6 +68,7 @@ private:
uint32_t m_shaderResourceTableRootIndex = UINT32_MAX;
uint32_t m_unorderedAccessTableRootIndex = UINT32_MAX;
uint32_t m_samplerTableRootIndex = UINT32_MAX;
std::vector<SetRootParameterMapping> m_setRootParameterMappings;
std::vector<DescriptorSetLayoutDesc> m_setLayouts;
std::vector<std::vector<DescriptorSetLayoutBinding>> m_setLayoutBindings;
std::vector<D3D12_ROOT_PARAMETER> m_rootParameters;

View File

@@ -197,15 +197,23 @@ void D3D12CommandList::SetGraphicsDescriptorSets(
continue;
}
const uint32_t setIndex = firstSet + i;
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
const DescriptorSetLayoutBinding& binding = bindings[bindingIndex];
const bool hasBinding = d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasConstantBufferBinding(setIndex, binding.binding)
: d3d12Layout->HasConstantBufferBinding(binding.binding);
const uint32_t rootParameterIndex = d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetConstantBufferRootParameterIndex(setIndex, binding.binding)
: d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding);
if (static_cast<DescriptorType>(binding.type) == DescriptorType::CBV &&
d3d12Layout->HasConstantBufferBinding(binding.binding) &&
hasBinding &&
d3d12Set->UploadConstantBuffer(binding.binding)) {
SetGraphicsRootConstantBufferView(
d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding),
rootParameterIndex,
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
}
}
@@ -216,28 +224,49 @@ void D3D12CommandList::SetGraphicsDescriptorSets(
}
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
if (d3d12Set->HasBindingType(DescriptorType::SRV) && d3d12Layout->HasShaderResourceTable()) {
const bool hasSrvTable = d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasShaderResourceTable(setIndex)
: d3d12Layout->HasShaderResourceTable();
const bool hasUavTable = d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasUnorderedAccessTable(setIndex)
: d3d12Layout->HasUnorderedAccessTable();
if (d3d12Set->HasBindingType(DescriptorType::SRV) && hasSrvTable) {
const uint32_t srvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::SRV);
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
if (gpuHandle.ptr != 0) {
SetGraphicsRootDescriptorTable(d3d12Layout->GetShaderResourceTableRootParameterIndex(), gpuHandle);
SetGraphicsRootDescriptorTable(
d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetShaderResourceTableRootParameterIndex(setIndex)
: d3d12Layout->GetShaderResourceTableRootParameterIndex(),
gpuHandle);
}
}
if (d3d12Set->HasBindingType(DescriptorType::UAV) && d3d12Layout->HasUnorderedAccessTable()) {
if (d3d12Set->HasBindingType(DescriptorType::UAV) && hasUavTable) {
const uint32_t uavBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::UAV);
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(uavBinding);
if (gpuHandle.ptr != 0) {
SetGraphicsRootDescriptorTable(d3d12Layout->GetUnorderedAccessTableRootParameterIndex(), gpuHandle);
SetGraphicsRootDescriptorTable(
d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetUnorderedAccessTableRootParameterIndex(setIndex)
: d3d12Layout->GetUnorderedAccessTableRootParameterIndex(),
gpuHandle);
}
}
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
HasSamplerBindings(d3d12Set) &&
d3d12Layout->HasSamplerTable()) {
(d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasSamplerTable(setIndex)
: d3d12Layout->HasSamplerTable())) {
const uint32_t samplerBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::Sampler);
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(samplerBinding);
if (gpuHandle.ptr != 0) {
SetGraphicsRootDescriptorTable(d3d12Layout->GetSamplerTableRootParameterIndex(), gpuHandle);
SetGraphicsRootDescriptorTable(
d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetSamplerTableRootParameterIndex(setIndex)
: d3d12Layout->GetSamplerTableRootParameterIndex(),
gpuHandle);
}
}
}
@@ -285,15 +314,23 @@ void D3D12CommandList::SetComputeDescriptorSets(
continue;
}
const uint32_t setIndex = firstSet + i;
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
const DescriptorSetLayoutBinding& binding = bindings[bindingIndex];
const bool hasBinding = d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasConstantBufferBinding(setIndex, binding.binding)
: d3d12Layout->HasConstantBufferBinding(binding.binding);
const uint32_t rootParameterIndex = d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetConstantBufferRootParameterIndex(setIndex, binding.binding)
: d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding);
if (static_cast<DescriptorType>(binding.type) == DescriptorType::CBV &&
d3d12Layout->HasConstantBufferBinding(binding.binding) &&
hasBinding &&
d3d12Set->UploadConstantBuffer(binding.binding)) {
m_commandList->SetComputeRootConstantBufferView(
d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding),
rootParameterIndex,
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
}
}
@@ -304,33 +341,48 @@ void D3D12CommandList::SetComputeDescriptorSets(
}
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
if (d3d12Set->HasBindingType(DescriptorType::SRV) && d3d12Layout->HasShaderResourceTable()) {
const bool hasSrvTable = d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasShaderResourceTable(setIndex)
: d3d12Layout->HasShaderResourceTable();
const bool hasUavTable = d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasUnorderedAccessTable(setIndex)
: d3d12Layout->HasUnorderedAccessTable();
if (d3d12Set->HasBindingType(DescriptorType::SRV) && hasSrvTable) {
const uint32_t srvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::SRV);
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
if (gpuHandle.ptr != 0) {
m_commandList->SetComputeRootDescriptorTable(
d3d12Layout->GetShaderResourceTableRootParameterIndex(),
d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetShaderResourceTableRootParameterIndex(setIndex)
: d3d12Layout->GetShaderResourceTableRootParameterIndex(),
gpuHandle);
}
}
if (d3d12Set->HasBindingType(DescriptorType::UAV) && d3d12Layout->HasUnorderedAccessTable()) {
if (d3d12Set->HasBindingType(DescriptorType::UAV) && hasUavTable) {
const uint32_t uavBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::UAV);
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(uavBinding);
if (gpuHandle.ptr != 0) {
m_commandList->SetComputeRootDescriptorTable(
d3d12Layout->GetUnorderedAccessTableRootParameterIndex(),
d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetUnorderedAccessTableRootParameterIndex(setIndex)
: d3d12Layout->GetUnorderedAccessTableRootParameterIndex(),
gpuHandle);
}
}
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
HasSamplerBindings(d3d12Set) &&
d3d12Layout->HasSamplerTable()) {
(d3d12Layout->UsesSetLayouts()
? d3d12Layout->HasSamplerTable(setIndex)
: d3d12Layout->HasSamplerTable())) {
const uint32_t samplerBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::Sampler);
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(samplerBinding);
if (gpuHandle.ptr != 0) {
m_commandList->SetComputeRootDescriptorTable(
d3d12Layout->GetSamplerTableRootParameterIndex(),
d3d12Layout->UsesSetLayouts()
? d3d12Layout->GetSamplerTableRootParameterIndex(setIndex)
: d3d12Layout->GetSamplerTableRootParameterIndex(),
gpuHandle);
}
}

View File

@@ -1,6 +1,8 @@
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
#include "XCEngine/RHI/D3D12/D3D12Device.h"
#include <algorithm>
namespace XCEngine {
namespace RHI {
@@ -28,6 +30,52 @@ void AccumulateDescriptorCounts(const DescriptorSetLayoutDesc& setLayout, RHIPip
}
}
uint32_t CountBindingEntriesOfType(const DescriptorSetLayoutDesc& setLayout, DescriptorType type) {
uint32_t count = 0;
for (uint32_t bindingIndex = 0; bindingIndex < setLayout.bindingCount; ++bindingIndex) {
if (static_cast<DescriptorType>(setLayout.bindings[bindingIndex].type) == type) {
++count;
}
}
return count;
}
uint32_t SumDescriptorCountOfType(const DescriptorSetLayoutDesc& setLayout, DescriptorType type) {
uint32_t count = 0;
for (uint32_t bindingIndex = 0; bindingIndex < setLayout.bindingCount; ++bindingIndex) {
const DescriptorSetLayoutBinding& binding = setLayout.bindings[bindingIndex];
if (static_cast<DescriptorType>(binding.type) == type) {
count += binding.count > 0 ? binding.count : 1u;
}
}
return count;
}
std::vector<const DescriptorSetLayoutBinding*> GatherBindingsOfTypeSorted(
const DescriptorSetLayoutDesc& setLayout,
DescriptorType type) {
std::vector<const DescriptorSetLayoutBinding*> bindings;
bindings.reserve(setLayout.bindingCount);
for (uint32_t bindingIndex = 0; bindingIndex < setLayout.bindingCount; ++bindingIndex) {
const DescriptorSetLayoutBinding& binding = setLayout.bindings[bindingIndex];
if (static_cast<DescriptorType>(binding.type) == type) {
bindings.push_back(&binding);
}
}
std::sort(
bindings.begin(),
bindings.end(),
[](const DescriptorSetLayoutBinding* left, const DescriptorSetLayoutBinding* right) {
return left->binding < right->binding;
});
return bindings;
}
} // namespace
D3D12PipelineLayout::D3D12PipelineLayout()
@@ -88,7 +136,315 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
m_shaderResourceTableRootIndex = UINT32_MAX;
m_unorderedAccessTableRootIndex = UINT32_MAX;
m_samplerTableRootIndex = UINT32_MAX;
m_setRootParameterMappings.clear();
if (UsesSetLayouts()) {
if (!InitializeSetAwareRootSignature()) {
return false;
}
} else {
if (!InitializeFlatRootSignature()) {
return false;
}
}
D3D12_ROOT_SIGNATURE_DESC rootSigDesc = D3D12RootSignature::CreateDesc(
m_rootParameters.empty() ? nullptr : m_rootParameters.data(),
static_cast<uint32_t>(m_rootParameters.size()),
nullptr, 0,
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
ID3D12Device* d3d12Device = device->GetDevice();
if (!d3d12Device) {
return false;
}
ID3DBlob* signature = nullptr;
ID3DBlob* error = nullptr;
HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
if (FAILED(hr)) {
if (error) {
error->Release();
}
return false;
}
hr = d3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature));
signature->Release();
if (FAILED(hr)) {
return false;
}
return true;
}
void D3D12PipelineLayout::Shutdown() {
m_rootSignature.Reset();
m_desc = {};
m_rootParameters.clear();
m_descriptorRanges.clear();
m_constantBufferRootIndices.clear();
m_shaderResourceTableRootIndex = UINT32_MAX;
m_unorderedAccessTableRootIndex = UINT32_MAX;
m_samplerTableRootIndex = UINT32_MAX;
m_setRootParameterMappings.clear();
m_setLayouts.clear();
m_setLayoutBindings.clear();
m_device = nullptr;
}
bool D3D12PipelineLayout::HasConstantBufferBinding(uint32_t binding) const {
if (UsesSetLayouts()) {
return HasConstantBufferBinding(0, binding);
}
return m_constantBufferRootIndices.find(binding) != m_constantBufferRootIndices.end();
}
uint32_t D3D12PipelineLayout::GetConstantBufferRootParameterIndex(uint32_t binding) const {
if (UsesSetLayouts()) {
return GetConstantBufferRootParameterIndex(0, binding);
}
auto it = m_constantBufferRootIndices.find(binding);
if (it != m_constantBufferRootIndices.end()) {
return it->second;
}
return UINT32_MAX;
}
bool D3D12PipelineLayout::HasShaderResourceTable() const {
if (UsesSetLayouts()) {
return HasShaderResourceTable(0);
}
return m_shaderResourceTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetShaderResourceTableRootParameterIndex() const {
if (UsesSetLayouts()) {
return GetShaderResourceTableRootParameterIndex(0);
}
return m_shaderResourceTableRootIndex;
}
bool D3D12PipelineLayout::HasUnorderedAccessTable() const {
if (UsesSetLayouts()) {
return HasUnorderedAccessTable(0);
}
return m_unorderedAccessTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetUnorderedAccessTableRootParameterIndex() const {
if (UsesSetLayouts()) {
return GetUnorderedAccessTableRootParameterIndex(0);
}
return m_unorderedAccessTableRootIndex;
}
bool D3D12PipelineLayout::HasSamplerTable() const {
if (UsesSetLayouts()) {
return HasSamplerTable(0);
}
return m_samplerTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetSamplerTableRootParameterIndex() const {
if (UsesSetLayouts()) {
return GetSamplerTableRootParameterIndex(0);
}
return m_samplerTableRootIndex;
}
bool D3D12PipelineLayout::HasConstantBufferBinding(uint32_t setIndex, uint32_t binding) const {
if (!UsesSetLayouts()) {
return setIndex == 0 && HasConstantBufferBinding(binding);
}
if (setIndex >= m_setRootParameterMappings.size()) {
return false;
}
return m_setRootParameterMappings[setIndex].constantBufferRootIndices.find(binding) !=
m_setRootParameterMappings[setIndex].constantBufferRootIndices.end();
}
uint32_t D3D12PipelineLayout::GetConstantBufferRootParameterIndex(uint32_t setIndex, uint32_t binding) const {
if (!UsesSetLayouts()) {
return setIndex == 0 ? GetConstantBufferRootParameterIndex(binding) : UINT32_MAX;
}
if (setIndex >= m_setRootParameterMappings.size()) {
return UINT32_MAX;
}
const auto& rootIndices = m_setRootParameterMappings[setIndex].constantBufferRootIndices;
auto it = rootIndices.find(binding);
if (it != rootIndices.end()) {
return it->second;
}
return UINT32_MAX;
}
bool D3D12PipelineLayout::HasShaderResourceTable(uint32_t setIndex) const {
if (!UsesSetLayouts()) {
return setIndex == 0 && HasShaderResourceTable();
}
return setIndex < m_setRootParameterMappings.size() &&
m_setRootParameterMappings[setIndex].shaderResourceTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetShaderResourceTableRootParameterIndex(uint32_t setIndex) const {
if (!UsesSetLayouts()) {
return setIndex == 0 ? GetShaderResourceTableRootParameterIndex() : UINT32_MAX;
}
return setIndex < m_setRootParameterMappings.size()
? m_setRootParameterMappings[setIndex].shaderResourceTableRootIndex
: UINT32_MAX;
}
bool D3D12PipelineLayout::HasUnorderedAccessTable(uint32_t setIndex) const {
if (!UsesSetLayouts()) {
return setIndex == 0 && HasUnorderedAccessTable();
}
return setIndex < m_setRootParameterMappings.size() &&
m_setRootParameterMappings[setIndex].unorderedAccessTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetUnorderedAccessTableRootParameterIndex(uint32_t setIndex) const {
if (!UsesSetLayouts()) {
return setIndex == 0 ? GetUnorderedAccessTableRootParameterIndex() : UINT32_MAX;
}
return setIndex < m_setRootParameterMappings.size()
? m_setRootParameterMappings[setIndex].unorderedAccessTableRootIndex
: UINT32_MAX;
}
bool D3D12PipelineLayout::HasSamplerTable(uint32_t setIndex) const {
if (!UsesSetLayouts()) {
return setIndex == 0 && HasSamplerTable();
}
return setIndex < m_setRootParameterMappings.size() &&
m_setRootParameterMappings[setIndex].samplerTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetSamplerTableRootParameterIndex(uint32_t setIndex) const {
if (!UsesSetLayouts()) {
return setIndex == 0 ? GetSamplerTableRootParameterIndex() : UINT32_MAX;
}
return setIndex < m_setRootParameterMappings.size()
? m_setRootParameterMappings[setIndex].samplerTableRootIndex
: UINT32_MAX;
}
bool D3D12PipelineLayout::InitializeSetAwareRootSignature() {
const uint32_t setCount = m_desc.setLayoutCount;
m_setRootParameterMappings.assign(setCount, SetRootParameterMapping{});
uint32_t rootParameterCount = 0;
uint32_t descriptorRangeCount = 0;
for (uint32_t setIndex = 0; setIndex < setCount; ++setIndex) {
const DescriptorSetLayoutDesc& setLayout = m_desc.setLayouts[setIndex];
rootParameterCount += CountBindingEntriesOfType(setLayout, DescriptorType::CBV);
rootParameterCount += SumDescriptorCountOfType(setLayout, DescriptorType::SRV) > 0 ? 1u : 0u;
rootParameterCount += SumDescriptorCountOfType(setLayout, DescriptorType::UAV) > 0 ? 1u : 0u;
rootParameterCount += SumDescriptorCountOfType(setLayout, DescriptorType::Sampler) > 0 ? 1u : 0u;
descriptorRangeCount += CountBindingEntriesOfType(setLayout, DescriptorType::SRV);
descriptorRangeCount += CountBindingEntriesOfType(setLayout, DescriptorType::UAV);
descriptorRangeCount += CountBindingEntriesOfType(setLayout, DescriptorType::Sampler);
}
m_rootParameters.reserve(rootParameterCount);
m_descriptorRanges.reserve(descriptorRangeCount);
uint32_t rootIndex = 0;
uint32_t nextCBVRegister = 0;
uint32_t nextSRVRegister = 0;
uint32_t nextUAVRegister = 0;
uint32_t nextSamplerRegister = 0;
for (uint32_t setIndex = 0; setIndex < setCount; ++setIndex) {
const DescriptorSetLayoutDesc& setLayout = m_desc.setLayouts[setIndex];
SetRootParameterMapping& setMapping = m_setRootParameterMappings[setIndex];
const auto cbvBindings = GatherBindingsOfTypeSorted(setLayout, DescriptorType::CBV);
for (const DescriptorSetLayoutBinding* binding : cbvBindings) {
m_rootParameters.push_back(D3D12RootSignature::CreateCBV(nextCBVRegister, ShaderVisibility::All, 0));
setMapping.constantBufferRootIndices[binding->binding] = rootIndex++;
nextCBVRegister += binding->count > 0 ? binding->count : 1u;
}
const auto appendDescriptorTable =
[this, &rootIndex](
const DescriptorSetLayoutDesc& layout,
DescriptorType type,
D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
uint32_t& nextRegister,
uint32_t& rootParameterIndex) {
const auto bindings = GatherBindingsOfTypeSorted(layout, type);
if (bindings.empty()) {
return;
}
const size_t rangeStart = m_descriptorRanges.size();
for (const DescriptorSetLayoutBinding* binding : bindings) {
const uint32_t descriptorCount = binding->count > 0 ? binding->count : 1u;
m_descriptorRanges.push_back(
D3D12RootSignature::CreateDescriptorRange(
rangeType,
nextRegister,
descriptorCount,
0));
nextRegister += descriptorCount;
}
m_rootParameters.push_back(
D3D12RootSignature::CreateDescriptorTable(
static_cast<uint32_t>(bindings.size()),
m_descriptorRanges.data() + rangeStart,
ShaderVisibility::All));
rootParameterIndex = rootIndex++;
};
appendDescriptorTable(
setLayout,
DescriptorType::SRV,
D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
nextSRVRegister,
setMapping.shaderResourceTableRootIndex);
appendDescriptorTable(
setLayout,
DescriptorType::UAV,
D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
nextUAVRegister,
setMapping.unorderedAccessTableRootIndex);
appendDescriptorTable(
setLayout,
DescriptorType::Sampler,
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
nextSamplerRegister,
setMapping.samplerTableRootIndex);
}
return true;
}
bool D3D12PipelineLayout::InitializeFlatRootSignature() {
const RHIPipelineLayoutDesc& normalizedDesc = m_desc;
const uint32_t rootParameterCount =
@@ -143,87 +499,8 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
rootIndex++;
}
D3D12_ROOT_SIGNATURE_DESC rootSigDesc = D3D12RootSignature::CreateDesc(
m_rootParameters.empty() ? nullptr : m_rootParameters.data(),
static_cast<uint32_t>(m_rootParameters.size()),
nullptr, 0,
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
ID3D12Device* d3d12Device = device->GetDevice();
if (!d3d12Device) {
return false;
}
ID3DBlob* signature = nullptr;
ID3DBlob* error = nullptr;
HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
if (FAILED(hr)) {
if (error) {
error->Release();
}
return false;
}
hr = d3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature));
signature->Release();
if (FAILED(hr)) {
return false;
}
return true;
}
void D3D12PipelineLayout::Shutdown() {
m_rootSignature.Reset();
m_desc = {};
m_rootParameters.clear();
m_descriptorRanges.clear();
m_constantBufferRootIndices.clear();
m_shaderResourceTableRootIndex = UINT32_MAX;
m_unorderedAccessTableRootIndex = UINT32_MAX;
m_samplerTableRootIndex = UINT32_MAX;
m_setLayouts.clear();
m_setLayoutBindings.clear();
m_device = nullptr;
}
bool D3D12PipelineLayout::HasConstantBufferBinding(uint32_t binding) const {
return m_constantBufferRootIndices.find(binding) != m_constantBufferRootIndices.end();
}
uint32_t D3D12PipelineLayout::GetConstantBufferRootParameterIndex(uint32_t binding) const {
auto it = m_constantBufferRootIndices.find(binding);
if (it != m_constantBufferRootIndices.end()) {
return it->second;
}
return UINT32_MAX;
}
bool D3D12PipelineLayout::HasShaderResourceTable() const {
return m_shaderResourceTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetShaderResourceTableRootParameterIndex() const {
return m_shaderResourceTableRootIndex;
}
bool D3D12PipelineLayout::HasUnorderedAccessTable() const {
return m_unorderedAccessTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetUnorderedAccessTableRootParameterIndex() const {
return m_unorderedAccessTableRootIndex;
}
bool D3D12PipelineLayout::HasSamplerTable() const {
return m_samplerTableRootIndex != UINT32_MAX;
}
uint32_t D3D12PipelineLayout::GetSamplerTableRootParameterIndex() const {
return m_samplerTableRootIndex;
}
} // namespace RHI
} // namespace XCEngine