fix(rhi): honor firstSet in set-aware d3d12 bindings
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user