fix(rhi): honor firstSet in set-aware d3d12 bindings
This commit is contained in:
@@ -17,6 +17,13 @@ class D3D12Device;
|
|||||||
|
|
||||||
class D3D12PipelineLayout : public RHIPipelineLayout {
|
class D3D12PipelineLayout : public RHIPipelineLayout {
|
||||||
public:
|
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();
|
||||||
~D3D12PipelineLayout() override;
|
~D3D12PipelineLayout() override;
|
||||||
|
|
||||||
@@ -27,6 +34,9 @@ public:
|
|||||||
void* GetNativeHandle() override { return m_rootSignature.Get(); }
|
void* GetNativeHandle() override { return m_rootSignature.Get(); }
|
||||||
ID3D12RootSignature* GetRootSignature() const { 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;
|
bool HasConstantBufferBinding(uint32_t binding) const;
|
||||||
uint32_t GetConstantBufferRootParameterIndex(uint32_t binding) const;
|
uint32_t GetConstantBufferRootParameterIndex(uint32_t binding) const;
|
||||||
bool HasShaderResourceTable() const;
|
bool HasShaderResourceTable() const;
|
||||||
@@ -35,10 +45,21 @@ public:
|
|||||||
uint32_t GetUnorderedAccessTableRootParameterIndex() const;
|
uint32_t GetUnorderedAccessTableRootParameterIndex() const;
|
||||||
bool HasSamplerTable() const;
|
bool HasSamplerTable() const;
|
||||||
uint32_t GetSamplerTableRootParameterIndex() 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; }
|
const RHIPipelineLayoutDesc& GetDesc() const { return m_desc; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool InitializeInternal(D3D12Device* device, const RHIPipelineLayoutDesc& desc);
|
bool InitializeInternal(D3D12Device* device, const RHIPipelineLayoutDesc& desc);
|
||||||
|
bool InitializeSetAwareRootSignature();
|
||||||
|
bool InitializeFlatRootSignature();
|
||||||
|
|
||||||
ComPtr<ID3D12RootSignature> m_rootSignature;
|
ComPtr<ID3D12RootSignature> m_rootSignature;
|
||||||
D3D12Device* m_device;
|
D3D12Device* m_device;
|
||||||
@@ -47,6 +68,7 @@ private:
|
|||||||
uint32_t m_shaderResourceTableRootIndex = UINT32_MAX;
|
uint32_t m_shaderResourceTableRootIndex = UINT32_MAX;
|
||||||
uint32_t m_unorderedAccessTableRootIndex = UINT32_MAX;
|
uint32_t m_unorderedAccessTableRootIndex = UINT32_MAX;
|
||||||
uint32_t m_samplerTableRootIndex = UINT32_MAX;
|
uint32_t m_samplerTableRootIndex = UINT32_MAX;
|
||||||
|
std::vector<SetRootParameterMapping> m_setRootParameterMappings;
|
||||||
std::vector<DescriptorSetLayoutDesc> m_setLayouts;
|
std::vector<DescriptorSetLayoutDesc> m_setLayouts;
|
||||||
std::vector<std::vector<DescriptorSetLayoutBinding>> m_setLayoutBindings;
|
std::vector<std::vector<DescriptorSetLayoutBinding>> m_setLayoutBindings;
|
||||||
std::vector<D3D12_ROOT_PARAMETER> m_rootParameters;
|
std::vector<D3D12_ROOT_PARAMETER> m_rootParameters;
|
||||||
|
|||||||
@@ -197,15 +197,23 @@ void D3D12CommandList::SetGraphicsDescriptorSets(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t setIndex = firstSet + i;
|
||||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||||
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
|
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
|
||||||
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
|
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
|
||||||
const DescriptorSetLayoutBinding& binding = bindings[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 &&
|
if (static_cast<DescriptorType>(binding.type) == DescriptorType::CBV &&
|
||||||
d3d12Layout->HasConstantBufferBinding(binding.binding) &&
|
hasBinding &&
|
||||||
d3d12Set->UploadConstantBuffer(binding.binding)) {
|
d3d12Set->UploadConstantBuffer(binding.binding)) {
|
||||||
SetGraphicsRootConstantBufferView(
|
SetGraphicsRootConstantBufferView(
|
||||||
d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding),
|
rootParameterIndex,
|
||||||
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
|
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,28 +224,49 @@ void D3D12CommandList::SetGraphicsDescriptorSets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
|
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 uint32_t srvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::SRV);
|
||||||
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
|
||||||
if (gpuHandle.ptr != 0) {
|
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 uint32_t uavBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::UAV);
|
||||||
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(uavBinding);
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(uavBinding);
|
||||||
if (gpuHandle.ptr != 0) {
|
if (gpuHandle.ptr != 0) {
|
||||||
SetGraphicsRootDescriptorTable(d3d12Layout->GetUnorderedAccessTableRootParameterIndex(), gpuHandle);
|
SetGraphicsRootDescriptorTable(
|
||||||
|
d3d12Layout->UsesSetLayouts()
|
||||||
|
? d3d12Layout->GetUnorderedAccessTableRootParameterIndex(setIndex)
|
||||||
|
: d3d12Layout->GetUnorderedAccessTableRootParameterIndex(),
|
||||||
|
gpuHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
|
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
|
||||||
HasSamplerBindings(d3d12Set) &&
|
HasSamplerBindings(d3d12Set) &&
|
||||||
d3d12Layout->HasSamplerTable()) {
|
(d3d12Layout->UsesSetLayouts()
|
||||||
|
? d3d12Layout->HasSamplerTable(setIndex)
|
||||||
|
: d3d12Layout->HasSamplerTable())) {
|
||||||
const uint32_t samplerBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::Sampler);
|
const uint32_t samplerBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::Sampler);
|
||||||
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(samplerBinding);
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(samplerBinding);
|
||||||
if (gpuHandle.ptr != 0) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t setIndex = firstSet + i;
|
||||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||||
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
|
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
|
||||||
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
|
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
|
||||||
const DescriptorSetLayoutBinding& binding = bindings[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 &&
|
if (static_cast<DescriptorType>(binding.type) == DescriptorType::CBV &&
|
||||||
d3d12Layout->HasConstantBufferBinding(binding.binding) &&
|
hasBinding &&
|
||||||
d3d12Set->UploadConstantBuffer(binding.binding)) {
|
d3d12Set->UploadConstantBuffer(binding.binding)) {
|
||||||
m_commandList->SetComputeRootConstantBufferView(
|
m_commandList->SetComputeRootConstantBufferView(
|
||||||
d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding),
|
rootParameterIndex,
|
||||||
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
|
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,33 +341,48 @@ void D3D12CommandList::SetComputeDescriptorSets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
|
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 uint32_t srvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::SRV);
|
||||||
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
|
||||||
if (gpuHandle.ptr != 0) {
|
if (gpuHandle.ptr != 0) {
|
||||||
m_commandList->SetComputeRootDescriptorTable(
|
m_commandList->SetComputeRootDescriptorTable(
|
||||||
d3d12Layout->GetShaderResourceTableRootParameterIndex(),
|
d3d12Layout->UsesSetLayouts()
|
||||||
|
? d3d12Layout->GetShaderResourceTableRootParameterIndex(setIndex)
|
||||||
|
: d3d12Layout->GetShaderResourceTableRootParameterIndex(),
|
||||||
gpuHandle);
|
gpuHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d3d12Set->HasBindingType(DescriptorType::UAV) && d3d12Layout->HasUnorderedAccessTable()) {
|
if (d3d12Set->HasBindingType(DescriptorType::UAV) && hasUavTable) {
|
||||||
const uint32_t uavBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::UAV);
|
const uint32_t uavBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::UAV);
|
||||||
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(uavBinding);
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(uavBinding);
|
||||||
if (gpuHandle.ptr != 0) {
|
if (gpuHandle.ptr != 0) {
|
||||||
m_commandList->SetComputeRootDescriptorTable(
|
m_commandList->SetComputeRootDescriptorTable(
|
||||||
d3d12Layout->GetUnorderedAccessTableRootParameterIndex(),
|
d3d12Layout->UsesSetLayouts()
|
||||||
|
? d3d12Layout->GetUnorderedAccessTableRootParameterIndex(setIndex)
|
||||||
|
: d3d12Layout->GetUnorderedAccessTableRootParameterIndex(),
|
||||||
gpuHandle);
|
gpuHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
|
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
|
||||||
HasSamplerBindings(d3d12Set) &&
|
HasSamplerBindings(d3d12Set) &&
|
||||||
d3d12Layout->HasSamplerTable()) {
|
(d3d12Layout->UsesSetLayouts()
|
||||||
|
? d3d12Layout->HasSamplerTable(setIndex)
|
||||||
|
: d3d12Layout->HasSamplerTable())) {
|
||||||
const uint32_t samplerBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::Sampler);
|
const uint32_t samplerBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::Sampler);
|
||||||
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(samplerBinding);
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(samplerBinding);
|
||||||
if (gpuHandle.ptr != 0) {
|
if (gpuHandle.ptr != 0) {
|
||||||
m_commandList->SetComputeRootDescriptorTable(
|
m_commandList->SetComputeRootDescriptorTable(
|
||||||
d3d12Layout->GetSamplerTableRootParameterIndex(),
|
d3d12Layout->UsesSetLayouts()
|
||||||
|
? d3d12Layout->GetSamplerTableRootParameterIndex(setIndex)
|
||||||
|
: d3d12Layout->GetSamplerTableRootParameterIndex(),
|
||||||
gpuHandle);
|
gpuHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
||||||
#include "XCEngine/RHI/D3D12/D3D12Device.h"
|
#include "XCEngine/RHI/D3D12/D3D12Device.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace RHI {
|
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
|
} // namespace
|
||||||
|
|
||||||
D3D12PipelineLayout::D3D12PipelineLayout()
|
D3D12PipelineLayout::D3D12PipelineLayout()
|
||||||
@@ -88,7 +136,315 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
|
|||||||
m_shaderResourceTableRootIndex = UINT32_MAX;
|
m_shaderResourceTableRootIndex = UINT32_MAX;
|
||||||
m_unorderedAccessTableRootIndex = UINT32_MAX;
|
m_unorderedAccessTableRootIndex = UINT32_MAX;
|
||||||
m_samplerTableRootIndex = 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 RHIPipelineLayoutDesc& normalizedDesc = m_desc;
|
||||||
|
|
||||||
const uint32_t rootParameterCount =
|
const uint32_t rootParameterCount =
|
||||||
@@ -143,87 +499,8 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
|
|||||||
rootIndex++;
|
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;
|
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 RHI
|
||||||
} // namespace XCEngine
|
} // namespace XCEngine
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ struct MatrixBufferData {
|
|||||||
constexpr float kSphereRadius = 1.0f;
|
constexpr float kSphereRadius = 1.0f;
|
||||||
constexpr int kSphereSegments = 32;
|
constexpr int kSphereSegments = 32;
|
||||||
constexpr float kPi = 3.14159265358979323846f;
|
constexpr float kPi = 3.14159265358979323846f;
|
||||||
|
constexpr uint32_t kSphereDescriptorFirstSet = 1;
|
||||||
|
constexpr uint32_t kSphereDescriptorSetCount = 4;
|
||||||
|
|
||||||
std::filesystem::path GetExecutableDirectory() {
|
std::filesystem::path GetExecutableDirectory() {
|
||||||
char exePath[MAX_PATH] = {};
|
char exePath[MAX_PATH] = {};
|
||||||
@@ -452,10 +454,15 @@ void SphereTest::InitializeSphereResources() {
|
|||||||
ASSERT_NE(mSamplerSet, nullptr);
|
ASSERT_NE(mSamplerSet, nullptr);
|
||||||
mSamplerSet->UpdateSampler(0, mSampler);
|
mSamplerSet->UpdateSampler(0, mSampler);
|
||||||
|
|
||||||
|
DescriptorSetLayoutDesc setLayouts[kSphereDescriptorSetCount] = {};
|
||||||
|
// Reserve set0 so the integration test exercises non-zero firstSet binding.
|
||||||
|
setLayouts[1] = constantLayoutDesc;
|
||||||
|
setLayouts[2] = textureLayoutDesc;
|
||||||
|
setLayouts[3] = samplerLayoutDesc;
|
||||||
|
|
||||||
RHIPipelineLayoutDesc pipelineLayoutDesc = {};
|
RHIPipelineLayoutDesc pipelineLayoutDesc = {};
|
||||||
pipelineLayoutDesc.constantBufferCount = 1;
|
pipelineLayoutDesc.setLayouts = setLayouts;
|
||||||
pipelineLayoutDesc.textureCount = 1;
|
pipelineLayoutDesc.setLayoutCount = kSphereDescriptorSetCount;
|
||||||
pipelineLayoutDesc.samplerCount = 1;
|
|
||||||
mPipelineLayout = GetDevice()->CreatePipelineLayout(pipelineLayoutDesc);
|
mPipelineLayout = GetDevice()->CreatePipelineLayout(pipelineLayoutDesc);
|
||||||
ASSERT_NE(mPipelineLayout, nullptr);
|
ASSERT_NE(mPipelineLayout, nullptr);
|
||||||
|
|
||||||
@@ -584,7 +591,7 @@ void SphereTest::RenderFrame() {
|
|||||||
|
|
||||||
cmdList->SetPipelineState(mPipelineState);
|
cmdList->SetPipelineState(mPipelineState);
|
||||||
RHIDescriptorSet* descriptorSets[] = { mConstantSet, mTextureSet, mSamplerSet };
|
RHIDescriptorSet* descriptorSets[] = { mConstantSet, mTextureSet, mSamplerSet };
|
||||||
cmdList->SetGraphicsDescriptorSets(0, 3, descriptorSets, mPipelineLayout);
|
cmdList->SetGraphicsDescriptorSets(kSphereDescriptorFirstSet, 3, descriptorSets, mPipelineLayout);
|
||||||
cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList);
|
cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList);
|
||||||
|
|
||||||
RHIResourceView* vertexBuffers[] = { mVertexBufferView };
|
RHIResourceView* vertexBuffers[] = { mVertexBufferView };
|
||||||
|
|||||||
@@ -283,10 +283,12 @@ TEST_P(RHITestFixture, PipelineLayout_D3D12InfersBindingClassesFromSetLayouts) {
|
|||||||
ASSERT_NE(layout, nullptr);
|
ASSERT_NE(layout, nullptr);
|
||||||
|
|
||||||
auto* d3d12Layout = static_cast<D3D12PipelineLayout*>(layout);
|
auto* d3d12Layout = static_cast<D3D12PipelineLayout*>(layout);
|
||||||
EXPECT_TRUE(d3d12Layout->HasConstantBufferBinding(0));
|
EXPECT_TRUE(d3d12Layout->UsesSetLayouts());
|
||||||
EXPECT_TRUE(d3d12Layout->HasShaderResourceTable());
|
EXPECT_EQ(d3d12Layout->GetSetLayoutCount(), 4u);
|
||||||
EXPECT_TRUE(d3d12Layout->HasUnorderedAccessTable());
|
EXPECT_TRUE(d3d12Layout->HasConstantBufferBinding(0, 0));
|
||||||
EXPECT_TRUE(d3d12Layout->HasSamplerTable());
|
EXPECT_TRUE(d3d12Layout->HasShaderResourceTable(1));
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasUnorderedAccessTable(2));
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasSamplerTable(3));
|
||||||
EXPECT_EQ(d3d12Layout->GetDesc().constantBufferCount, 1u);
|
EXPECT_EQ(d3d12Layout->GetDesc().constantBufferCount, 1u);
|
||||||
EXPECT_EQ(d3d12Layout->GetDesc().textureCount, 1u);
|
EXPECT_EQ(d3d12Layout->GetDesc().textureCount, 1u);
|
||||||
EXPECT_EQ(d3d12Layout->GetDesc().uavCount, 1u);
|
EXPECT_EQ(d3d12Layout->GetDesc().uavCount, 1u);
|
||||||
@@ -295,3 +297,68 @@ TEST_P(RHITestFixture, PipelineLayout_D3D12InfersBindingClassesFromSetLayouts) {
|
|||||||
layout->Shutdown();
|
layout->Shutdown();
|
||||||
delete layout;
|
delete layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, PipelineLayout_D3D12SeparatesOverlappingBindingsAcrossSetSlots) {
|
||||||
|
if (GetBackendType() != RHIType::D3D12) {
|
||||||
|
GTEST_SKIP() << "D3D12-specific root parameter verification";
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorSetLayoutBinding set0Bindings[2] = {};
|
||||||
|
set0Bindings[0].binding = 0;
|
||||||
|
set0Bindings[0].type = static_cast<uint32_t>(DescriptorType::CBV);
|
||||||
|
set0Bindings[0].count = 1;
|
||||||
|
set0Bindings[1].binding = 0;
|
||||||
|
set0Bindings[1].type = static_cast<uint32_t>(DescriptorType::SRV);
|
||||||
|
set0Bindings[1].count = 1;
|
||||||
|
|
||||||
|
DescriptorSetLayoutBinding set1Bindings[2] = {};
|
||||||
|
set1Bindings[0].binding = 0;
|
||||||
|
set1Bindings[0].type = static_cast<uint32_t>(DescriptorType::CBV);
|
||||||
|
set1Bindings[0].count = 1;
|
||||||
|
set1Bindings[1].binding = 0;
|
||||||
|
set1Bindings[1].type = static_cast<uint32_t>(DescriptorType::SRV);
|
||||||
|
set1Bindings[1].count = 1;
|
||||||
|
|
||||||
|
DescriptorSetLayoutBinding set2Bindings[1] = {};
|
||||||
|
set2Bindings[0].binding = 0;
|
||||||
|
set2Bindings[0].type = static_cast<uint32_t>(DescriptorType::Sampler);
|
||||||
|
set2Bindings[0].count = 1;
|
||||||
|
|
||||||
|
DescriptorSetLayoutDesc setLayouts[3] = {};
|
||||||
|
setLayouts[0].bindings = set0Bindings;
|
||||||
|
setLayouts[0].bindingCount = 2;
|
||||||
|
setLayouts[1].bindings = set1Bindings;
|
||||||
|
setLayouts[1].bindingCount = 2;
|
||||||
|
setLayouts[2].bindings = set2Bindings;
|
||||||
|
setLayouts[2].bindingCount = 1;
|
||||||
|
|
||||||
|
RHIPipelineLayoutDesc desc = {};
|
||||||
|
desc.setLayouts = setLayouts;
|
||||||
|
desc.setLayoutCount = 3;
|
||||||
|
|
||||||
|
RHIPipelineLayout* layout = GetDevice()->CreatePipelineLayout(desc);
|
||||||
|
ASSERT_NE(layout, nullptr);
|
||||||
|
|
||||||
|
auto* d3d12Layout = static_cast<D3D12PipelineLayout*>(layout);
|
||||||
|
EXPECT_TRUE(d3d12Layout->UsesSetLayouts());
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasConstantBufferBinding(0, 0));
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasConstantBufferBinding(1, 0));
|
||||||
|
EXPECT_FALSE(d3d12Layout->HasConstantBufferBinding(2, 0));
|
||||||
|
EXPECT_NE(
|
||||||
|
d3d12Layout->GetConstantBufferRootParameterIndex(0, 0),
|
||||||
|
d3d12Layout->GetConstantBufferRootParameterIndex(1, 0));
|
||||||
|
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasShaderResourceTable(0));
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasShaderResourceTable(1));
|
||||||
|
EXPECT_FALSE(d3d12Layout->HasShaderResourceTable(2));
|
||||||
|
EXPECT_NE(
|
||||||
|
d3d12Layout->GetShaderResourceTableRootParameterIndex(0),
|
||||||
|
d3d12Layout->GetShaderResourceTableRootParameterIndex(1));
|
||||||
|
|
||||||
|
EXPECT_FALSE(d3d12Layout->HasSamplerTable(0));
|
||||||
|
EXPECT_FALSE(d3d12Layout->HasSamplerTable(1));
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasSamplerTable(2));
|
||||||
|
|
||||||
|
layout->Shutdown();
|
||||||
|
delete layout;
|
||||||
|
}
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ tests/RHI/integration/
|
|||||||
- `sphere_opengl.ppm`
|
- `sphere_opengl.ppm`
|
||||||
5. 两个后端都必须与同一张 `GT.ppm` 做比对。
|
5. 两个后端都必须与同一张 `GT.ppm` 做比对。
|
||||||
6. 新测试如果暴露抽象层缺口,应先补 RHI,再补测试。
|
6. 新测试如果暴露抽象层缺口,应先补 RHI,再补测试。
|
||||||
|
7. 至少保留一个场景覆盖 `firstSet != 0` 的描述符绑定路径,当前由 `sphere` 负责验证。
|
||||||
|
|
||||||
### 6.3 命名
|
### 6.3 命名
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user