refactor(rhi): untangle d3d12 descriptor bindings
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -32,32 +33,46 @@ public:
|
|||||||
void WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset = 0) override;
|
void WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset = 0) override;
|
||||||
|
|
||||||
uint32_t GetBindingCount() const override { return m_bindingCount; }
|
uint32_t GetBindingCount() const override { return m_bindingCount; }
|
||||||
const DescriptorSetLayoutBinding* GetBindings() const override { return m_bindings; }
|
const DescriptorSetLayoutBinding* GetBindings() const override { return m_bindings.empty() ? nullptr : m_bindings.data(); }
|
||||||
|
|
||||||
void* GetConstantBufferData() override { return m_constantBufferData.data(); }
|
void* GetConstantBufferData() override;
|
||||||
size_t GetConstantBufferSize() const override { return m_constantBufferData.size(); }
|
size_t GetConstantBufferSize() const override;
|
||||||
bool IsConstantDirty() const override { return m_constantBufferDirty; }
|
bool IsConstantDirty() const override;
|
||||||
void MarkConstantClean() override { m_constantBufferDirty = false; }
|
void MarkConstantClean() override;
|
||||||
|
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index = 0) const;
|
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index = 0) const;
|
||||||
|
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandleForBinding(uint32_t binding) const;
|
||||||
uint32_t GetOffset() const { return m_offset; }
|
uint32_t GetOffset() const { return m_offset; }
|
||||||
uint32_t GetCount() const { return m_count; }
|
uint32_t GetCount() const { return m_count; }
|
||||||
D3D12DescriptorHeap* GetHeap() const { return m_heap; }
|
D3D12DescriptorHeap* GetHeap() const { return m_heap; }
|
||||||
bool HasBindingType(DescriptorType type) const;
|
bool HasBindingType(DescriptorType type) const;
|
||||||
uint32_t GetFirstBindingOfType(DescriptorType type) const;
|
uint32_t GetFirstBindingOfType(DescriptorType type) const;
|
||||||
bool UploadConstantBuffer();
|
uint32_t GetDescriptorIndexForBinding(uint32_t binding) const;
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS GetConstantBufferGPUAddress() const;
|
bool UploadConstantBuffer(uint32_t binding);
|
||||||
|
D3D12_GPU_VIRTUAL_ADDRESS GetConstantBufferGPUAddress(uint32_t binding) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct BindingRecord {
|
||||||
|
DescriptorSetLayoutBinding layout = {};
|
||||||
|
uint32_t descriptorIndex = UINT32_MAX;
|
||||||
|
std::vector<uint8_t> constantBufferData;
|
||||||
|
bool constantBufferDirty = false;
|
||||||
|
std::unique_ptr<D3D12Buffer> constantBuffer;
|
||||||
|
uint64_t constantBufferCapacity = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
BindingRecord* FindBindingRecord(uint32_t binding);
|
||||||
|
const BindingRecord* FindBindingRecord(uint32_t binding) const;
|
||||||
|
BindingRecord* FindFirstBindingRecordOfType(DescriptorType type);
|
||||||
|
const BindingRecord* FindFirstBindingRecordOfType(DescriptorType type) const;
|
||||||
|
|
||||||
D3D12DescriptorHeap* m_heap;
|
D3D12DescriptorHeap* m_heap;
|
||||||
uint32_t m_offset;
|
uint32_t m_offset;
|
||||||
uint32_t m_count;
|
uint32_t m_count;
|
||||||
uint32_t m_bindingCount;
|
uint32_t m_bindingCount;
|
||||||
DescriptorSetLayoutBinding* m_bindings;
|
std::vector<DescriptorSetLayoutBinding> m_bindings;
|
||||||
std::vector<uint8_t> m_constantBufferData;
|
std::vector<BindingRecord> m_bindingRecords;
|
||||||
bool m_constantBufferDirty = false;
|
std::unordered_map<uint32_t, uint32_t> m_bindingToRecordIndex;
|
||||||
std::unique_ptr<D3D12Buffer> m_constantBuffer;
|
|
||||||
uint64_t m_constantBufferCapacity = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace RHI
|
} // namespace RHI
|
||||||
|
|||||||
@@ -27,8 +27,14 @@ 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(); }
|
||||||
|
|
||||||
uint32_t GetRootParameterIndex(uint32_t shaderRegister) const;
|
bool HasConstantBufferBinding(uint32_t binding) const;
|
||||||
bool HasRootParameter(uint32_t shaderRegister) const;
|
uint32_t GetConstantBufferRootParameterIndex(uint32_t binding) const;
|
||||||
|
bool HasShaderResourceTable() const;
|
||||||
|
uint32_t GetShaderResourceTableRootParameterIndex() const;
|
||||||
|
bool HasUnorderedAccessTable() const;
|
||||||
|
uint32_t GetUnorderedAccessTableRootParameterIndex() const;
|
||||||
|
bool HasSamplerTable() const;
|
||||||
|
uint32_t GetSamplerTableRootParameterIndex() const;
|
||||||
const RHIPipelineLayoutDesc& GetDesc() const { return m_desc; }
|
const RHIPipelineLayoutDesc& GetDesc() const { return m_desc; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -37,7 +43,10 @@ private:
|
|||||||
ComPtr<ID3D12RootSignature> m_rootSignature;
|
ComPtr<ID3D12RootSignature> m_rootSignature;
|
||||||
D3D12Device* m_device;
|
D3D12Device* m_device;
|
||||||
RHIPipelineLayoutDesc m_desc = {};
|
RHIPipelineLayoutDesc m_desc = {};
|
||||||
std::unordered_map<uint32_t, uint32_t> m_registerToRootIndex;
|
std::unordered_map<uint32_t, uint32_t> m_constantBufferRootIndices;
|
||||||
|
uint32_t m_shaderResourceTableRootIndex = UINT32_MAX;
|
||||||
|
uint32_t m_unorderedAccessTableRootIndex = UINT32_MAX;
|
||||||
|
uint32_t m_samplerTableRootIndex = UINT32_MAX;
|
||||||
std::vector<D3D12_ROOT_PARAMETER> m_rootParameters;
|
std::vector<D3D12_ROOT_PARAMETER> m_rootParameters;
|
||||||
std::vector<D3D12_DESCRIPTOR_RANGE> m_descriptorRanges;
|
std::vector<D3D12_DESCRIPTOR_RANGE> m_descriptorRanges;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -198,14 +198,15 @@ void D3D12CommandList::SetGraphicsDescriptorSets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||||
if (d3d12Set->HasBindingType(DescriptorType::CBV)) {
|
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
|
||||||
const uint32_t cbvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::CBV);
|
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
|
||||||
if (cbvBinding != UINT32_MAX &&
|
const DescriptorSetLayoutBinding& binding = bindings[bindingIndex];
|
||||||
d3d12Layout->HasRootParameter(cbvBinding) &&
|
if (static_cast<DescriptorType>(binding.type) == DescriptorType::CBV &&
|
||||||
d3d12Set->UploadConstantBuffer()) {
|
d3d12Layout->HasConstantBufferBinding(binding.binding) &&
|
||||||
|
d3d12Set->UploadConstantBuffer(binding.binding)) {
|
||||||
SetGraphicsRootConstantBufferView(
|
SetGraphicsRootConstantBufferView(
|
||||||
d3d12Layout->GetRootParameterIndex(cbvBinding),
|
d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding),
|
||||||
d3d12Set->GetConstantBufferGPUAddress());
|
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,11 +215,30 @@ void D3D12CommandList::SetGraphicsDescriptorSets(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandle();
|
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
|
||||||
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV && HasDescriptorTableBindings(d3d12Set) && d3d12Layout->HasRootParameter(100)) {
|
if (d3d12Set->HasBindingType(DescriptorType::SRV) && d3d12Layout->HasShaderResourceTable()) {
|
||||||
SetGraphicsRootDescriptorTable(d3d12Layout->GetRootParameterIndex(100), gpuHandle);
|
const uint32_t srvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::SRV);
|
||||||
} else if (heap->GetType() == DescriptorHeapType::Sampler && HasSamplerBindings(d3d12Set) && d3d12Layout->HasRootParameter(200)) {
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
|
||||||
SetGraphicsRootDescriptorTable(d3d12Layout->GetRootParameterIndex(200), gpuHandle);
|
if (gpuHandle.ptr != 0) {
|
||||||
|
SetGraphicsRootDescriptorTable(d3d12Layout->GetShaderResourceTableRootParameterIndex(), gpuHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d3d12Set->HasBindingType(DescriptorType::UAV) && d3d12Layout->HasUnorderedAccessTable()) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
|
||||||
|
HasSamplerBindings(d3d12Set) &&
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,6 +254,7 @@ void D3D12CommandList::SetComputeDescriptorSets(
|
|||||||
|
|
||||||
D3D12PipelineLayout* d3d12Layout = static_cast<D3D12PipelineLayout*>(pipelineLayout);
|
D3D12PipelineLayout* d3d12Layout = static_cast<D3D12PipelineLayout*>(pipelineLayout);
|
||||||
SetPipelineLayout(d3d12Layout);
|
SetPipelineLayout(d3d12Layout);
|
||||||
|
m_commandList->SetComputeRootSignature(d3d12Layout->GetRootSignature());
|
||||||
|
|
||||||
std::vector<ID3D12DescriptorHeap*> descriptorHeaps;
|
std::vector<ID3D12DescriptorHeap*> descriptorHeaps;
|
||||||
descriptorHeaps.reserve(2);
|
descriptorHeaps.reserve(2);
|
||||||
@@ -265,14 +286,15 @@ void D3D12CommandList::SetComputeDescriptorSets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||||
if (d3d12Set->HasBindingType(DescriptorType::CBV)) {
|
const DescriptorSetLayoutBinding* bindings = d3d12Set->GetBindings();
|
||||||
const uint32_t cbvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::CBV);
|
for (uint32_t bindingIndex = 0; bindingIndex < d3d12Set->GetBindingCount(); ++bindingIndex) {
|
||||||
if (cbvBinding != UINT32_MAX &&
|
const DescriptorSetLayoutBinding& binding = bindings[bindingIndex];
|
||||||
d3d12Layout->HasRootParameter(cbvBinding) &&
|
if (static_cast<DescriptorType>(binding.type) == DescriptorType::CBV &&
|
||||||
d3d12Set->UploadConstantBuffer()) {
|
d3d12Layout->HasConstantBufferBinding(binding.binding) &&
|
||||||
|
d3d12Set->UploadConstantBuffer(binding.binding)) {
|
||||||
m_commandList->SetComputeRootConstantBufferView(
|
m_commandList->SetComputeRootConstantBufferView(
|
||||||
d3d12Layout->GetRootParameterIndex(cbvBinding),
|
d3d12Layout->GetConstantBufferRootParameterIndex(binding.binding),
|
||||||
d3d12Set->GetConstantBufferGPUAddress());
|
d3d12Set->GetConstantBufferGPUAddress(binding.binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,11 +303,36 @@ void D3D12CommandList::SetComputeDescriptorSets(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandle();
|
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
|
||||||
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV && HasDescriptorTableBindings(d3d12Set) && d3d12Layout->HasRootParameter(100)) {
|
if (d3d12Set->HasBindingType(DescriptorType::SRV) && d3d12Layout->HasShaderResourceTable()) {
|
||||||
m_commandList->SetComputeRootDescriptorTable(d3d12Layout->GetRootParameterIndex(100), gpuHandle);
|
const uint32_t srvBinding = d3d12Set->GetFirstBindingOfType(DescriptorType::SRV);
|
||||||
} else if (heap->GetType() == DescriptorHeapType::Sampler && HasSamplerBindings(d3d12Set) && d3d12Layout->HasRootParameter(200)) {
|
const D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandleForBinding(srvBinding);
|
||||||
m_commandList->SetComputeRootDescriptorTable(d3d12Layout->GetRootParameterIndex(200), gpuHandle);
|
if (gpuHandle.ptr != 0) {
|
||||||
|
m_commandList->SetComputeRootDescriptorTable(
|
||||||
|
d3d12Layout->GetShaderResourceTableRootParameterIndex(),
|
||||||
|
gpuHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d3d12Set->HasBindingType(DescriptorType::UAV) && d3d12Layout->HasUnorderedAccessTable()) {
|
||||||
|
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(),
|
||||||
|
gpuHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (heap->GetType() == DescriptorHeapType::Sampler &&
|
||||||
|
HasSamplerBindings(d3d12Set) &&
|
||||||
|
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(),
|
||||||
|
gpuHandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,22 @@
|
|||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace RHI {
|
namespace RHI {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool UsesDescriptorHeap(DescriptorHeapType heapType, DescriptorType bindingType) {
|
||||||
|
if (heapType == DescriptorHeapType::CBV_SRV_UAV) {
|
||||||
|
return bindingType == DescriptorType::SRV || bindingType == DescriptorType::UAV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heapType == DescriptorHeapType::Sampler) {
|
||||||
|
return bindingType == DescriptorType::Sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
D3D12DescriptorHeap::D3D12DescriptorHeap()
|
D3D12DescriptorHeap::D3D12DescriptorHeap()
|
||||||
: m_type(DescriptorHeapType::CBV_SRV_UAV)
|
: m_type(DescriptorHeapType::CBV_SRV_UAV)
|
||||||
, m_numDescriptors(0)
|
, m_numDescriptors(0)
|
||||||
@@ -100,8 +116,10 @@ D3D12_DESCRIPTOR_HEAP_DESC D3D12DescriptorHeap::CreateDesc(DescriptorHeapType ty
|
|||||||
RHIDescriptorSet* D3D12DescriptorHeap::AllocateSet(const DescriptorSetLayoutDesc& layout) {
|
RHIDescriptorSet* D3D12DescriptorHeap::AllocateSet(const DescriptorSetLayoutDesc& layout) {
|
||||||
uint32_t requiredDescriptors = 0;
|
uint32_t requiredDescriptors = 0;
|
||||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||||
|
if (UsesDescriptorHeap(m_type, static_cast<DescriptorType>(layout.bindings[i].type))) {
|
||||||
requiredDescriptors += layout.bindings[i].count;
|
requiredDescriptors += layout.bindings[i].count;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_nextFreeOffset + requiredDescriptors > m_numDescriptors) {
|
if (m_nextFreeOffset + requiredDescriptors > m_numDescriptors) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
|
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
|
||||||
#include "XCEngine/RHI/D3D12/D3D12Sampler.h"
|
#include "XCEngine/RHI/D3D12/D3D12Sampler.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace RHI {
|
namespace RHI {
|
||||||
|
|
||||||
@@ -14,6 +17,18 @@ uint64_t AlignConstantBufferSize(size_t size) {
|
|||||||
return (minSize + 255ull) & ~255ull;
|
return (minSize + 255ull) & ~255ull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UsesDescriptorHeap(DescriptorHeapType heapType, DescriptorType bindingType) {
|
||||||
|
if (heapType == DescriptorHeapType::CBV_SRV_UAV) {
|
||||||
|
return bindingType == DescriptorType::SRV || bindingType == DescriptorType::UAV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heapType == DescriptorHeapType::Sampler) {
|
||||||
|
return bindingType == DescriptorType::Sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
D3D12DescriptorSet::D3D12DescriptorSet()
|
D3D12DescriptorSet::D3D12DescriptorSet()
|
||||||
@@ -21,7 +36,7 @@ D3D12DescriptorSet::D3D12DescriptorSet()
|
|||||||
, m_offset(0)
|
, m_offset(0)
|
||||||
, m_count(0)
|
, m_count(0)
|
||||||
, m_bindingCount(0)
|
, m_bindingCount(0)
|
||||||
, m_bindings(nullptr) {
|
, m_bindings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12DescriptorSet::~D3D12DescriptorSet() {
|
D3D12DescriptorSet::~D3D12DescriptorSet() {
|
||||||
@@ -34,10 +49,53 @@ bool D3D12DescriptorSet::Initialize(D3D12DescriptorHeap* heap, uint32_t offset,
|
|||||||
m_count = count;
|
m_count = count;
|
||||||
m_bindingCount = layout.bindingCount;
|
m_bindingCount = layout.bindingCount;
|
||||||
|
|
||||||
|
m_bindings.clear();
|
||||||
|
m_bindingRecords.clear();
|
||||||
|
m_bindingToRecordIndex.clear();
|
||||||
|
|
||||||
if (layout.bindingCount > 0 && layout.bindings != nullptr) {
|
if (layout.bindingCount > 0 && layout.bindings != nullptr) {
|
||||||
m_bindings = new DescriptorSetLayoutBinding[layout.bindingCount];
|
m_bindings.reserve(layout.bindingCount);
|
||||||
|
m_bindingRecords.reserve(layout.bindingCount);
|
||||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||||
m_bindings[i] = layout.bindings[i];
|
m_bindings.push_back(layout.bindings[i]);
|
||||||
|
|
||||||
|
BindingRecord record = {};
|
||||||
|
record.layout = layout.bindings[i];
|
||||||
|
m_bindingRecords.push_back(std::move(record));
|
||||||
|
m_bindingToRecordIndex[layout.bindings[i].binding] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nextDescriptorIndex = 0;
|
||||||
|
const DescriptorType orderedTypes[] = {
|
||||||
|
DescriptorType::SRV,
|
||||||
|
DescriptorType::UAV,
|
||||||
|
DescriptorType::Sampler,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (DescriptorType type : orderedTypes) {
|
||||||
|
if (!UsesDescriptorHeap(m_heap->GetType(), type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> matchingIndices;
|
||||||
|
matchingIndices.reserve(m_bindingRecords.size());
|
||||||
|
for (uint32_t i = 0; i < m_bindingRecords.size(); ++i) {
|
||||||
|
if (static_cast<DescriptorType>(m_bindingRecords[i].layout.type) == type) {
|
||||||
|
matchingIndices.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(
|
||||||
|
matchingIndices.begin(),
|
||||||
|
matchingIndices.end(),
|
||||||
|
[this](uint32_t left, uint32_t right) {
|
||||||
|
return m_bindingRecords[left].layout.binding < m_bindingRecords[right].layout.binding;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (uint32_t recordIndex : matchingIndices) {
|
||||||
|
m_bindingRecords[recordIndex].descriptorIndex = nextDescriptorIndex;
|
||||||
|
nextDescriptorIndex += m_bindingRecords[recordIndex].layout.count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,12 +107,9 @@ void D3D12DescriptorSet::Shutdown() {
|
|||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
m_count = 0;
|
m_count = 0;
|
||||||
m_bindingCount = 0;
|
m_bindingCount = 0;
|
||||||
m_constantBuffer.reset();
|
m_bindings.clear();
|
||||||
m_constantBufferCapacity = 0;
|
m_bindingRecords.clear();
|
||||||
if (m_bindings != nullptr) {
|
m_bindingToRecordIndex.clear();
|
||||||
delete[] m_bindings;
|
|
||||||
m_bindings = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12DescriptorSet::Bind() {
|
void D3D12DescriptorSet::Bind() {
|
||||||
@@ -68,17 +123,8 @@ void D3D12DescriptorSet::Update(uint32_t offset, RHIResourceView* view) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t descriptorOffset = 0;
|
const uint32_t descriptorOffset = GetDescriptorIndexForBinding(offset);
|
||||||
bool foundBinding = false;
|
if (descriptorOffset == UINT32_MAX) {
|
||||||
for (uint32_t i = 0; i < m_bindingCount; ++i) {
|
|
||||||
if (m_bindings[i].binding == offset) {
|
|
||||||
foundBinding = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
descriptorOffset += m_bindings[i].count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundBinding) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,17 +147,8 @@ void D3D12DescriptorSet::UpdateSampler(uint32_t offset, RHISampler* sampler) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t descriptorOffset = 0;
|
const uint32_t descriptorOffset = GetDescriptorIndexForBinding(offset);
|
||||||
bool foundBinding = false;
|
if (descriptorOffset == UINT32_MAX) {
|
||||||
for (uint32_t i = 0; i < m_bindingCount; ++i) {
|
|
||||||
if (m_bindings[i].binding == offset) {
|
|
||||||
foundBinding = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
descriptorOffset += m_bindings[i].count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundBinding) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,26 +159,75 @@ void D3D12DescriptorSet::UpdateSampler(uint32_t offset, RHISampler* sampler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorSet::GetGPUHandle(uint32_t index) const {
|
D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorSet::GetGPUHandle(uint32_t index) const {
|
||||||
if (m_heap == nullptr) {
|
if (m_heap == nullptr || index >= m_count) {
|
||||||
return D3D12_GPU_DESCRIPTOR_HANDLE{0};
|
return D3D12_GPU_DESCRIPTOR_HANDLE{0};
|
||||||
}
|
}
|
||||||
GPUDescriptorHandle handle = m_heap->GetGPUDescriptorHandle(m_offset + index);
|
GPUDescriptorHandle handle = m_heap->GetGPUDescriptorHandle(m_offset + index);
|
||||||
return D3D12_GPU_DESCRIPTOR_HANDLE{ handle.ptr };
|
return D3D12_GPU_DESCRIPTOR_HANDLE{ handle.ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12DescriptorSet::WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset) {
|
D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorSet::GetGPUHandleForBinding(uint32_t binding) const {
|
||||||
(void)binding;
|
const uint32_t descriptorIndex = GetDescriptorIndexForBinding(binding);
|
||||||
size_t requiredSize = offset + size;
|
if (descriptorIndex == UINT32_MAX) {
|
||||||
if (m_constantBufferData.size() < requiredSize) {
|
return D3D12_GPU_DESCRIPTOR_HANDLE{0};
|
||||||
m_constantBufferData.resize(requiredSize);
|
}
|
||||||
|
|
||||||
|
return GetGPUHandle(descriptorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D12DescriptorSet::WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset) {
|
||||||
|
BindingRecord* bindingRecord = FindBindingRecord(binding);
|
||||||
|
if (bindingRecord == nullptr ||
|
||||||
|
static_cast<DescriptorType>(bindingRecord->layout.type) != DescriptorType::CBV ||
|
||||||
|
data == nullptr ||
|
||||||
|
size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t requiredSize = offset + size;
|
||||||
|
if (bindingRecord->constantBufferData.size() < requiredSize) {
|
||||||
|
bindingRecord->constantBufferData.resize(requiredSize);
|
||||||
|
}
|
||||||
|
memcpy(bindingRecord->constantBufferData.data() + offset, data, size);
|
||||||
|
bindingRecord->constantBufferDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* D3D12DescriptorSet::GetConstantBufferData() {
|
||||||
|
BindingRecord* bindingRecord = FindFirstBindingRecordOfType(DescriptorType::CBV);
|
||||||
|
if (bindingRecord == nullptr || bindingRecord->constantBufferData.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindingRecord->constantBufferData.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t D3D12DescriptorSet::GetConstantBufferSize() const {
|
||||||
|
const BindingRecord* bindingRecord = FindFirstBindingRecordOfType(DescriptorType::CBV);
|
||||||
|
return bindingRecord != nullptr ? bindingRecord->constantBufferData.size() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3D12DescriptorSet::IsConstantDirty() const {
|
||||||
|
for (const BindingRecord& bindingRecord : m_bindingRecords) {
|
||||||
|
if (static_cast<DescriptorType>(bindingRecord.layout.type) == DescriptorType::CBV &&
|
||||||
|
bindingRecord.constantBufferDirty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D12DescriptorSet::MarkConstantClean() {
|
||||||
|
for (BindingRecord& bindingRecord : m_bindingRecords) {
|
||||||
|
if (static_cast<DescriptorType>(bindingRecord.layout.type) == DescriptorType::CBV) {
|
||||||
|
bindingRecord.constantBufferDirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
memcpy(m_constantBufferData.data() + offset, data, size);
|
|
||||||
m_constantBufferDirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D12DescriptorSet::HasBindingType(DescriptorType type) const {
|
bool D3D12DescriptorSet::HasBindingType(DescriptorType type) const {
|
||||||
for (uint32_t i = 0; i < m_bindingCount; ++i) {
|
for (const BindingRecord& bindingRecord : m_bindingRecords) {
|
||||||
if (static_cast<DescriptorType>(m_bindings[i].type) == type) {
|
if (static_cast<DescriptorType>(bindingRecord.layout.type) == type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,21 +235,42 @@ bool D3D12DescriptorSet::HasBindingType(DescriptorType type) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t D3D12DescriptorSet::GetFirstBindingOfType(DescriptorType type) const {
|
uint32_t D3D12DescriptorSet::GetFirstBindingOfType(DescriptorType type) const {
|
||||||
for (uint32_t i = 0; i < m_bindingCount; ++i) {
|
uint32_t firstBinding = UINT32_MAX;
|
||||||
if (static_cast<DescriptorType>(m_bindings[i].type) == type) {
|
for (const BindingRecord& bindingRecord : m_bindingRecords) {
|
||||||
return m_bindings[i].binding;
|
if (static_cast<DescriptorType>(bindingRecord.layout.type) == type) {
|
||||||
|
if (bindingRecord.layout.binding < firstBinding) {
|
||||||
|
firstBinding = bindingRecord.layout.binding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return firstBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t D3D12DescriptorSet::GetDescriptorIndexForBinding(uint32_t binding) const {
|
||||||
|
const BindingRecord* bindingRecord = FindBindingRecord(binding);
|
||||||
|
if (bindingRecord == nullptr || m_heap == nullptr) {
|
||||||
return UINT32_MAX;
|
return UINT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D12DescriptorSet::UploadConstantBuffer() {
|
if (!UsesDescriptorHeap(m_heap->GetType(), static_cast<DescriptorType>(bindingRecord->layout.type))) {
|
||||||
if (!HasBindingType(DescriptorType::CBV) || m_heap == nullptr || m_heap->GetDevice() == nullptr) {
|
return UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindingRecord->descriptorIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3D12DescriptorSet::UploadConstantBuffer(uint32_t binding) {
|
||||||
|
BindingRecord* bindingRecord = FindBindingRecord(binding);
|
||||||
|
if (bindingRecord == nullptr ||
|
||||||
|
static_cast<DescriptorType>(bindingRecord->layout.type) != DescriptorType::CBV ||
|
||||||
|
m_heap == nullptr ||
|
||||||
|
m_heap->GetDevice() == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t alignedSize = AlignConstantBufferSize(m_constantBufferData.size());
|
const uint64_t alignedSize = AlignConstantBufferSize(bindingRecord->constantBufferData.size());
|
||||||
if (!m_constantBuffer || m_constantBufferCapacity < alignedSize) {
|
if (!bindingRecord->constantBuffer || bindingRecord->constantBufferCapacity < alignedSize) {
|
||||||
auto constantBuffer = std::make_unique<D3D12Buffer>();
|
auto constantBuffer = std::make_unique<D3D12Buffer>();
|
||||||
if (!constantBuffer->Initialize(
|
if (!constantBuffer->Initialize(
|
||||||
m_heap->GetDevice(),
|
m_heap->GetDevice(),
|
||||||
@@ -175,21 +282,66 @@ bool D3D12DescriptorSet::UploadConstantBuffer() {
|
|||||||
|
|
||||||
constantBuffer->SetBufferType(BufferType::Constant);
|
constantBuffer->SetBufferType(BufferType::Constant);
|
||||||
constantBuffer->SetStride(static_cast<uint32_t>(alignedSize));
|
constantBuffer->SetStride(static_cast<uint32_t>(alignedSize));
|
||||||
m_constantBuffer = std::move(constantBuffer);
|
bindingRecord->constantBuffer = std::move(constantBuffer);
|
||||||
m_constantBufferCapacity = alignedSize;
|
bindingRecord->constantBufferCapacity = alignedSize;
|
||||||
m_constantBufferDirty = true;
|
bindingRecord->constantBufferDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_constantBufferDirty && !m_constantBufferData.empty()) {
|
if (bindingRecord->constantBufferDirty && !bindingRecord->constantBufferData.empty()) {
|
||||||
m_constantBuffer->SetData(m_constantBufferData.data(), m_constantBufferData.size());
|
bindingRecord->constantBuffer->SetData(
|
||||||
m_constantBufferDirty = false;
|
bindingRecord->constantBufferData.data(),
|
||||||
|
bindingRecord->constantBufferData.size());
|
||||||
|
bindingRecord->constantBufferDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_constantBuffer != nullptr;
|
return bindingRecord->constantBuffer != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS D3D12DescriptorSet::GetConstantBufferGPUAddress() const {
|
D3D12_GPU_VIRTUAL_ADDRESS D3D12DescriptorSet::GetConstantBufferGPUAddress(uint32_t binding) const {
|
||||||
return m_constantBuffer ? m_constantBuffer->GetGPUVirtualAddress() : 0;
|
const BindingRecord* bindingRecord = FindBindingRecord(binding);
|
||||||
|
if (bindingRecord == nullptr || bindingRecord->constantBuffer == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindingRecord->constantBuffer->GetGPUVirtualAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12DescriptorSet::BindingRecord* D3D12DescriptorSet::FindBindingRecord(uint32_t binding) {
|
||||||
|
auto it = m_bindingToRecordIndex.find(binding);
|
||||||
|
if (it == m_bindingToRecordIndex.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_bindingRecords[it->second];
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3D12DescriptorSet::BindingRecord* D3D12DescriptorSet::FindBindingRecord(uint32_t binding) const {
|
||||||
|
auto it = m_bindingToRecordIndex.find(binding);
|
||||||
|
if (it == m_bindingToRecordIndex.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_bindingRecords[it->second];
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12DescriptorSet::BindingRecord* D3D12DescriptorSet::FindFirstBindingRecordOfType(DescriptorType type) {
|
||||||
|
for (BindingRecord& bindingRecord : m_bindingRecords) {
|
||||||
|
if (static_cast<DescriptorType>(bindingRecord.layout.type) == type) {
|
||||||
|
return &bindingRecord;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3D12DescriptorSet::BindingRecord* D3D12DescriptorSet::FindFirstBindingRecordOfType(DescriptorType type) const {
|
||||||
|
for (const BindingRecord& bindingRecord : m_bindingRecords) {
|
||||||
|
if (static_cast<DescriptorType>(bindingRecord.layout.type) == type) {
|
||||||
|
return &bindingRecord;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace RHI
|
} // namespace RHI
|
||||||
|
|||||||
@@ -26,14 +26,19 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
|
|||||||
|
|
||||||
m_rootParameters.clear();
|
m_rootParameters.clear();
|
||||||
m_descriptorRanges.clear();
|
m_descriptorRanges.clear();
|
||||||
m_registerToRootIndex.clear();
|
m_constantBufferRootIndices.clear();
|
||||||
|
m_shaderResourceTableRootIndex = UINT32_MAX;
|
||||||
|
m_unorderedAccessTableRootIndex = UINT32_MAX;
|
||||||
|
m_samplerTableRootIndex = UINT32_MAX;
|
||||||
|
|
||||||
const uint32_t rootParameterCount =
|
const uint32_t rootParameterCount =
|
||||||
desc.constantBufferCount +
|
desc.constantBufferCount +
|
||||||
(desc.textureCount > 0 ? 1u : 0u) +
|
(desc.textureCount > 0 ? 1u : 0u) +
|
||||||
|
(desc.uavCount > 0 ? 1u : 0u) +
|
||||||
(desc.samplerCount > 0 ? 1u : 0u);
|
(desc.samplerCount > 0 ? 1u : 0u);
|
||||||
const uint32_t descriptorRangeCount =
|
const uint32_t descriptorRangeCount =
|
||||||
(desc.textureCount > 0 ? 1u : 0u) +
|
(desc.textureCount > 0 ? 1u : 0u) +
|
||||||
|
(desc.uavCount > 0 ? 1u : 0u) +
|
||||||
(desc.samplerCount > 0 ? 1u : 0u);
|
(desc.samplerCount > 0 ? 1u : 0u);
|
||||||
|
|
||||||
m_rootParameters.reserve(rootParameterCount);
|
m_rootParameters.reserve(rootParameterCount);
|
||||||
@@ -44,7 +49,7 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
|
|||||||
for (uint32_t i = 0; i < desc.constantBufferCount; ++i) {
|
for (uint32_t i = 0; i < desc.constantBufferCount; ++i) {
|
||||||
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateCBV(i, ShaderVisibility::All, 0);
|
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateCBV(i, ShaderVisibility::All, 0);
|
||||||
m_rootParameters.push_back(param);
|
m_rootParameters.push_back(param);
|
||||||
m_registerToRootIndex[i] = rootIndex;
|
m_constantBufferRootIndices[i] = rootIndex;
|
||||||
rootIndex++;
|
rootIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,9 +59,17 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
|
|||||||
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
|
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
|
||||||
1, &m_descriptorRanges.back(), ShaderVisibility::All);
|
1, &m_descriptorRanges.back(), ShaderVisibility::All);
|
||||||
m_rootParameters.push_back(param);
|
m_rootParameters.push_back(param);
|
||||||
for (uint32_t i = 0; i < desc.textureCount; ++i) {
|
m_shaderResourceTableRootIndex = rootIndex;
|
||||||
m_registerToRootIndex[100 + i] = rootIndex;
|
rootIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (desc.uavCount > 0) {
|
||||||
|
m_descriptorRanges.push_back(D3D12RootSignature::CreateDescriptorRange(
|
||||||
|
D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, desc.uavCount, 0));
|
||||||
|
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
|
||||||
|
1, &m_descriptorRanges.back(), ShaderVisibility::All);
|
||||||
|
m_rootParameters.push_back(param);
|
||||||
|
m_unorderedAccessTableRootIndex = rootIndex;
|
||||||
rootIndex++;
|
rootIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +79,7 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
|
|||||||
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
|
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
|
||||||
1, &m_descriptorRanges.back(), ShaderVisibility::All);
|
1, &m_descriptorRanges.back(), ShaderVisibility::All);
|
||||||
m_rootParameters.push_back(param);
|
m_rootParameters.push_back(param);
|
||||||
for (uint32_t i = 0; i < desc.samplerCount; ++i) {
|
m_samplerTableRootIndex = rootIndex;
|
||||||
m_registerToRootIndex[200 + i] = rootIndex;
|
|
||||||
}
|
|
||||||
rootIndex++;
|
rootIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,20 +120,47 @@ void D3D12PipelineLayout::Shutdown() {
|
|||||||
m_desc = {};
|
m_desc = {};
|
||||||
m_rootParameters.clear();
|
m_rootParameters.clear();
|
||||||
m_descriptorRanges.clear();
|
m_descriptorRanges.clear();
|
||||||
m_registerToRootIndex.clear();
|
m_constantBufferRootIndices.clear();
|
||||||
|
m_shaderResourceTableRootIndex = UINT32_MAX;
|
||||||
|
m_unorderedAccessTableRootIndex = UINT32_MAX;
|
||||||
|
m_samplerTableRootIndex = UINT32_MAX;
|
||||||
m_device = nullptr;
|
m_device = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t D3D12PipelineLayout::GetRootParameterIndex(uint32_t shaderRegister) const {
|
bool D3D12PipelineLayout::HasConstantBufferBinding(uint32_t binding) const {
|
||||||
auto it = m_registerToRootIndex.find(shaderRegister);
|
return m_constantBufferRootIndices.find(binding) != m_constantBufferRootIndices.end();
|
||||||
if (it != m_registerToRootIndex.end()) {
|
}
|
||||||
|
|
||||||
|
uint32_t D3D12PipelineLayout::GetConstantBufferRootParameterIndex(uint32_t binding) const {
|
||||||
|
auto it = m_constantBufferRootIndices.find(binding);
|
||||||
|
if (it != m_constantBufferRootIndices.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
return UINT32_MAX;
|
return UINT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D12PipelineLayout::HasRootParameter(uint32_t shaderRegister) const {
|
bool D3D12PipelineLayout::HasShaderResourceTable() const {
|
||||||
return m_registerToRootIndex.find(shaderRegister) != m_registerToRootIndex.end();
|
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
|
||||||
|
|||||||
@@ -407,6 +407,105 @@ TEST_P(RHITestFixture, DescriptorSet_MultipleAllocations_AdvanceDescriptorOffset
|
|||||||
delete pool;
|
delete pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, DescriptorSet_D3D12MixedBindings_AssignDescriptorIndicesByType) {
|
||||||
|
if (GetBackendType() != RHIType::D3D12) {
|
||||||
|
GTEST_SKIP() << "D3D12-specific descriptor index verification";
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorPoolDesc poolDesc = {};
|
||||||
|
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
|
||||||
|
poolDesc.descriptorCount = 4;
|
||||||
|
poolDesc.shaderVisible = true;
|
||||||
|
|
||||||
|
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
|
||||||
|
ASSERT_NE(pool, nullptr);
|
||||||
|
|
||||||
|
DescriptorSetLayoutBinding bindings[3] = {};
|
||||||
|
bindings[0].binding = 2;
|
||||||
|
bindings[0].type = static_cast<uint32_t>(DescriptorType::UAV);
|
||||||
|
bindings[0].count = 1;
|
||||||
|
bindings[1].binding = 0;
|
||||||
|
bindings[1].type = static_cast<uint32_t>(DescriptorType::CBV);
|
||||||
|
bindings[1].count = 1;
|
||||||
|
bindings[2].binding = 1;
|
||||||
|
bindings[2].type = static_cast<uint32_t>(DescriptorType::SRV);
|
||||||
|
bindings[2].count = 1;
|
||||||
|
|
||||||
|
DescriptorSetLayoutDesc layoutDesc = {};
|
||||||
|
layoutDesc.bindings = bindings;
|
||||||
|
layoutDesc.bindingCount = 3;
|
||||||
|
|
||||||
|
RHIDescriptorSet* firstSet = pool->AllocateSet(layoutDesc);
|
||||||
|
RHIDescriptorSet* secondSet = pool->AllocateSet(layoutDesc);
|
||||||
|
ASSERT_NE(firstSet, nullptr);
|
||||||
|
ASSERT_NE(secondSet, nullptr);
|
||||||
|
|
||||||
|
auto* firstD3D12Set = static_cast<D3D12DescriptorSet*>(firstSet);
|
||||||
|
auto* secondD3D12Set = static_cast<D3D12DescriptorSet*>(secondSet);
|
||||||
|
EXPECT_EQ(firstD3D12Set->GetCount(), 2u);
|
||||||
|
EXPECT_EQ(firstD3D12Set->GetDescriptorIndexForBinding(1), 0u);
|
||||||
|
EXPECT_EQ(firstD3D12Set->GetDescriptorIndexForBinding(2), 1u);
|
||||||
|
EXPECT_EQ(firstD3D12Set->GetDescriptorIndexForBinding(0), UINT32_MAX);
|
||||||
|
EXPECT_EQ(firstD3D12Set->GetOffset(), 0u);
|
||||||
|
EXPECT_EQ(secondD3D12Set->GetOffset(), 2u);
|
||||||
|
|
||||||
|
firstSet->Shutdown();
|
||||||
|
delete firstSet;
|
||||||
|
secondSet->Shutdown();
|
||||||
|
delete secondSet;
|
||||||
|
pool->Shutdown();
|
||||||
|
delete pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, DescriptorSet_D3D12MultipleConstantBuffersUploadIndependently) {
|
||||||
|
if (GetBackendType() != RHIType::D3D12) {
|
||||||
|
GTEST_SKIP() << "D3D12-specific constant buffer verification";
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorPoolDesc poolDesc = {};
|
||||||
|
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
|
||||||
|
poolDesc.descriptorCount = 1;
|
||||||
|
poolDesc.shaderVisible = false;
|
||||||
|
|
||||||
|
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
|
||||||
|
ASSERT_NE(pool, nullptr);
|
||||||
|
|
||||||
|
DescriptorSetLayoutBinding bindings[2] = {};
|
||||||
|
bindings[0].binding = 0;
|
||||||
|
bindings[0].type = static_cast<uint32_t>(DescriptorType::CBV);
|
||||||
|
bindings[0].count = 1;
|
||||||
|
bindings[1].binding = 1;
|
||||||
|
bindings[1].type = static_cast<uint32_t>(DescriptorType::CBV);
|
||||||
|
bindings[1].count = 1;
|
||||||
|
|
||||||
|
DescriptorSetLayoutDesc layoutDesc = {};
|
||||||
|
layoutDesc.bindings = bindings;
|
||||||
|
layoutDesc.bindingCount = 2;
|
||||||
|
|
||||||
|
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
|
||||||
|
ASSERT_NE(set, nullptr);
|
||||||
|
|
||||||
|
auto* d3d12Set = static_cast<D3D12DescriptorSet*>(set);
|
||||||
|
const float firstData[16] = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
const float secondData[16] = { 2.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
d3d12Set->WriteConstant(0, firstData, sizeof(firstData));
|
||||||
|
d3d12Set->WriteConstant(1, secondData, sizeof(secondData));
|
||||||
|
|
||||||
|
ASSERT_TRUE(d3d12Set->UploadConstantBuffer(0));
|
||||||
|
ASSERT_TRUE(d3d12Set->UploadConstantBuffer(1));
|
||||||
|
|
||||||
|
const D3D12_GPU_VIRTUAL_ADDRESS firstAddress = d3d12Set->GetConstantBufferGPUAddress(0);
|
||||||
|
const D3D12_GPU_VIRTUAL_ADDRESS secondAddress = d3d12Set->GetConstantBufferGPUAddress(1);
|
||||||
|
EXPECT_NE(firstAddress, 0u);
|
||||||
|
EXPECT_NE(secondAddress, 0u);
|
||||||
|
EXPECT_NE(firstAddress, secondAddress);
|
||||||
|
|
||||||
|
set->Shutdown();
|
||||||
|
delete set;
|
||||||
|
pool->Shutdown();
|
||||||
|
delete pool;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(RHITestFixture, DescriptorSet_Update_UsesBindingNumberOnOpenGL) {
|
TEST_P(RHITestFixture, DescriptorSet_Update_UsesBindingNumberOnOpenGL) {
|
||||||
if (GetBackendType() != RHIType::OpenGL) {
|
if (GetBackendType() != RHIType::OpenGL) {
|
||||||
GTEST_SKIP() << "OpenGL-specific descriptor binding verification";
|
GTEST_SKIP() << "OpenGL-specific descriptor binding verification";
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ TEST_P(RHITestFixture, PipelineLayout_DescriptorSetAllocation) {
|
|||||||
delete layout;
|
delete layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(RHITestFixture, PipelineLayout_D3D12ConstantBuffers_MapToDistinctRootParameters) {
|
TEST_P(RHITestFixture, PipelineLayout_D3D12TracksDistinctBindingClasses) {
|
||||||
if (GetBackendType() != RHIType::D3D12) {
|
if (GetBackendType() != RHIType::D3D12) {
|
||||||
GTEST_SKIP() << "D3D12-specific root parameter verification";
|
GTEST_SKIP() << "D3D12-specific root parameter verification";
|
||||||
}
|
}
|
||||||
@@ -154,17 +154,30 @@ TEST_P(RHITestFixture, PipelineLayout_D3D12ConstantBuffers_MapToDistinctRootPara
|
|||||||
RHIPipelineLayoutDesc desc = {};
|
RHIPipelineLayoutDesc desc = {};
|
||||||
desc.constantBufferCount = 2;
|
desc.constantBufferCount = 2;
|
||||||
desc.textureCount = 1;
|
desc.textureCount = 1;
|
||||||
|
desc.uavCount = 1;
|
||||||
desc.samplerCount = 1;
|
desc.samplerCount = 1;
|
||||||
|
|
||||||
RHIPipelineLayout* layout = GetDevice()->CreatePipelineLayout(desc);
|
RHIPipelineLayout* layout = GetDevice()->CreatePipelineLayout(desc);
|
||||||
ASSERT_NE(layout, nullptr);
|
ASSERT_NE(layout, nullptr);
|
||||||
|
|
||||||
auto* d3d12Layout = static_cast<D3D12PipelineLayout*>(layout);
|
auto* d3d12Layout = static_cast<D3D12PipelineLayout*>(layout);
|
||||||
EXPECT_TRUE(d3d12Layout->HasRootParameter(0));
|
EXPECT_TRUE(d3d12Layout->HasConstantBufferBinding(0));
|
||||||
EXPECT_TRUE(d3d12Layout->HasRootParameter(1));
|
EXPECT_TRUE(d3d12Layout->HasConstantBufferBinding(1));
|
||||||
EXPECT_TRUE(d3d12Layout->HasRootParameter(100));
|
EXPECT_FALSE(d3d12Layout->HasConstantBufferBinding(2));
|
||||||
EXPECT_TRUE(d3d12Layout->HasRootParameter(200));
|
|
||||||
EXPECT_NE(d3d12Layout->GetRootParameterIndex(0), d3d12Layout->GetRootParameterIndex(1));
|
EXPECT_TRUE(d3d12Layout->HasShaderResourceTable());
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasUnorderedAccessTable());
|
||||||
|
EXPECT_TRUE(d3d12Layout->HasSamplerTable());
|
||||||
|
|
||||||
|
EXPECT_NE(
|
||||||
|
d3d12Layout->GetConstantBufferRootParameterIndex(0),
|
||||||
|
d3d12Layout->GetConstantBufferRootParameterIndex(1));
|
||||||
|
EXPECT_NE(
|
||||||
|
d3d12Layout->GetShaderResourceTableRootParameterIndex(),
|
||||||
|
d3d12Layout->GetUnorderedAccessTableRootParameterIndex());
|
||||||
|
EXPECT_NE(
|
||||||
|
d3d12Layout->GetUnorderedAccessTableRootParameterIndex(),
|
||||||
|
d3d12Layout->GetSamplerTableRootParameterIndex());
|
||||||
|
|
||||||
layout->Shutdown();
|
layout->Shutdown();
|
||||||
delete layout;
|
delete layout;
|
||||||
|
|||||||
Reference in New Issue
Block a user