diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-02-20 05:46:52 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:38:09 +0000 |
| commit | ac28bcb6cd1f23cd4223bd16ed3564b3488f5e2b (patch) | |
| tree | 5cbe903ea5f5379a9ff2a585362356d73f4fa91e /Graphics/GraphicsEngineD3D12 | |
| parent | PipelineResourceSignatureD3D12Impl and PipelineResourceSignatureVkImpl: remov... (diff) | |
| download | DiligentCore-ac28bcb6cd1f23cd4223bd16ed3564b3488f5e2b.tar.gz DiligentCore-ac28bcb6cd1f23cd4223bd16ed3564b3488f5e2b.zip | |
D3D12 backend: moved resource state transition logic from PipelineResourceSignatureD3D12Impl to ShaderResourceCacheD3D12
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
5 files changed, 301 insertions, 307 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp index 11c9f123..29cff8e9 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp @@ -133,6 +133,13 @@ public: Uint32 OffsetFromTableStart(CacheContentType Type) const { return Type == CacheContentType::SRB ? SRBOffsetFromTableStart : SigOffsetFromTableStart; } D3D12_ROOT_PARAMETER_TYPE GetD3D12RootParamType() const { return static_cast<D3D12_ROOT_PARAMETER_TYPE>(RootParamType); } + + bool IsRootView() const + { + return (GetD3D12RootParamType() == D3D12_ROOT_PARAMETER_TYPE_CBV || + GetD3D12RootParamType() == D3D12_ROOT_PARAMETER_TYPE_SRV || + GetD3D12RootParamType() == D3D12_ROOT_PARAMETER_TYPE_UAV); + } }; const ResourceAttribs& GetResourceAttribs(Uint32 ResIndex) const @@ -260,11 +267,6 @@ public: Uint32 ResIndex, ShaderResourceCacheD3D12& ResourceCache) const; - void TransitionResources(ShaderResourceCacheD3D12& ResourceCache, - CommandContext& Ctx, - bool PerformResourceTransitions, - bool ValidateStates) const; - void CommitRootTables(ShaderResourceCacheD3D12& ResourceCache, CommandContext& Ctx, DeviceContextD3D12Impl* pDeviceCtx, diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp index ecee02b6..2daa4183 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp @@ -88,10 +88,12 @@ namespace Diligent { +class CommandContext; + class ShaderResourceCacheD3D12 { public: - enum class CacheContentType + enum class CacheContentType : Uint8 { Signature = 0, // The cache is used by the pipeline resource signature to hold static resources. SRB = 1 // The cache is used by SRB to hold resources of all types (static, mutable, dynamic). @@ -99,9 +101,8 @@ public: explicit ShaderResourceCacheD3D12(CacheContentType ContentType) noexcept : m_NumTables{0}, - m_ContentType{static_cast<Uint32>(ContentType)} + m_ContentType{ContentType} { - VERIFY_EXPR(GetContentType() == ContentType); } // clang-format off @@ -113,12 +114,12 @@ public: ~ShaderResourceCacheD3D12(); - static size_t GetRequiredMemorySize(Uint32 NumTables, - Uint32 TableSizes[]); + static size_t GetRequiredMemorySize(Uint32 NumTables, + const Uint32 TableSizes[]); void Initialize(IMemoryAllocator& MemAllocator, Uint32 NumTables, - Uint32 TableSizes[]); + const Uint32 TableSizes[]); static constexpr Uint32 InvalidDescriptorOffset = ~0u; @@ -131,6 +132,11 @@ public: // Note that for dynamic resources, this is the only available CPU descriptor handle. D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0}; RefCntAutoPtr<IDeviceObject> pObject; + + __forceinline void TransitionResource(CommandContext& Ctx); +#ifdef DILIGENT_DEVELOPMENT + void DvpVerifyResourceState(); +#endif }; class RootTable @@ -316,18 +322,48 @@ public: return DstDescrHandle; } + template <class TOperation> + __forceinline void ProcessTableResources(Uint32 RootInd, + const D3D12_ROOT_PARAMETER& d3d12Param, + D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType, + TOperation Operation) + { + auto& TableResources = GetRootTable(RootInd); + for (UINT r = 0; r < d3d12Param.DescriptorTable.NumDescriptorRanges; ++r) + { + const auto& range = d3d12Param.DescriptorTable.pDescriptorRanges[r]; + VERIFY(dbgHeapType == D3D12DescriptorRangeTypeToD3D12HeapType(range.RangeType), "Mistmatch between descriptor heap type and descriptor range type"); + for (UINT d = 0; d < range.NumDescriptors; ++d) + { + const auto Offset = range.OffsetInDescriptorsFromTableStart + d; + auto& Res = TableResources.GetResource(Offset, dbgHeapType); + Operation(Offset, range, Res); + } + } + } + + void TransitionResources(CommandContext& Ctx, + bool PerformTransitions, + bool ValidateStates); + Uint32& GetDynamicRootBuffersCounter() { return m_NumDynamicRootBuffers; } // Returns the number of dynamic buffers bound as root views in the cache regardless of their variable types Uint32 GetNumDynamicRootBuffers() const { return m_NumDynamicRootBuffers; } - CacheContentType GetContentType() const { return static_cast<CacheContentType>(m_ContentType); } + CacheContentType GetContentType() const { return m_ContentType; } #ifdef DILIGENT_DEBUG //void DbgVerifyBoundDynamicCBsCounter() const; #endif private: + Resource& GetResource(Uint32 Idx) + { + VERIFY_EXPR(Idx < m_TotalResourceCount); + return reinterpret_cast<Resource*>(reinterpret_cast<RootTable*>(m_pMemory) + m_NumTables)[Idx]; + } + // Allocation in a GPU-visible sampler descriptor heap DescriptorHeapAllocation m_SamplerHeapSpace; @@ -341,9 +377,13 @@ private: Uint32 m_NumDynamicRootBuffers = 0; // The number of descriptor tables in the cache - Uint32 m_NumTables : 31; + Uint32 m_NumTables = 0; + + // The total number of resources in the cache + Uint32 m_TotalResourceCount = 0; + // Indicates what types of resources are stored in the cache - const Uint32 m_ContentType : 1; + const CacheContentType m_ContentType; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 2722a80e..d5af4ce0 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -349,7 +349,7 @@ void DeviceContextD3D12Impl::TransitionShaderResources(IPipelineState* pPipeline auto* pResBindingD3D12Impl = ValidatedCast<ShaderResourceBindingD3D12Impl>(pShaderResourceBinding); auto& ResourceCache = pResBindingD3D12Impl->GetResourceCache(); - pResBindingD3D12Impl->GetSignature()->TransitionResources(ResourceCache, CmdCtx, true, false); + ResourceCache.TransitionResources(CmdCtx, true, false); } void DeviceContextD3D12Impl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) @@ -368,12 +368,12 @@ void DeviceContextD3D12Impl::CommitShaderResources(IShaderResourceBinding* pShad if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { - pSignature->TransitionResources(ResourceCache, CmdCtx, true, false); + ResourceCache.TransitionResources(CmdCtx, true, false); } #ifdef DILIGENT_DEVELOPMENT else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY) { - pSignature->TransitionResources(ResourceCache, CmdCtx, false, true); + ResourceCache.TransitionResources(CmdCtx, false, true); } #endif diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp index bba1d296..6d38ceaf 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp @@ -451,13 +451,17 @@ std::vector<Uint32, STDAllocatorRawMem<Uint32>> PipelineResourceSignatureD3D12Im std::vector<Uint32, STDAllocatorRawMem<Uint32>> CacheTableSizes(m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews(), 0, STD_ALLOCATOR_RAW_MEM(Uint32, GetRawAllocator(), "Allocator for vector<Uint32>")); for (Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt) { - const auto& RootParam = m_RootParams.GetRootTable(rt); + const auto& RootParam = m_RootParams.GetRootTable(rt); + VERIFY(CacheTableSizes[RootParam.RootIndex] == 0, "Cache table at index ", RootParam.RootIndex, + " has already been initialized. This is a bug as each root index must be used only once."); CacheTableSizes[RootParam.RootIndex] = RootParam.GetDescriptorTableSize(); } for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) { - const auto& RootParam = m_RootParams.GetRootView(rv); + const auto& RootParam = m_RootParams.GetRootView(rv); + VERIFY(CacheTableSizes[RootParam.RootIndex] == 0, "Cache table at index ", RootParam.RootIndex, + " has already been initialized. This is a bug as each root index must be used only once."); CacheTableSizes[RootParam.RootIndex] = 1; } @@ -468,7 +472,7 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach IMemoryAllocator& CacheMemAllocator, const char* DbgPipelineName) const { - auto CacheTableSizes = GetCacheTableSizes(); + const auto CacheTableSizes = GetCacheTableSizes(); // Initialize resource cache to hold root tables ResourceCache.Initialize(CacheMemAllocator, static_cast<Uint32>(CacheTableSizes.size()), CacheTableSizes.data()); @@ -478,7 +482,7 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach Uint32 TotalSamplerDescriptors = m_RootParams.GetTotalSamplerSlots(ROOT_PARAMETER_GROUP_STATIC_MUTABLE); DescriptorHeapAllocation CbcSrvUavHeapSpace, SamplerHeapSpace; - if (TotalSrvCbvUavDescriptors) + if (TotalSrvCbvUavDescriptors > 0) { CbcSrvUavHeapSpace = GetDevice()->AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, TotalSrvCbvUavDescriptors); DEV_CHECK_ERR(!CbcSrvUavHeapSpace.IsNull(), @@ -488,7 +492,7 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach } VERIFY_EXPR(TotalSrvCbvUavDescriptors == 0 && CbcSrvUavHeapSpace.IsNull() || CbcSrvUavHeapSpace.GetNumHandles() == TotalSrvCbvUavDescriptors); - if (TotalSamplerDescriptors) + if (TotalSamplerDescriptors > 0) { SamplerHeapSpace = GetDevice()->AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, TotalSamplerDescriptors); DEV_CHECK_ERR(!SamplerHeapSpace.IsNull(), @@ -523,7 +527,6 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach RootTableCache.SetDebugAttribs(TableSize, HeapType, IsDynamic); #endif - // Space for dynamic variables is allocated at every draw call if (!IsDynamic) { if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) @@ -539,9 +542,12 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach } else { + // Space for dynamic variables is allocated at every commit VERIFY_EXPR(RootTableCache.m_TableStartOffset == ShaderResourceCacheD3D12::InvalidDescriptorOffset); } } + VERIFY_EXPR(SrvCbvUavTblStartOffset == TotalSrvCbvUavDescriptors); + VERIFY_EXPR(SamplerTblStartOffset == TotalSamplerDescriptors); #ifdef DILIGENT_DEBUG for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) @@ -561,9 +567,6 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach } #endif - VERIFY_EXPR(SrvCbvUavTblStartOffset == TotalSrvCbvUavDescriptors); - VERIFY_EXPR(SamplerTblStartOffset == TotalSamplerDescriptors); - ResourceCache.SetDescriptorHeapSpace(std::move(CbcSrvUavHeapSpace), std::move(SamplerHeapSpace)); } @@ -663,7 +666,7 @@ void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderReso auto& DstRes = DstRootTable.GetResource(DstCacheOffset, HeapType); if (DstRes.pObject != SrcRes.pObject) { - DEV_CHECK_ERR(DstRes.pObject == nullptr, "Static resource has already been initialized, and the resource to be assigned from the shader does not match previously assigned resource"); + 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) { @@ -692,7 +695,7 @@ void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderReso else { auto DstHandle = DstResourceCache.CopyDescriptors<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(d3d12Device, SrcRes.CPUDescriptorHandle, 1, DstRootIndex, DstCacheOffset); - VERIFY_EXPR(DstHandle.ptr != 0 || (DstRes.Type == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER || DstRes.Type == SHADER_RESOURCE_TYPE_BUFFER_SRV || DstRes.Type == SHADER_RESOURCE_TYPE_BUFFER_UAV)); + VERIFY_EXPR(DstHandle.ptr != 0 || Attr.IsRootView()); } } else @@ -705,268 +708,6 @@ void PipelineResourceSignatureD3D12Impl::InitializeStaticSRBResources(ShaderReso } } - -namespace -{ - -template <class TOperation> -__forceinline void ProcessCachedTableResources(Uint32 RootInd, - const D3D12_ROOT_PARAMETER& d3d12Param, - ShaderResourceCacheD3D12& ResourceCache, - D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType, - TOperation Operation) -{ - auto& TableResources = ResourceCache.GetRootTable(RootInd); - for (UINT r = 0; r < d3d12Param.DescriptorTable.NumDescriptorRanges; ++r) - { - const auto& range = d3d12Param.DescriptorTable.pDescriptorRanges[r]; - VERIFY(dbgHeapType == D3D12DescriptorRangeTypeToD3D12HeapType(range.RangeType), "Mistmatch between descriptor heap type and descriptor range type"); - for (UINT d = 0; d < range.NumDescriptors; ++d) - { - const auto Offset = range.OffsetInDescriptorsFromTableStart + d; - auto& Res = TableResources.GetResource(Offset, dbgHeapType); - Operation(Offset, range, Res); - } - } -} - -__forceinline void TransitionResource(CommandContext& Ctx, - ShaderResourceCacheD3D12::Resource& Res, - D3D12_DESCRIPTOR_RANGE_TYPE RangeType) -{ - static_assert(SHADER_RESOURCE_TYPE_LAST == SHADER_RESOURCE_TYPE_ACCEL_STRUCT, "Please update this function to handle the new resource type"); - switch (Res.Type) - { - case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV, "Unexpected descriptor range type"); - // Not using QueryInterface() for the sake of efficiency - auto* pBuffToTransition = Res.pObject.RawPtr<BufferD3D12Impl>(); - if (pBuffToTransition->IsInKnownState() && !pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) - Ctx.TransitionResource(*pBuffToTransition, RESOURCE_STATE_CONSTANT_BUFFER); - } - break; - - case SHADER_RESOURCE_TYPE_BUFFER_SRV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - auto* pBuffViewD3D12 = Res.pObject.RawPtr<BufferViewD3D12Impl>(); - auto* pBuffToTransition = pBuffViewD3D12->GetBuffer<BufferD3D12Impl>(); - if (pBuffToTransition->IsInKnownState() && !pBuffToTransition->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) - Ctx.TransitionResource(*pBuffToTransition, RESOURCE_STATE_SHADER_RESOURCE); - } - break; - - case SHADER_RESOURCE_TYPE_BUFFER_UAV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - auto* pBuffViewD3D12 = Res.pObject.RawPtr<BufferViewD3D12Impl>(); - auto* pBuffToTransition = pBuffViewD3D12->GetBuffer<BufferD3D12Impl>(); - if (pBuffToTransition->IsInKnownState()) - { - // We must always call TransitionResource() even when the state is already - // RESOURCE_STATE_UNORDERED_ACCESS as in this case UAV barrier must be executed - Ctx.TransitionResource(*pBuffToTransition, RESOURCE_STATE_UNORDERED_ACCESS); - } - } - break; - - case SHADER_RESOURCE_TYPE_TEXTURE_SRV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - auto* pTexViewD3D12 = Res.pObject.RawPtr<TextureViewD3D12Impl>(); - auto* pTexToTransition = pTexViewD3D12->GetTexture<TextureD3D12Impl>(); - if (pTexToTransition->IsInKnownState() && !pTexToTransition->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) - Ctx.TransitionResource(*pTexToTransition, RESOURCE_STATE_SHADER_RESOURCE); - } - break; - - case SHADER_RESOURCE_TYPE_TEXTURE_UAV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - auto* pTexViewD3D12 = Res.pObject.RawPtr<TextureViewD3D12Impl>(); - auto* pTexToTransition = pTexViewD3D12->GetTexture<TextureD3D12Impl>(); - if (pTexToTransition->IsInKnownState()) - { - // We must always call TransitionResource() even when the state is already - // RESOURCE_STATE_UNORDERED_ACCESS as in this case UAV barrier must be executed - Ctx.TransitionResource(*pTexToTransition, RESOURCE_STATE_UNORDERED_ACCESS); - } - } - break; - - case SHADER_RESOURCE_TYPE_SAMPLER: - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type"); - break; - - case SHADER_RESOURCE_TYPE_ACCEL_STRUCT: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - auto* pTlasD3D12 = Res.pObject.RawPtr<TopLevelASD3D12Impl>(); - if (pTlasD3D12->IsInKnownState()) - Ctx.TransitionResource(*pTlasD3D12, RESOURCE_STATE_RAY_TRACING); - } - break; - - default: - // Resource not bound - VERIFY(Res.Type == SHADER_RESOURCE_TYPE_UNKNOWN, "Unexpected resource type"); - VERIFY(Res.pObject == nullptr && Res.CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected"); - } -} - - -#ifdef DILIGENT_DEVELOPMENT -void DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resource& Res, D3D12_DESCRIPTOR_RANGE_TYPE RangeType) -{ - static_assert(SHADER_RESOURCE_TYPE_LAST == SHADER_RESOURCE_TYPE_ACCEL_STRUCT, "Please update this function to handle the new resource type"); - switch (Res.Type) - { - case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV, "Unexpected descriptor range type"); - // Not using QueryInterface() for the sake of efficiency - const auto* pBufferD3D12 = Res.pObject.RawPtr<const BufferD3D12Impl>(); - if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) - { - LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_CONSTANT_BUFFER state. Actual state: ", - GetResourceStateString(pBufferD3D12->GetState()), - ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " - "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state " - "with IDeviceContext::TransitionResourceStates()."); - } - } - break; - - case SHADER_RESOURCE_TYPE_BUFFER_SRV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - const auto* pBuffViewD3D12 = Res.pObject.RawPtr<const BufferViewD3D12Impl>(); - const auto* pBufferD3D12 = pBuffViewD3D12->GetBuffer<const BufferD3D12Impl>(); - if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) - { - LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_SHADER_RESOURCE state. Actual state: ", - GetResourceStateString(pBufferD3D12->GetState()), - ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " - "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state " - "with IDeviceContext::TransitionResourceStates()."); - } - } - break; - - case SHADER_RESOURCE_TYPE_BUFFER_UAV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - const auto* pBuffViewD3D12 = Res.pObject.RawPtr<const BufferViewD3D12Impl>(); - const auto* pBufferD3D12 = pBuffViewD3D12->GetBuffer<const BufferD3D12Impl>(); - if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_UNORDERED_ACCESS state. Actual state: ", - GetResourceStateString(pBufferD3D12->GetState()), - ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " - "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state " - "with IDeviceContext::TransitionResourceStates()."); - } - } - break; - - case SHADER_RESOURCE_TYPE_TEXTURE_SRV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - const auto* pTexViewD3D12 = Res.pObject.RawPtr<const TextureViewD3D12Impl>(); - const auto* pTexD3D12 = pTexViewD3D12->GetTexture<TextureD3D12Impl>(); - if (pTexD3D12->IsInKnownState() && !pTexD3D12->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) - { - LOG_ERROR_MESSAGE("Texture '", pTexD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_SHADER_RESOURCE state. Actual state: ", - GetResourceStateString(pTexD3D12->GetState()), - ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " - "when calling IDeviceContext::CommitShaderResources() or explicitly transition the texture state " - "with IDeviceContext::TransitionResourceStates()."); - } - } - break; - - case SHADER_RESOURCE_TYPE_TEXTURE_UAV: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type"); - const auto* pTexViewD3D12 = Res.pObject.RawPtr<const TextureViewD3D12Impl>(); - const auto* pTexD3D12 = pTexViewD3D12->GetTexture<const TextureD3D12Impl>(); - if (pTexD3D12->IsInKnownState() && !pTexD3D12->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - LOG_ERROR_MESSAGE("Texture '", pTexD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_UNORDERED_ACCESS state. Actual state: ", - GetResourceStateString(pTexD3D12->GetState()), - ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " - "when calling IDeviceContext::CommitShaderResources() or explicitly transition the texture state " - "with IDeviceContext::TransitionResourceStates()."); - } - } - break; - - case SHADER_RESOURCE_TYPE_SAMPLER: - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type"); - break; - - case SHADER_RESOURCE_TYPE_ACCEL_STRUCT: - { - VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); - const auto* pTLASD3D12 = Res.pObject.RawPtr<const TopLevelASD3D12Impl>(); - if (pTLASD3D12->IsInKnownState() && !pTLASD3D12->CheckState(RESOURCE_STATE_RAY_TRACING)) - { - LOG_ERROR_MESSAGE("TLAS '", pTLASD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_RAY_TRACING state. Actual state: ", - GetResourceStateString(pTLASD3D12->GetState()), - ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " - "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state " - "with IDeviceContext::TransitionResourceStates()."); - } - } - break; - - default: - // Resource not bound - VERIFY(Res.Type == SHADER_RESOURCE_TYPE_UNKNOWN, "Unexpected resource type"); - VERIFY(Res.pObject == nullptr && Res.CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected"); - } -} -#endif // DILIGENT_DEVELOPMENT - -} // namespace - -void PipelineResourceSignatureD3D12Impl::TransitionResources(ShaderResourceCacheD3D12& ResourceCache, - CommandContext& Ctx, - bool PerformResourceTransitions, - bool ValidateStates) const -{ - m_RootParams.ProcessRootTables( - [&](Uint32 RootInd, - const RootParameter& RootTable, - const D3D12_ROOT_PARAMETER& D3D12Param, - bool IsResourceTable, - D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType) // - { - ProcessCachedTableResources( - RootInd, D3D12Param, ResourceCache, dbgHeapType, - [&](UINT OffsetFromTableStart, - const D3D12_DESCRIPTOR_RANGE& range, - ShaderResourceCacheD3D12::Resource& Res) // - { - // AZ TODO: optimize - if (PerformResourceTransitions) - { - TransitionResource(Ctx, Res, range.RangeType); - } -#ifdef DILIGENT_DEVELOPMENT - else if (ValidateStates) - { - DvpVerifyResourceState(Res, range.RangeType); - } -#endif - } // - ); - } // - ); -} - - void PipelineResourceSignatureD3D12Impl::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, CommandContext& CmdCtx, DeviceContextD3D12Impl* pDeviceCtx, @@ -1104,8 +845,8 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D if (IsDynamicTable) { - ProcessCachedTableResources( - RootInd, d3d12Param, ResourceCache, dbgHeapType, + ResourceCache.ProcessTableResources( + RootInd, d3d12Param, dbgHeapType, [&](UINT OffsetFromTableStart, const D3D12_DESCRIPTOR_RANGE& range, ShaderResourceCacheD3D12::Resource& Res) // diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp index ccb1207b..aa3820bb 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp @@ -29,12 +29,18 @@ #include "ShaderResourceCacheD3D12.hpp" #include "BufferD3D12Impl.hpp" +#include "CommandContext.hpp" +#include "BufferD3D12Impl.hpp" +#include "BufferViewD3D12Impl.hpp" +#include "TextureD3D12Impl.hpp" +#include "TextureViewD3D12Impl.hpp" +#include "TopLevelASD3D12Impl.hpp" namespace Diligent { -size_t ShaderResourceCacheD3D12::GetRequiredMemorySize(Uint32 NumTables, - Uint32 TableSizes[]) +size_t ShaderResourceCacheD3D12::GetRequiredMemorySize(Uint32 NumTables, + const Uint32 TableSizes[]) { size_t MemorySize = NumTables * sizeof(RootTable); for (Uint32 t = 0; t < NumTables; ++t) @@ -43,7 +49,7 @@ size_t ShaderResourceCacheD3D12::GetRequiredMemorySize(Uint32 NumTables, } // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Cache-Structure -void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, Uint32 NumTables, Uint32 TableSizes[]) +void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, Uint32 NumTables, const Uint32 TableSizes[]) { // Memory layout: // __________________________________________________________ @@ -58,19 +64,20 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, Uint32 // VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized"); - m_pAllocator = &MemAllocator; - m_NumTables = NumTables; - Uint32 TotalResources = 0; + m_pAllocator = &MemAllocator; + m_NumTables = NumTables; + + m_TotalResourceCount = 0; for (Uint32 t = 0; t < NumTables; ++t) - TotalResources += TableSizes[t]; - auto MemorySize = NumTables * sizeof(RootTable) + TotalResources * sizeof(Resource); + m_TotalResourceCount += TableSizes[t]; + const auto MemorySize = NumTables * sizeof(RootTable) + m_TotalResourceCount * sizeof(Resource); VERIFY_EXPR(MemorySize == GetRequiredMemorySize(NumTables, TableSizes)); if (MemorySize > 0) { m_pMemory = ALLOCATE_RAW(*m_pAllocator, "Memory for shader resource cache data", MemorySize); auto* pTables = reinterpret_cast<RootTable*>(m_pMemory); auto* pCurrResPtr = reinterpret_cast<Resource*>(pTables + m_NumTables); - for (Uint32 res = 0; res < TotalResources; ++res) + for (Uint32 res = 0; res < m_TotalResourceCount; ++res) new (pCurrResPtr + res) Resource{}; for (Uint32 t = 0; t < NumTables; ++t) @@ -86,12 +93,8 @@ ShaderResourceCacheD3D12::~ShaderResourceCacheD3D12() { if (m_pMemory) { - Uint32 TotalResources = 0; - for (Uint32 t = 0; t < m_NumTables; ++t) - TotalResources += GetRootTable(t).GetSize(); - auto* pResources = reinterpret_cast<Resource*>(reinterpret_cast<RootTable*>(m_pMemory) + m_NumTables); - for (Uint32 res = 0; res < TotalResources; ++res) - pResources[res].~Resource(); + for (Uint32 res = 0; res < m_TotalResourceCount; ++res) + GetResource(res).~Resource(); for (Uint32 t = 0; t < m_NumTables; ++t) GetRootTable(t).~RootTable(); @@ -99,6 +102,214 @@ ShaderResourceCacheD3D12::~ShaderResourceCacheD3D12() } } + +void ShaderResourceCacheD3D12::Resource::TransitionResource(CommandContext& Ctx) +{ + static_assert(SHADER_RESOURCE_TYPE_LAST == 8, "Please update this function to handle the new resource type"); + switch (Type) + { + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: + { + // No need to use QueryInterface() - types are verified when resources are bound + auto* pBuffToTransition = pObject.RawPtr<BufferD3D12Impl>(); + if (pBuffToTransition->IsInKnownState() && !pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) + Ctx.TransitionResource(*pBuffToTransition, RESOURCE_STATE_CONSTANT_BUFFER); + } + break; + + case SHADER_RESOURCE_TYPE_BUFFER_SRV: + { + auto* pBuffViewD3D12 = pObject.RawPtr<BufferViewD3D12Impl>(); + auto* pBuffToTransition = pBuffViewD3D12->GetBuffer<BufferD3D12Impl>(); + if (pBuffToTransition->IsInKnownState() && !pBuffToTransition->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) + Ctx.TransitionResource(*pBuffToTransition, RESOURCE_STATE_SHADER_RESOURCE); + } + break; + + case SHADER_RESOURCE_TYPE_BUFFER_UAV: + { + auto* pBuffViewD3D12 = pObject.RawPtr<BufferViewD3D12Impl>(); + auto* pBuffToTransition = pBuffViewD3D12->GetBuffer<BufferD3D12Impl>(); + if (pBuffToTransition->IsInKnownState()) + { + // We must always call TransitionResource() even when the state is already + // RESOURCE_STATE_UNORDERED_ACCESS as in this case UAV barrier must be executed + Ctx.TransitionResource(*pBuffToTransition, RESOURCE_STATE_UNORDERED_ACCESS); + } + } + break; + + case SHADER_RESOURCE_TYPE_TEXTURE_SRV: + { + auto* pTexViewD3D12 = pObject.RawPtr<TextureViewD3D12Impl>(); + auto* pTexToTransition = pTexViewD3D12->GetTexture<TextureD3D12Impl>(); + if (pTexToTransition->IsInKnownState() && !pTexToTransition->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) + Ctx.TransitionResource(*pTexToTransition, RESOURCE_STATE_SHADER_RESOURCE); + } + break; + + case SHADER_RESOURCE_TYPE_TEXTURE_UAV: + { + auto* pTexViewD3D12 = pObject.RawPtr<TextureViewD3D12Impl>(); + auto* pTexToTransition = pTexViewD3D12->GetTexture<TextureD3D12Impl>(); + if (pTexToTransition->IsInKnownState()) + { + // We must always call TransitionResource() even when the state is already + // RESOURCE_STATE_UNORDERED_ACCESS as in this case UAV barrier must be executed + Ctx.TransitionResource(*pTexToTransition, RESOURCE_STATE_UNORDERED_ACCESS); + } + } + break; + + case SHADER_RESOURCE_TYPE_SAMPLER: + // Nothing to transition + break; + + case SHADER_RESOURCE_TYPE_ACCEL_STRUCT: + { + auto* pTlasD3D12 = pObject.RawPtr<TopLevelASD3D12Impl>(); + if (pTlasD3D12->IsInKnownState()) + Ctx.TransitionResource(*pTlasD3D12, RESOURCE_STATE_RAY_TRACING); + } + break; + + default: + // Resource is not bound + VERIFY(Type == SHADER_RESOURCE_TYPE_UNKNOWN, "Unexpected resource type"); + VERIFY(pObject == nullptr && CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected"); + } +} + + +#ifdef DILIGENT_DEVELOPMENT +void ShaderResourceCacheD3D12::Resource::DvpVerifyResourceState() +{ + static_assert(SHADER_RESOURCE_TYPE_LAST == 8, "Please update this function to handle the new resource type"); + switch (Type) + { + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: + { + // Not using QueryInterface() for the sake of efficiency + const auto* pBufferD3D12 = pObject.RawPtr<const BufferD3D12Impl>(); + if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_CONSTANT_BUFFER state. Actual state: ", + GetResourceStateString(pBufferD3D12->GetState()), + ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state " + "with IDeviceContext::TransitionResourceStates()."); + } + } + break; + + case SHADER_RESOURCE_TYPE_BUFFER_SRV: + { + const auto* pBuffViewD3D12 = pObject.RawPtr<const BufferViewD3D12Impl>(); + const auto* pBufferD3D12 = pBuffViewD3D12->GetBuffer<const BufferD3D12Impl>(); + if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_SHADER_RESOURCE state. Actual state: ", + GetResourceStateString(pBufferD3D12->GetState()), + ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state " + "with IDeviceContext::TransitionResourceStates()."); + } + } + break; + + case SHADER_RESOURCE_TYPE_BUFFER_UAV: + { + const auto* pBuffViewD3D12 = pObject.RawPtr<const BufferViewD3D12Impl>(); + const auto* pBufferD3D12 = pBuffViewD3D12->GetBuffer<const BufferD3D12Impl>(); + if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_UNORDERED_ACCESS state. Actual state: ", + GetResourceStateString(pBufferD3D12->GetState()), + ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state " + "with IDeviceContext::TransitionResourceStates()."); + } + } + break; + + case SHADER_RESOURCE_TYPE_TEXTURE_SRV: + { + const auto* pTexViewD3D12 = pObject.RawPtr<const TextureViewD3D12Impl>(); + const auto* pTexD3D12 = pTexViewD3D12->GetTexture<TextureD3D12Impl>(); + if (pTexD3D12->IsInKnownState() && !pTexD3D12->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) + { + LOG_ERROR_MESSAGE("Texture '", pTexD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_SHADER_RESOURCE state. Actual state: ", + GetResourceStateString(pTexD3D12->GetState()), + ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + "when calling IDeviceContext::CommitShaderResources() or explicitly transition the texture state " + "with IDeviceContext::TransitionResourceStates()."); + } + } + break; + + case SHADER_RESOURCE_TYPE_TEXTURE_UAV: + { + const auto* pTexViewD3D12 = pObject.RawPtr<const TextureViewD3D12Impl>(); + const auto* pTexD3D12 = pTexViewD3D12->GetTexture<const TextureD3D12Impl>(); + if (pTexD3D12->IsInKnownState() && !pTexD3D12->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("Texture '", pTexD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_UNORDERED_ACCESS state. Actual state: ", + GetResourceStateString(pTexD3D12->GetState()), + ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + "when calling IDeviceContext::CommitShaderResources() or explicitly transition the texture state " + "with IDeviceContext::TransitionResourceStates()."); + } + } + break; + + case SHADER_RESOURCE_TYPE_SAMPLER: + // No resource + break; + + case SHADER_RESOURCE_TYPE_ACCEL_STRUCT: + { + const auto* pTLASD3D12 = pObject.RawPtr<const TopLevelASD3D12Impl>(); + if (pTLASD3D12->IsInKnownState() && !pTLASD3D12->CheckState(RESOURCE_STATE_RAY_TRACING)) + { + LOG_ERROR_MESSAGE("TLAS '", pTLASD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_RAY_TRACING state. Actual state: ", + GetResourceStateString(pTLASD3D12->GetState()), + ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state " + "with IDeviceContext::TransitionResourceStates()."); + } + } + break; + + default: + // Resource is not bound + VERIFY(Type == SHADER_RESOURCE_TYPE_UNKNOWN, "Unexpected resource type"); + VERIFY(pObject == nullptr && CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected"); + } +} +#endif // DILIGENT_DEVELOPMENT + +void ShaderResourceCacheD3D12::TransitionResources(CommandContext& Ctx, + bool PerformTransitions, + bool ValidateStates) +{ + for (Uint32 r = 0; r < m_TotalResourceCount; ++r) + { + auto& Res = GetResource(r); + if (PerformTransitions) + { + Res.TransitionResource(Ctx); + } +#ifdef DILIGENT_DEVELOPMENT + else if (ValidateStates) + { + Res.DvpVerifyResourceState(); + } +#endif + } +} + + + #ifdef DILIGENT_DEBUG //void ShaderResourceCacheD3D12::DbgVerifyBoundDynamicCBsCounter() const //{ |
