diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-02-23 22:55:03 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:38:10 +0000 |
| commit | ef714d980193bb09b97deafe672a81ace1518ad6 (patch) | |
| tree | e24508f11fddd32ead1ce8ead1b111dc06dfac31 /Graphics/GraphicsEngineD3D12 | |
| parent | D3D12: optimized CommitRootTables by creatin DescriptorHeapAllocation objects... (diff) | |
| download | DiligentCore-ef714d980193bb09b97deafe672a81ace1518ad6.tar.gz DiligentCore-ef714d980193bb09b97deafe672a81ace1518ad6.zip | |
Reworked ShaderResourceCacheD3D12 to keep track of bound dynamic root buffer indices; optimized CommitRootViews
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
7 files changed, 325 insertions, 244 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp index eaa2c817..3cf8d702 100644 --- a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp +++ b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp @@ -196,7 +196,7 @@ public: // Returns pointer to D3D12 descriptor heap that contains this allocation - ID3D12DescriptorHeap* GetDescriptorHeap() { return m_pDescriptorHeap; } + ID3D12DescriptorHeap* GetDescriptorHeap() const { return m_pDescriptorHeap; } // clang-format off diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp index af251389..ef73d277 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp @@ -255,20 +255,20 @@ public: Uint32 ResIndex, const ShaderResourceCacheD3D12& ResourceCache) const; - void CommitRootTables(ShaderResourceCacheD3D12& ResourceCache, - CommandContext& Ctx, - DeviceContextD3D12Impl* pDeviceCtx, - Uint32 DeviceCtxId, - bool IsCompute, - Uint32 BaseRootIndex) const; - - void CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, - CommandContext& Ctx, - DeviceContextD3D12Impl* pDeviceCtx, - Uint32 DeviceCtxId, - Uint32 BaseRootIndex, - bool IsCompute, - bool CommitDynamicBuffers) const; + void CommitRootTables(const ShaderResourceCacheD3D12& ResourceCache, + CommandContext& Ctx, + DeviceContextD3D12Impl* pDeviceCtx, + Uint32 DeviceCtxId, + bool IsCompute, + Uint32 BaseRootIndex) const; + + void CommitRootViews(const ShaderResourceCacheD3D12& ResourceCache, + CommandContext& Ctx, + DeviceContextD3D12Impl* pDeviceCtx, + Uint32 DeviceCtxId, + Uint32 BaseRootIndex, + bool IsCompute, + Uint64 BuffersMask) const; const RootParamsManager& GetRootParams() const { return m_RootParams; } @@ -285,8 +285,7 @@ public: Uint32 ResIndex, const ShaderResourceCacheD3D12& ResourceCache, const char* ShaderName, - const char* PSOName, - Uint32& DynamicRootBuffersCounter) const; + const char* PSOName) const; #endif private: diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp index f6b2e3b4..4be8fdbe 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp @@ -160,43 +160,73 @@ public: class RootTable { public: - RootTable(Uint32 NumResources, Resource* pResources, Uint32 TableStartOffset = InvalidDescriptorOffset) noexcept : + RootTable(Uint32 _NumResources, + Resource* _pResources, + bool _IsRootView, + Uint32 _TableStartOffset = InvalidDescriptorOffset) noexcept : // clang-format off - m_NumResources {NumResources }, - m_pResources {pResources }, - m_TableStartOffset{TableStartOffset} + m_NumResources {_NumResources }, + m_IsRootView {_IsRootView ? 1u : 0u}, + m_pResources {_pResources }, + m_TableStartOffset{_TableStartOffset } // clang-format on - {} + { + VERIFY_EXPR(GetSize() == _NumResources); + VERIFY_EXPR(IsRootView() == _IsRootView); + VERIFY(!IsRootView() || GetSize() == 1, "Root views may only contain one resource"); + } const Resource& GetResource(Uint32 OffsetFromTableStart) const { VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart); return m_pResources[OffsetFromTableStart]; } + + Uint32 GetSize() const { return m_NumResources; } + Uint32 GetStartOffset() const { return m_TableStartOffset; } + bool IsRootView() const { return m_IsRootView != 0; } + + private: + friend class ShaderResourceCacheD3D12; Resource& GetResource(Uint32 OffsetFromTableStart) { VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart); return m_pResources[OffsetFromTableStart]; } - Uint32 GetSize() const { return m_NumResources; } - Uint32 GetStartOffset() const { return m_TableStartOffset; } - private: // Offset from the start of the descriptor heap allocation to the start of the table const Uint32 m_TableStartOffset; - // The total number of resources in the table, accounting for array size - const Uint32 m_NumResources; + // The total number of resources in the table, accounting for array sizes + const Uint32 m_NumResources : 31; + + // Flag indicating if this table stores the resource of a root view + const Uint32 m_IsRootView : 1; Resource* const m_pResources; }; - RootTable& GetRootTable(Uint32 RootIndex) + + const Resource& SetResource(Uint32 RootIndex, + Uint32 OffsetFromTableStart, + SHADER_RESOURCE_TYPE Type, + D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle, + RefCntAutoPtr<IDeviceObject>&& pObject); + + const Resource& CopyResource(Uint32 RootIndex, + Uint32 OffsetFromTableStart, + const Resource& SrcRes) { - VERIFY_EXPR(RootIndex < m_NumTables); - return reinterpret_cast<RootTable*>(m_pMemory.get())[RootIndex]; + return SetResource(RootIndex, OffsetFromTableStart, SrcRes.Type, SrcRes.CPUDescriptorHandle, RefCntAutoPtr<IDeviceObject>{SrcRes.pObject}); + } + + const Resource& ResetResource(Uint32 RootIndex, + Uint32 OffsetFromTableStart) + { + return SetResource(RootIndex, OffsetFromTableStart, SHADER_RESOURCE_TYPE_UNKNOWN, D3D12_CPU_DESCRIPTOR_HANDLE{}, RefCntAutoPtr<IDeviceObject>{}); } + const RootTable& GetRootTable(Uint32 RootIndex) const { VERIFY_EXPR(RootIndex < m_NumTables); @@ -205,7 +235,7 @@ public: Uint32 GetNumRootTables() const { return m_NumTables; } - ID3D12DescriptorHeap* GetDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, ROOT_PARAMETER_GROUP Group) + ID3D12DescriptorHeap* GetDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, ROOT_PARAMETER_GROUP Group) const { auto AllocationIdx = m_AllocationIndex[HeapType][Group]; return AllocationIdx >= 0 ? m_DescriptorAllocations[AllocationIdx].GetDescriptorHeap() : nullptr; @@ -230,8 +260,8 @@ public: return m_DescriptorAllocations[AllocationIdx].GetHandle<HandleType>(RootParam.GetStartOffset() + OffsetFromTableStart); } - DescriptorHeapAllocation& GetDescriptorAllocation(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, - ROOT_PARAMETER_GROUP Group) + const DescriptorHeapAllocation& GetDescriptorAllocation(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, + ROOT_PARAMETER_GROUP Group) const { const auto AllocationIdx = m_AllocationIndex[HeapType][Group]; VERIFY(AllocationIdx >= 0, "Descriptor space is not assigned to this combination of heap type and parameter group"); @@ -246,14 +276,22 @@ public: }; void TransitionResourceStates(CommandContext& Ctx, StateTransitionMode Mode); - Uint32& GetDynamicRootBuffersCounter() { return m_NumDynamicRootBuffers; } + CacheContentType GetContentType() const { return m_ContentType; } - // Returns the number of dynamic buffers bound as root views in the cache regardless of their variable types - Uint32 GetNumDynamicRootBuffers() const { return m_NumDynamicRootBuffers; } + Uint64 GetDynamicRootBuffersMask() const { return m_DynamicRootBuffersMask; } + Uint64 GetNonDynamicRootBuffersMask() const { return m_NonDynamicRootBuffersMask; } - CacheContentType GetContentType() const { return m_ContentType; } +#ifdef DILIGENT_DEBUG + void DbgValidateDynamicBuffersMask() const; +#endif private: + RootTable& GetRootTable(Uint32 RootIndex) + { + VERIFY_EXPR(RootIndex < m_NumTables); + return reinterpret_cast<RootTable*>(m_pMemory.get())[RootIndex]; + } + Resource& GetResource(Uint32 Idx) { VERIFY_EXPR(Idx < m_TotalResourceCount); @@ -262,15 +300,14 @@ private: size_t AllocateMemory(IMemoryAllocator& MemAllocator); +private: + static constexpr Uint32 MaxRootTables = 64; + std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory; // Descriptor heap allocations, indexed by m_AllocationIndex DescriptorHeapAllocation* m_DescriptorAllocations = nullptr; - // The number of the dynamic buffers bound in the resource cache as root views - // regardless of their variable type - Uint32 m_NumDynamicRootBuffers = 0; - // The total number of resources in the cache Uint32 m_TotalResourceCount = 0; @@ -287,7 +324,12 @@ private: // (CBV_SRV_UAV, SAMPLER) and GPU visibility. // -1 indicates no allocation. std::array<std::array<Int8, ROOT_PARAMETER_GROUP_COUNT>, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER + 1> m_AllocationIndex{}; + + // The bitmask indicating root views with bound dynamic buffers + Uint64 m_DynamicRootBuffersMask = Uint64{0}; + + // The bitmask indicating root views with bound non-dynamic buffers + Uint64 m_NonDynamicRootBuffersMask = Uint64{0}; }; -static_assert(sizeof(ShaderResourceCacheD3D12) == sizeof(void*) * 3 + 16, "Unexpected sizeof(ShaderResourceCacheD3D12) - did you pack the members properly?"); } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 4066ca1b..014792af 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -315,14 +315,22 @@ void DeviceContextD3D12Impl::CommitRootTablesAndViews(RootTableInfo& RootInfo) auto* const pSRB = RootInfo.SRBs[s]; DEV_CHECK_ERR(pSRB != nullptr, "No SRB is committed and binding index ", s); + VERIFY_EXPR(pSRB->GetBindingIndex() == s); + const auto& ResourceCache = pSRB->GetResourceCache(); if (!RootInfo.bRootTablesCommited) { - pSignature->CommitRootTables(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), IsCompute, RootSig.GetBaseRootIndex(s)); + pSignature->CommitRootTables(ResourceCache, CmdCtx, this, GetContextId(), IsCompute, RootSig.GetBaseRootIndex(s)); } // Always commit root views. This method is not called if root views are up to date - constexpr auto CommitDynamicBuffers = true; - pSignature->CommitRootViews(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootSig.GetBaseRootIndex(s), IsCompute, CommitDynamicBuffers); + if (auto DynamicRootBuffersMask = ResourceCache.GetDynamicRootBuffersMask()) + { + pSignature->CommitRootViews(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootSig.GetBaseRootIndex(s), IsCompute, DynamicRootBuffersMask); + } + else + { + VERIFY((RootInfo.DynamicBuffersMask & (Uint64{1} << s)) == 0, "There are no dynamic root buffers in the cache, but the bit in DynamicBuffersMask is set"); + } } RootInfo.bRootTablesCommited = true; @@ -355,6 +363,10 @@ void DeviceContextD3D12Impl::CommitShaderResources(IShaderResourceBinding* pShad auto& CmdCtx = GetCmdContext(); auto* pSignature = pResBindingD3D12Impl->GetSignature(); +#ifdef DILIGENT_DEBUG + ResourceCache.DbgValidateDynamicBuffersMask(); +#endif + if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { ResourceCache.TransitionResourceStates(CmdCtx, ShaderResourceCacheD3D12::StateTransitionMode::Transition); @@ -371,7 +383,7 @@ void DeviceContextD3D12Impl::CommitShaderResources(IShaderResourceBinding* pShad RootInfo.SRBs[SRBIndex] = pResBindingD3D12Impl; - if (ResourceCache.GetDynamicRootBuffersCounter() > 0) + if (ResourceCache.GetDynamicRootBuffersMask() != 0) RootInfo.SetDynamicBufferBit(SRBIndex); else RootInfo.ClearDynamicBufferBit(SRBIndex); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp index b7f2141f..b285f58b 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp @@ -442,88 +442,6 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach ResourceCache.Initialize(CacheMemAllocator, m_pDevice, m_RootParams); } -inline void UpdateDynamicRootBuffersCounter(const BufferD3D12Impl* pOldBuff, - const BufferD3D12Impl* pNewBuff, - Uint32& BuffCounter, - D3D12_ROOT_PARAMETER_TYPE d3d12RootParamType) -{ - if (pOldBuff != nullptr && pOldBuff->GetDesc().Usage == USAGE_DYNAMIC) - { - if (d3d12RootParamType == D3D12_ROOT_PARAMETER_TYPE_CBV) - { - // Only count dynamic buffers bound as root views - VERIFY(BuffCounter > 0, "There is a dynamic root buffer in the resource cache, but dynamic buffers counter is zero"); - --BuffCounter; - } - else - { - VERIFY_EXPR(pOldBuff->GetD3D12Resource() != nullptr); - } - } - if (pNewBuff != nullptr && pNewBuff->GetDesc().Usage == USAGE_DYNAMIC) - { - if (d3d12RootParamType == D3D12_ROOT_PARAMETER_TYPE_CBV) - { - // Only count dynamic buffers bound as root views - ++BuffCounter; - } - else - { - DEV_CHECK_ERR(pNewBuff->GetD3D12Resource() != nullptr, - "Dynamic constant buffers that don't have backing d3d12 resource must be bound as root views"); - } - } -} - -inline void UpdateDynamicRootBuffersCounter(const BufferViewD3D12Impl* pOldBuffView, - const BufferViewD3D12Impl* pNewBuffView, - Uint32& BuffCounter, - D3D12_ROOT_PARAMETER_TYPE d3d12RootParamType) -{ - if (pOldBuffView != nullptr) - { - auto* const pOldBuff = pOldBuffView->GetBuffer<BufferD3D12Impl>(); - if (pOldBuff->GetDesc().Usage == USAGE_DYNAMIC) - { - if (d3d12RootParamType == D3D12_ROOT_PARAMETER_TYPE_SRV || d3d12RootParamType == D3D12_ROOT_PARAMETER_TYPE_UAV) - { - // Only count dynamic buffers bound as root views - VERIFY(BuffCounter > 0, "There is a dynamic root buffer in the resource cache, but dynamic buffers counter is zero"); - --BuffCounter; - } - else - { - VERIFY_EXPR(pOldBuff->GetD3D12Resource() != nullptr); - } - } - } - if (pNewBuffView != nullptr) - { - auto* const pNewBuffer = pNewBuffView->GetBuffer<BufferD3D12Impl>(); - if (pNewBuffer->GetDesc().Usage == USAGE_DYNAMIC) - { - if (d3d12RootParamType == D3D12_ROOT_PARAMETER_TYPE_SRV || d3d12RootParamType == D3D12_ROOT_PARAMETER_TYPE_UAV) - { - // Only count dynamic buffers bound as root views - ++BuffCounter; - } - else - { - DEV_CHECK_ERR(pNewBuffer->GetD3D12Resource() != nullptr, - "Dynamic buffers that don't have backing d3d12 resource must be bound as root views"); - } - } - } -} - -inline void UpdateDynamicRootBuffersCounter(const TextureViewD3D12Impl*, - const TextureViewD3D12Impl*, - Uint32&, - D3D12_ROOT_PARAMETER_TYPE) -{ -} - - void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderResourceCacheD3D12& DstResourceCache) const { if (m_pStaticResCache == nullptr) @@ -539,8 +457,6 @@ void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderReso VERIFY_EXPR(SrcCacheType == ShaderResourceCacheD3D12::CacheContentType::Signature); VERIFY_EXPR(DstCacheType == ShaderResourceCacheD3D12::CacheContentType::SRB); - auto& DynamicRootBuffersCounter = DstResourceCache.GetDynamicRootBuffersCounter(); - for (Uint32 r = ResIdxRange.first; r < ResIdxRange.second; ++r) { const auto& ResDesc = GetResourceDesc(r); @@ -555,7 +471,7 @@ void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderReso const auto DstRootIndex = Attr.RootIndex(DstCacheType); const auto SrcRootIndex = Attr.RootIndex(SrcCacheType); const auto& SrcRootTable = SrcResourceCache.GetRootTable(SrcRootIndex); - auto& DstRootTable = DstResourceCache.GetRootTable(DstRootIndex); + const auto& DstRootTable = const_cast<const ShaderResourceCacheD3D12&>(DstResourceCache).GetRootTable(DstRootIndex); auto SrcCacheOffset = Attr.OffsetFromTableStart(SrcCacheType); auto DstCacheOffset = Attr.OffsetFromTableStart(DstCacheType); @@ -565,29 +481,12 @@ void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderReso if (!SrcRes.pObject) LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetShaderResourcePrintName(ResDesc, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'."); - auto& DstRes = DstRootTable.GetResource(DstCacheOffset); + const auto& DstRes = DstRootTable.GetResource(DstCacheOffset); if (DstRes.pObject != SrcRes.pObject) { DEV_CHECK_ERR(DstRes.pObject == nullptr, "Static resource has already been initialized, and the new resource does not match previously assigned resource."); - if (SrcRes.Type == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER) - { - UpdateDynamicRootBuffersCounter(DstRes.pObject.RawPtr<const BufferD3D12Impl>(), - SrcRes.pObject.RawPtr<const BufferD3D12Impl>(), - DynamicRootBuffersCounter, - Attr.GetD3D12RootParamType()); - } - else if (SrcRes.Type == SHADER_RESOURCE_TYPE_BUFFER_SRV || SrcRes.Type == SHADER_RESOURCE_TYPE_BUFFER_UAV) - { - UpdateDynamicRootBuffersCounter(DstRes.pObject.RawPtr<const BufferViewD3D12Impl>(), - SrcRes.pObject.RawPtr<const BufferViewD3D12Impl>(), - DynamicRootBuffersCounter, - Attr.GetD3D12RootParamType()); - } - - DstRes.pObject = SrcRes.pObject; - DstRes.Type = SrcRes.Type; - DstRes.CPUDescriptorHandle = SrcRes.CPUDescriptorHandle; + DstResourceCache.CopyResource(DstRootIndex, DstCacheOffset, SrcRes); if (!Attr.IsRootView()) { @@ -607,20 +506,22 @@ void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderReso } } -void PipelineResourceSignatureD3D12Impl::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, - CommandContext& CmdCtx, - DeviceContextD3D12Impl* pDeviceCtx, - Uint32 DeviceCtxId, - Uint32 BaseRootIndex, - bool IsCompute, - bool CommitDynamicBuffers) const +void PipelineResourceSignatureD3D12Impl::CommitRootViews(const ShaderResourceCacheD3D12& ResourceCache, + CommandContext& CmdCtx, + DeviceContextD3D12Impl* pDeviceCtx, + Uint32 DeviceCtxId, + Uint32 BaseRootIndex, + bool IsCompute, + Uint64 BuffersMask) const { - for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) + while (BuffersMask != 0) { - const auto& RootView = m_RootParams.GetRootView(rv); - const auto RootInd = RootView.RootIndex; + const auto BufferBit = ExtractLSB(BuffersMask); + const auto RootInd = PlatformMisc::GetLSB(BufferBit); + const auto& CacheTbl = ResourceCache.GetRootTable(RootInd); + VERIFY_EXPR(CacheTbl.IsRootView()); - auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0); + const auto& Res = CacheTbl.GetResource(0); if (Res.IsNull()) { LOG_ERROR_MESSAGE("Failed to bind root view at index ", BaseRootIndex + RootInd, ": no resource is bound in the cache."); @@ -645,18 +546,13 @@ void PipelineResourceSignatureD3D12Impl::CommitRootViews(ShaderResourceCacheD3D1 } VERIFY_EXPR(pBuffer != nullptr); - auto IsDynamic = pBuffer->GetDesc().Usage == USAGE_DYNAMIC; - if (IsDynamic != CommitDynamicBuffers) - continue; - - auto BufferGPUAddress = pBuffer->GetGPUAddress(DeviceCtxId, pDeviceCtx); + const auto BufferGPUAddress = pBuffer->GetGPUAddress(DeviceCtxId, pDeviceCtx); VERIFY_EXPR(BufferGPUAddress != 0); - auto* pd3d12CmdList = CmdCtx.GetCommandList(); + auto* const pd3d12CmdList = CmdCtx.GetCommandList(); switch (Res.Type) { case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: - VERIFY_EXPR(RootView.d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV); if (IsCompute) pd3d12CmdList->SetComputeRootConstantBufferView(BaseRootIndex + RootInd, BufferGPUAddress); else @@ -664,7 +560,6 @@ void PipelineResourceSignatureD3D12Impl::CommitRootViews(ShaderResourceCacheD3D1 break; case SHADER_RESOURCE_TYPE_BUFFER_SRV: - VERIFY_EXPR(RootView.d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV); if (IsCompute) pd3d12CmdList->SetComputeRootShaderResourceView(BaseRootIndex + RootInd, BufferGPUAddress); else @@ -672,7 +567,6 @@ void PipelineResourceSignatureD3D12Impl::CommitRootViews(ShaderResourceCacheD3D1 break; case SHADER_RESOURCE_TYPE_BUFFER_UAV: - VERIFY_EXPR(RootView.d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV); if (IsCompute) pd3d12CmdList->SetComputeRootUnorderedAccessView(BaseRootIndex + RootInd, BufferGPUAddress); else @@ -685,12 +579,12 @@ void PipelineResourceSignatureD3D12Impl::CommitRootViews(ShaderResourceCacheD3D1 } } -void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D12& ResourceCache, - CommandContext& CmdCtx, - DeviceContextD3D12Impl* pDeviceCtx, - Uint32 DeviceCtxId, - bool IsCompute, - Uint32 BaseRootIndex) const +void PipelineResourceSignatureD3D12Impl::CommitRootTables(const ShaderResourceCacheD3D12& ResourceCache, + CommandContext& CmdCtx, + DeviceContextD3D12Impl* pDeviceCtx, + Uint32 DeviceCtxId, + bool IsCompute, + Uint32 BaseRootIndex) const { auto* const pd3d12Device = GetDevice()->GetD3D12Device(); @@ -785,9 +679,11 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D } // Commit non-dynamic root buffer views - constexpr auto CommitDynamicBuffers = false; - CommitRootViews(ResourceCache, CmdCtx, pDeviceCtx, - DeviceCtxId, BaseRootIndex, IsCompute, CommitDynamicBuffers); + if (auto NonDynamicBuffersMask = ResourceCache.GetNonDynamicRootBuffersMask()) + { + CommitRootViews(ResourceCache, CmdCtx, pDeviceCtx, DeviceCtxId, + BaseRootIndex, IsCompute, NonDynamicBuffersMask); + } // Manually destroy DescriptorHeapAllocation objects we created. for (auto* pAllocation : pDynamicDescriptorAllocations) @@ -867,15 +763,18 @@ bool PipelineResourceSignatureD3D12Impl::HasImmutableSamplerArray(SHADER_TYPE Sh return false; } + namespace { struct BindResourceHelper { - ShaderResourceCacheD3D12::Resource& DstRes; + const ShaderResourceCacheD3D12::Resource& DstRes; const PipelineResourceDesc& ResDesc; const PipelineResourceSignatureD3D12Impl::ResourceAttribs& Attribs; + const Uint32 RootIndex; const Uint32 ArrayIndex; + const Uint32 OffsetFromTableStart; D3D12_CPU_DESCRIPTOR_HANDLE DstTableCPUDescriptorHandle; PipelineResourceSignatureD3D12Impl const& Signature; ShaderResourceCacheD3D12& ResourceCache; @@ -921,25 +820,23 @@ void BindResourceHelper::CacheCB(IDeviceObject* pBuffer) const return; } - DstRes.Type = ResDesc.ResourceType; - DstRes.CPUDescriptorHandle = pBuffD3D12->GetCBVHandle(); - VERIFY(DstRes.CPUDescriptorHandle.ptr != 0 || pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC, "No relevant CBV CPU descriptor handle"); + const auto CPUDescriptorHandle = pBuffD3D12->GetCBVHandle(); + VERIFY(CPUDescriptorHandle.ptr != 0 || pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC, "No relevant CBV CPU descriptor handle"); if (DstTableCPUDescriptorHandle.ptr != 0) { VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); - VERIFY_EXPR(DstRes.CPUDescriptorHandle.ptr != 0); + VERIFY_EXPR(CPUDescriptorHandle.ptr != 0); - GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } - UpdateDynamicRootBuffersCounter(DstRes.pObject.RawPtr<const BufferD3D12Impl>(), pBuffD3D12, ResourceCache.GetDynamicRootBuffersCounter(), Attribs.GetD3D12RootParamType()); - - DstRes.pObject = std::move(pBuffD3D12); + ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pBuffD3D12)); } } + void BindResourceHelper::CacheSampler(IDeviceObject* pSampler) const { RefCntAutoPtr<ISamplerD3D12> pSamplerD3D12{pSampler, IID_SamplerD3D12}; @@ -960,15 +857,13 @@ void BindResourceHelper::CacheSampler(IDeviceObject* pSampler) const return; } - DstRes.Type = SHADER_RESOURCE_TYPE_SAMPLER; - - DstRes.CPUDescriptorHandle = pSamplerD3D12->GetCPUDescriptorHandle(); - VERIFY(DstRes.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 sampler descriptor handle"); + const auto CPUDescriptorHandle = pSamplerD3D12->GetCPUDescriptorHandle(); + VERIFY(CPUDescriptorHandle.ptr != 0, "No relevant D3D12 sampler descriptor handle"); if (DstTableCPUDescriptorHandle.ptr != 0) { VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); - GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } else { @@ -976,15 +871,16 @@ void BindResourceHelper::CacheSampler(IDeviceObject* pSampler) const "Samplers must always be allocated in root tables and thus assigned descriptor"); } - DstRes.pObject = std::move(pSamplerD3D12); + ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pSamplerD3D12)); } else { - LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", GetShaderResourcePrintName(ResDesc, ArrayIndex), "'." - "Incorect object type: sampler is expected."); + LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", + GetShaderResourcePrintName(ResDesc, ArrayIndex), "'. Incorect object type: sampler is expected."); } } + void BindResourceHelper::CacheAccelStruct(IDeviceObject* pTLAS) const { RefCntAutoPtr<ITopLevelASD3D12> pTLASD3D12{pTLAS, IID_TopLevelASD3D12}; @@ -997,14 +893,13 @@ void BindResourceHelper::CacheAccelStruct(IDeviceObject* pTLAS) const return; } - DstRes.Type = SHADER_RESOURCE_TYPE_ACCEL_STRUCT; - DstRes.CPUDescriptorHandle = pTLASD3D12->GetCPUDescriptorHandle(); - VERIFY(DstRes.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 resource"); + const auto CPUDescriptorHandle = pTLASD3D12->GetCPUDescriptorHandle(); + VERIFY(CPUDescriptorHandle.ptr != 0, "No relevant D3D12 resource"); if (DstTableCPUDescriptorHandle.ptr != 0) { VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); - GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } else { @@ -1012,10 +907,11 @@ void BindResourceHelper::CacheAccelStruct(IDeviceObject* pTLAS) const "Acceleration structures are always allocated in root tables and thus must have a descriptor"); } - DstRes.pObject = std::move(pTLASD3D12); + ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pTLASD3D12)); } } + template <typename TResourceViewType> struct ResourceViewTraits {}; @@ -1084,23 +980,20 @@ void BindResourceHelper::CacheResourceView(IDeviceObject* pView, return; } - DstRes.Type = ResDesc.ResourceType; - DstRes.CPUDescriptorHandle = pViewD3D12->GetCPUDescriptorHandle(); - VERIFY(DstRes.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 view"); + const auto CPUDescriptorHandle = pViewD3D12->GetCPUDescriptorHandle(); + VERIFY(CPUDescriptorHandle.ptr != 0, "No relevant D3D12 view"); if (DstTableCPUDescriptorHandle.ptr != 0) { VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); - GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } - UpdateDynamicRootBuffersCounter(DstRes.pObject.RawPtr<const TResourceViewType>(), pViewD3D12, ResourceCache.GetDynamicRootBuffersCounter(), Attribs.GetD3D12RootParamType()); - BindSamplerProc(pViewD3D12); - DstRes.pObject = std::move(pViewD3D12); + ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pViewD3D12)); } } @@ -1162,11 +1055,11 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const if (pSampler) { VERIFY_EXPR(ResDesc.ArraySize == SamplerResDesc.ArraySize || SamplerResDesc.ArraySize == 1); - const auto CacheType = ResourceCache.GetContentType(); - const auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? ArrayIndex : 0; - const auto RootIndex = SamplerAttribs.RootIndex(CacheType); - const auto OffsetFromTableStart = SamplerAttribs.OffsetFromTableStart(CacheType) + SamplerArrInd; - auto& SampleDstRes = ResourceCache.GetRootTable(RootIndex).GetResource(OffsetFromTableStart); + const auto CacheType = ResourceCache.GetContentType(); + const auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? ArrayIndex : 0; + const auto SamRootIndex = SamplerAttribs.RootIndex(CacheType); + const auto SamOffsetFromTableStart = SamplerAttribs.OffsetFromTableStart(CacheType) + SamplerArrInd; + auto& SampleDstRes = const_cast<const ShaderResourceCacheD3D12&>(ResourceCache).GetRootTable(SamRootIndex).GetResource(SamOffsetFromTableStart); D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle{}; if (CacheType != ShaderResourceCacheD3D12::CacheContentType::Signature) @@ -1181,7 +1074,9 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const SampleDstRes, SamplerResDesc, SamplerAttribs, + SamRootIndex, SamplerArrInd, + SamOffsetFromTableStart, CPUDescriptorHandle, Signature, ResourceCache}; @@ -1226,7 +1121,7 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const LOG_ERROR_MESSAGE("Shader variable '", ResDesc.Name, "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. ", "Use another shader resource binding instance or label the variable as dynamic if you need to bind another resource."); - DstRes = ShaderResourceCacheD3D12::Resource{}; + ResourceCache.ResetResource(RootIndex, OffsetFromTableStart); if (Attribs.IsCombinedWithSampler()) { auto& SamplerResDesc = Signature.GetResourceDesc(Attribs.SamplerInd); @@ -1235,17 +1130,17 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const if (!SamplerAttribs.IsImmutableSamplerAssigned()) { - const auto CacheType = ResourceCache.GetContentType(); - auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? ArrayIndex : 0; - const auto RootIndex = SamplerAttribs.RootIndex(CacheType); - const auto OffsetFromTableStart = SamplerAttribs.OffsetFromTableStart(CacheType) + SamplerArrInd; - auto& DstSam = ResourceCache.GetRootTable(RootIndex).GetResource(OffsetFromTableStart); + const auto CacheType = ResourceCache.GetContentType(); + auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? ArrayIndex : 0; + const auto SamRootIndex = SamplerAttribs.RootIndex(CacheType); + const auto SamOffsetFromTableStart = SamplerAttribs.OffsetFromTableStart(CacheType) + SamplerArrInd; + const auto& DstSam = const_cast<const ShaderResourceCacheD3D12&>(ResourceCache).GetRootTable(SamRootIndex).GetResource(SamOffsetFromTableStart); if (DstSam.pObject != nullptr && SamplerResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) LOG_ERROR_MESSAGE("Sampler variable '", SamplerResDesc.Name, "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. ", "Use another shader resource binding instance or label the variable as dynamic if you need to bind another sampler."); - DstSam = ShaderResourceCacheD3D12::Resource{}; + ResourceCache.ResetResource(SamRootIndex, SamOffsetFromTableStart); } } } @@ -1268,8 +1163,8 @@ void PipelineResourceSignatureD3D12Impl::BindResource(IDeviceObject* VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize); - auto& RootTable = ResourceCache.GetRootTable(RootIndex); - auto& DstRes = RootTable.GetResource(OffsetFromTableStart); + const auto& RootTable = const_cast<const ShaderResourceCacheD3D12&>(ResourceCache).GetRootTable(RootIndex); + const auto& DstRes = RootTable.GetResource(OffsetFromTableStart); D3D12_CPU_DESCRIPTOR_HANDLE DstTableCPUDescriptorHandle{}; if (CacheType != ShaderResourceCacheD3D12::CacheContentType::Signature && !Attribs.IsRootView()) @@ -1286,7 +1181,9 @@ void PipelineResourceSignatureD3D12Impl::BindResource(IDeviceObject* DstRes, ResDesc, Attribs, + RootIndex, ArrayIndex, + OffsetFromTableStart, DstTableCPUDescriptorHandle, *this, ResourceCache}; @@ -1319,13 +1216,13 @@ bool PipelineResourceSignatureD3D12Impl::IsBound(Uint32 return false; } + #ifdef DILIGENT_DEVELOPMENT bool PipelineResourceSignatureD3D12Impl::DvpValidateCommittedResource(const D3DShaderResourceAttribs& D3DAttribs, Uint32 ResIndex, const ShaderResourceCacheD3D12& ResourceCache, const char* ShaderName, - const char* PSOName, - Uint32& DynamicRootBuffersCounter) const + const char* PSOName) const { const auto& ResDesc = GetResourceDesc(ResIndex); const auto& ResAttribs = GetResourceAttribs(ResIndex); @@ -1392,7 +1289,9 @@ bool PipelineResourceSignatureD3D12Impl::DvpValidateCommittedResource(const D3DS if (const auto* pBuffD3D12 = CachedRes.pObject.RawPtr<BufferD3D12Impl>()) { if (pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC) - ++DynamicRootBuffersCounter; + VERIFY_EXPR((ResourceCache.GetDynamicRootBuffersMask() & (Uint64{1} << RootIndex)) != 0); + else + VERIFY_EXPR((ResourceCache.GetNonDynamicRootBuffersMask() & (Uint64{1} << RootIndex)) != 0); } } break; @@ -1405,8 +1304,11 @@ bool PipelineResourceSignatureD3D12Impl::DvpValidateCommittedResource(const D3DS if (const auto* pBuffViewD3D12 = CachedRes.pObject.RawPtr<BufferViewD3D12Impl>()) { const auto* pBuffD3D12 = pBuffViewD3D12->GetBuffer<BufferD3D12Impl>(); + VERIFY_EXPR(pBuffD3D12 != nullptr); if (pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC) - ++DynamicRootBuffersCounter; + VERIFY_EXPR((ResourceCache.GetDynamicRootBuffersMask() & (Uint64{1} << RootIndex)) != 0); + else + VERIFY_EXPR((ResourceCache.GetNonDynamicRootBuffersMask() & (Uint64{1} << RootIndex)) != 0); } } break; diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 3bdc64c7..2bbfb956 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -821,8 +821,6 @@ void PipelineStateD3D12Impl::DvpVerifySRBResources(ShaderResourceBindingD3D12Imp } } - std::array<Uint32, MAX_RESOURCE_SIGNATURES> DynamicRootBuffersCounters{}; - auto attrib_it = m_ResourceAttibutions.begin(); for (const auto& pResources : m_ShaderResources) { @@ -839,26 +837,13 @@ void PipelineStateD3D12Impl::DvpVerifySRBResources(ShaderResourceBindingD3D12Imp } const auto& SRBCache = pSRBs[attrib_it->SignatureIndex]->GetResourceCache(); - attrib_it->pSignature->DvpValidateCommittedResource(Attribs, attrib_it->ResourceIndex, SRBCache, pResources->GetShaderName(), - m_Desc.Name, DynamicRootBuffersCounters[attrib_it->SignatureIndex]); + attrib_it->pSignature->DvpValidateCommittedResource(Attribs, attrib_it->ResourceIndex, SRBCache, pResources->GetShaderName(), m_Desc.Name); } ++attrib_it; } // ); } VERIFY_EXPR(attrib_it == m_ResourceAttibutions.end()); - -# ifdef DILIGENT_DEBUG - for (Uint32 sign = 0; sign < SignCount; ++sign) - { - auto* const pSRB = pSRBs[sign]; - if (pSRB == nullptr) - continue; - - const auto& SRBCache = pSRB->GetResourceCache(); - VERIFY(SRBCache.GetNumDynamicRootBuffers() == DynamicRootBuffersCounters[sign], "Incorrect root buffers counter"); - } -# endif } #endif diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp index 02c0d052..82b3aa30 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp @@ -123,6 +123,8 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, Uint32 NumTables, const Uint32 TableSizes[]) { + DEV_CHECK_ERR(NumTables < MaxRootTables, "The number of root tables (", NumTables, ") exceeds maximum allowed value (", MaxRootTables, ")."); + m_NumTables = static_cast<decltype(m_NumTables)>(NumTables); VERIFY_EXPR(m_NumTables == NumTables); @@ -137,7 +139,7 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, Uint32 ResIdx = 0; for (Uint32 t = 0; t < m_NumTables; ++t) { - new (&GetRootTable(t)) RootTable{TableSizes[t], TableSizes[t] > 0 ? &GetResource(ResIdx) : nullptr}; + new (&GetRootTable(t)) RootTable{TableSizes[t], TableSizes[t] > 0 ? &GetResource(ResIdx) : nullptr, false}; ResIdx += TableSizes[t]; } } @@ -149,6 +151,8 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, { const auto MemReq = GetMemoryRequirements(RootParams); + DEV_CHECK_ERR(MemReq.NumTables < MaxRootTables, "The number of root tables (", MemReq.NumTables, ") exceeds maximum allowed value (", MaxRootTables, ")."); + m_NumTables = static_cast<decltype(m_NumTables)>(MemReq.NumTables); VERIFY_EXPR(m_NumTables == MemReq.NumTables); @@ -179,6 +183,7 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, new (&GetRootTable(RootTbl.RootIndex)) RootTable{ TableSize, &GetResource(ResIdx), + false, // IsRootView RootTbl.TableOffsetInGroupAllocation}; ResIdx += TableSize; @@ -199,7 +204,9 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, new (&GetRootTable(RootView.RootIndex)) RootTable{ 1, - &GetResource(ResIdx)}; + &GetResource(ResIdx), + true //IsRootView + }; ++ResIdx; #ifdef DILIGENT_DEBUG @@ -277,6 +284,140 @@ ShaderResourceCacheD3D12::~ShaderResourceCacheD3D12() } + +const ShaderResourceCacheD3D12::Resource& ShaderResourceCacheD3D12::SetResource(Uint32 RootIndex, + Uint32 OffsetFromTableStart, + SHADER_RESOURCE_TYPE Type, + D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle, + RefCntAutoPtr<IDeviceObject>&& pObject) +{ + auto& Tbl = GetRootTable(RootIndex); + if (Tbl.IsRootView()) + { + const BufferD3D12Impl* pBuffer = nullptr; + if (pObject) + { + switch (Type) + { + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: + pBuffer = pObject.RawPtr<const BufferD3D12Impl>(); + break; + + case SHADER_RESOURCE_TYPE_BUFFER_SRV: + case SHADER_RESOURCE_TYPE_BUFFER_UAV: + pBuffer = pObject.RawPtr<BufferViewD3D12Impl>()->GetBuffer<const BufferD3D12Impl>(); + break; + + default: + UNEXPECTED("Only constant bufers and buffer SRVs/UAVs can be bound as root views."); + break; + } + } + + const Uint64 BufferBit = Uint64{1} << Uint64{RootIndex}; + m_DynamicRootBuffersMask &= ~BufferBit; + m_NonDynamicRootBuffersMask &= ~BufferBit; + if (pBuffer != nullptr) + { + const auto IsDynamic = pBuffer->GetDesc().Usage == USAGE_DYNAMIC; + (IsDynamic ? m_DynamicRootBuffersMask : m_NonDynamicRootBuffersMask) |= BufferBit; + } + } + else + { +#ifdef DILIGENT_DEVELOPMENT + if (GetContentType() == CacheContentType::SRB) + { + const BufferD3D12Impl* pBuffer = nullptr; + switch (Type) + { + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: + pBuffer = pObject.RawPtr<const BufferD3D12Impl>(); + break; + + case SHADER_RESOURCE_TYPE_BUFFER_SRV: + case SHADER_RESOURCE_TYPE_BUFFER_UAV: + pBuffer = pObject.RawPtr<BufferViewD3D12Impl>()->GetBuffer<const BufferD3D12Impl>(); + break; + + default: + // Do nothing; + break; + } + if (pBuffer != nullptr && pBuffer->GetDesc().Usage == USAGE_DYNAMIC) + { + DEV_CHECK_ERR(pBuffer->GetD3D12Resource() != nullptr, "Dynamic buffers that don't have backing d3d12 resource must be bound as root views"); + } + } +#endif + } + + auto& Res = Tbl.GetResource(OffsetFromTableStart); + + Res.Type = Type; + Res.pObject = std::move(pObject); + Res.CPUDescriptorHandle = CPUDescriptorHandle; + + return Res; +} + +#ifdef DILIGENT_DEBUG +void ShaderResourceCacheD3D12::DbgValidateDynamicBuffersMask() const +{ + VERIFY_EXPR((m_DynamicRootBuffersMask & m_NonDynamicRootBuffersMask) == 0); + for (Uint32 i = 0; i < GetNumRootTables(); ++i) + { + const auto& Tbl = GetRootTable(i); + const Uint64 DynamicBufferBit = Uint64{1} << Uint64{i}; + if (Tbl.IsRootView()) + { + VERIFY_EXPR(Tbl.GetSize() == 1); + const auto& Res = Tbl.GetResource(0); + + const BufferD3D12Impl* pBuffer = nullptr; + if (Res.pObject) + { + switch (Res.Type) + { + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: + pBuffer = Res.pObject.RawPtr<const BufferD3D12Impl>(); + break; + + case SHADER_RESOURCE_TYPE_BUFFER_SRV: + case SHADER_RESOURCE_TYPE_BUFFER_UAV: + pBuffer = Res.pObject.RawPtr<BufferViewD3D12Impl>()->GetBuffer<const BufferD3D12Impl>(); + break; + + default: + UNEXPECTED("Only constant bufers and buffer SRVs/UAVs can be bound as root views."); + break; + } + } + + if (pBuffer != nullptr) + { + const bool IsDynamicBuffer = pBuffer->GetDesc().Usage == USAGE_DYNAMIC; + VERIFY(((m_DynamicRootBuffersMask & DynamicBufferBit) != 0) == IsDynamicBuffer, + "Incorrect dynamic buffer bit set in the mask"); + VERIFY(((m_NonDynamicRootBuffersMask & DynamicBufferBit) != 0) == !IsDynamicBuffer, + "Incorrect dynamic buffer bit set in the mask"); + } + else + { + VERIFY((m_DynamicRootBuffersMask & DynamicBufferBit) == 0, "Bit must not be set when there are no buffer."); + VERIFY((m_NonDynamicRootBuffersMask & DynamicBufferBit) == 0, "Bit must not be set when there are no buffer."); + } + } + else + { + VERIFY((m_DynamicRootBuffersMask & DynamicBufferBit) == 0, "Dynamic buffer mask bit may only be set for root views"); + VERIFY((m_NonDynamicRootBuffersMask & DynamicBufferBit) == 0, "Non-dynamic buffer mask bit may only be set for root views"); + } + } +} +#endif + + void ShaderResourceCacheD3D12::Resource::TransitionResource(CommandContext& Ctx) { static_assert(SHADER_RESOURCE_TYPE_LAST == 8, "Please update this function to handle the new resource type"); |
