summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-02-20 05:46:52 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:38:09 +0000
commitac28bcb6cd1f23cd4223bd16ed3564b3488f5e2b (patch)
tree5cbe903ea5f5379a9ff2a585362356d73f4fa91e /Graphics/GraphicsEngineD3D12
parentPipelineResourceSignatureD3D12Impl and PipelineResourceSignatureVkImpl: remov... (diff)
downloadDiligentCore-ac28bcb6cd1f23cd4223bd16ed3564b3488f5e2b.tar.gz
DiligentCore-ac28bcb6cd1f23cd4223bd16ed3564b3488f5e2b.zip
D3D12 backend: moved resource state transition logic from PipelineResourceSignatureD3D12Impl to ShaderResourceCacheD3D12
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp12
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp58
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp6
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp291
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp241
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
//{