Diligent Engine  v.2.4.g
ShaderResourceCacheD3D12.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
32 
33 
34 // Shader resource cache stores D3D12 resources in a continuous chunk of memory:
35 //
36 //
37 // __________________________________________________________
38 // m_pMemory | m_pResources, m_NumResources == m |
39 // | | |
40 // V | V
41 // | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | DescriptorHeapAllocation[0] | ...
42 // | A \
43 // | | \
44 // |________________________________________________| \RefCntAutoPtr
45 // m_pResources, m_NumResources == n \_________
46 // | Object |
47 // ---------
48 //
49 // Nrt = m_NumTables
50 //
51 //
52 // The cache is also assigned decriptor heap space to store descriptor handles.
53 // Static and mutable table resources are stored in shader-visible heap.
54 // Dynamic table resources are stored in CPU-only heap.
55 // Root views are not assigned descriptor space.
56 //
57 //
58 // DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
59 // | DescrptHndl[0] ... DescrptHndl[n-1] | DescrptHndl[0] ... DescrptHndl[m-1] |
60 // A A
61 // | |
62 // | TableStartOffset | TableStartOffset
63 // | |
64 // | RootTable[0] | RootTable[1] | RootTable[2] | .... | RootTable[Nrt] |
65 // | |
66 // | TableStartOffset | InvalidDescriptorOffset
67 // | |
68 // V V
69 // | DescrptHndl[0] ... DescrptHndl[n-1] | X
70 // DESCRIPTOR_HEAP_TYPE_SAMPLER
71 //
72 //
73 //
74 // The allocation is inexed by the offset from the beginning of the root table.
75 // Each root table is assigned the space to store exactly m_NumResources resources.
76 //
77 //
78 //
79 // | RootTable[i] | Res[0] ... Res[n-1] |
80 // \
81 // TableStartOffset\____
82 // \
83 // V
84 // ..... | DescrptHndl[0] ... DescrptHndl[n-1] | ....
85 //
86 //
87 //
88 // The cache stores resources for both root tables and root views.
89 // Resources of root views are treated as single-descriptor tables
90 // Example:
91 //
92 // Root Index | Is Root View | Num Resources
93 // 0 | No | 1+
94 // 1 | Yes | 1
95 // 2 | Yes | 1
96 // 3 | No | 1+
97 // 4 | Yes | 1+
98 // 5 | Yes | 1+
99 // 6 | No | 1
100 // 7 | No | 1
101 // 8 | Yes | 1+
102 // Note that resource cache that is used by signature may contain empty tables.
103 
104 
105 #include <array>
106 #include <memory>
107 
108 #include "Shader.h"
109 #include "DescriptorHeap.hpp"
110 #include "RootParamsManager.hpp"
112 
113 namespace Diligent
114 {
115 
116 class CommandContext;
117 class RenderDeviceD3D12Impl;
118 
120 {
121 public:
122  explicit ShaderResourceCacheD3D12(ResourceCacheContentType ContentType) noexcept :
123  m_ContentType{ContentType}
124  {
125  for (auto& HeapIndex : m_AllocationIndex)
126  HeapIndex.fill(-1);
127  }
128 
129  // clang-format off
134  // clang-format on
135 
137 
139  {
143  size_t TotalSize = 0;
144  };
146 
147  // Initializes resource cache to hold the given number of root tables, no descriptor space
148  // is allocated (this is used to initialize the cache for a pipeline resource signature).
149  void Initialize(IMemoryAllocator& MemAllocator,
150  Uint32 NumTables,
151  const Uint32 TableSizes[]);
152 
153  // Initializes resource cache to hold the resources of a root parameters manager
154  // (this is used to initialize the cache for an SRB).
155  void Initialize(IMemoryAllocator& MemAllocator,
156  RenderDeviceD3D12Impl* pDevice,
157  const RootParamsManager& RootParams);
158 
159  static constexpr Uint32 InvalidDescriptorOffset = ~0u;
160 
161  struct Resource
162  {
163  Resource() noexcept {}
164 
166  // CPU descriptor handle of a cached resource in CPU-only descriptor heap.
167  D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {};
169 
170  bool IsNull() const { return pObject == nullptr; }
171 
172  // Transitions resource to the shader resource state required by Type member.
173  __forceinline void TransitionResource(CommandContext& Ctx);
174 
175 #ifdef DILIGENT_DEVELOPMENT
176  // Verifies that resource is in correct shader resource state required by Type member.
177  void DvpVerifyResourceState();
178 #endif
179  };
180 
181  class RootTable
182  {
183  public:
184  RootTable(Uint32 _NumResources,
185  Resource* _pResources,
186  bool _IsRootView,
187  Uint32 _TableStartOffset = InvalidDescriptorOffset) noexcept :
188  // clang-format off
189  m_NumResources {_NumResources },
190  m_IsRootView {_IsRootView ? 1u : 0u},
191  m_pResources {_pResources },
192  m_TableStartOffset{_TableStartOffset }
193  // clang-format on
194  {
195  VERIFY_EXPR(GetSize() == _NumResources);
196  VERIFY_EXPR(IsRootView() == _IsRootView);
197  VERIFY(!IsRootView() || GetSize() == 1, "Root views may only contain one resource");
198  }
199 
200  const Resource& GetResource(Uint32 OffsetFromTableStart) const
201  {
202  VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart);
203  return m_pResources[OffsetFromTableStart];
204  }
205 
206  Uint32 GetSize() const { return m_NumResources; }
207  Uint32 GetStartOffset() const { return m_TableStartOffset; }
208  bool IsRootView() const { return m_IsRootView != 0; }
209 
210  private:
212  Resource& GetResource(Uint32 OffsetFromTableStart)
213  {
214  VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart);
215  return m_pResources[OffsetFromTableStart];
216  }
217 
218  private:
219  // Offset from the start of the descriptor heap allocation to the start of the table
220  const Uint32 m_TableStartOffset;
221 
222  // The total number of resources in the table, accounting for array sizes
223  const Uint32 m_NumResources : 31;
224 
225  // Flag indicating if this table stores the resource of a root view
226  const Uint32 m_IsRootView : 1;
227 
228  Resource* const m_pResources;
229  };
230 
231  // Sets the resource at the given root index and offset from the table start
232  const Resource& SetResource(Uint32 RootIndex,
233  Uint32 OffsetFromTableStart,
235  D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle,
236  RefCntAutoPtr<IDeviceObject>&& pObject);
237 
238  // Copies the resource to the given root index and offset from the table start
239  const Resource& CopyResource(Uint32 RootIndex,
240  Uint32 OffsetFromTableStart,
241  const Resource& SrcRes)
242  {
243  return SetResource(RootIndex, OffsetFromTableStart, SrcRes.Type, SrcRes.CPUDescriptorHandle, RefCntAutoPtr<IDeviceObject>{SrcRes.pObject});
244  }
245 
246  // Resets the resource at the given root index and offset from the table start to default state
247  const Resource& ResetResource(Uint32 RootIndex,
248  Uint32 OffsetFromTableStart)
249  {
250  return SetResource(RootIndex, OffsetFromTableStart, SHADER_RESOURCE_TYPE_UNKNOWN, D3D12_CPU_DESCRIPTOR_HANDLE{}, RefCntAutoPtr<IDeviceObject>{});
251  }
252 
253  const RootTable& GetRootTable(Uint32 RootIndex) const
254  {
255  VERIFY_EXPR(RootIndex < m_NumTables);
256  return reinterpret_cast<const RootTable*>(m_pMemory.get())[RootIndex];
257  }
258 
259  Uint32 GetNumRootTables() const { return m_NumTables; }
260 
261  ID3D12DescriptorHeap* GetDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, ROOT_PARAMETER_GROUP Group) const
262  {
263  auto AllocationIdx = m_AllocationIndex[HeapType][Group];
264  return AllocationIdx >= 0 ? m_DescriptorAllocations[AllocationIdx].GetDescriptorHeap() : nullptr;
265  }
266 
267  // Returns CPU/GPU descriptor handle of a descriptor heap allocation
268  template <typename HandleType>
270  D3D12_DESCRIPTOR_HEAP_TYPE HeapType,
271  ROOT_PARAMETER_GROUP Group,
272  Uint32 RootParamInd,
273  Uint32 OffsetFromTableStart = 0) const
274  {
275  const auto& RootParam = GetRootTable(RootParamInd);
276  VERIFY(RootParam.GetStartOffset() != InvalidDescriptorOffset, "This root parameter is not assigned a valid descriptor table offset");
277  VERIFY(OffsetFromTableStart < RootParam.GetSize(), "Offset is out of range");
278 
279  const auto AllocationIdx = m_AllocationIndex[HeapType][Group];
280  VERIFY(AllocationIdx >= 0, "Descriptor space is not assigned to this table");
281  VERIFY_EXPR(AllocationIdx < m_NumDescriptorAllocations);
282 
283  return m_DescriptorAllocations[AllocationIdx].GetHandle<HandleType>(RootParam.GetStartOffset() + OffsetFromTableStart);
284  }
285 
286  const DescriptorHeapAllocation& GetDescriptorAllocation(D3D12_DESCRIPTOR_HEAP_TYPE HeapType,
287  ROOT_PARAMETER_GROUP Group) const
288  {
289  const auto AllocationIdx = m_AllocationIndex[HeapType][Group];
290  VERIFY(AllocationIdx >= 0, "Descriptor space is not assigned to this combination of heap type and parameter group");
291  VERIFY_EXPR(AllocationIdx < m_NumDescriptorAllocations);
292  return m_DescriptorAllocations[AllocationIdx];
293  }
294 
296  {
297  Transition,
298  Verify
299  };
300  // Transitions all resources in the cache
302 
303  ResourceCacheContentType GetContentType() const { return m_ContentType; }
304 
305  // Returns the bitmask indicating root views with bound dynamic buffers
306  Uint64 GetDynamicRootBuffersMask() const { return m_DynamicRootBuffersMask; }
307 
308  // Returns the bitmask indicating root views with bound non-dynamic buffers
309  Uint64 GetNonDynamicRootBuffersMask() const { return m_NonDynamicRootBuffersMask; }
310 
311 #ifdef DILIGENT_DEBUG
312  void DbgValidateDynamicBuffersMask() const;
313 #endif
314 
315 private:
316  RootTable& GetRootTable(Uint32 RootIndex)
317  {
318  VERIFY_EXPR(RootIndex < m_NumTables);
319  return reinterpret_cast<RootTable*>(m_pMemory.get())[RootIndex];
320  }
321 
322  Resource& GetResource(Uint32 Idx)
323  {
324  VERIFY_EXPR(Idx < m_TotalResourceCount);
325  return reinterpret_cast<Resource*>(reinterpret_cast<RootTable*>(m_pMemory.get()) + m_NumTables)[Idx];
326  }
327 
328  size_t AllocateMemory(IMemoryAllocator& MemAllocator);
329 
330 private:
331  static constexpr Uint32 MaxRootTables = 64;
332 
333  std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory;
334 
335  // Descriptor heap allocations, indexed by m_AllocationIndex
336  DescriptorHeapAllocation* m_DescriptorAllocations = nullptr;
337 
338  // The total number of resources in all descriptor tables
339  Uint32 m_TotalResourceCount = 0;
340 
341  // The number of descriptor tables in the cache
342  Uint16 m_NumTables = 0;
343 
344  // The number of descriptor heap allocations
345  Uint8 m_NumDescriptorAllocations = 0;
346 
347  // Indicates what types of resources are stored in the cache
348  const ResourceCacheContentType m_ContentType;
349 
350  // Descriptor allocation index in m_DescriptorAllocations array for every descriptor heap type
351  // (CBV_SRV_UAV, SAMPLER) and GPU visibility (false, true).
352  // -1 indicates no allocation.
353  std::array<std::array<Int8, ROOT_PARAMETER_GROUP_COUNT>, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER + 1> m_AllocationIndex{};
354 
355  // The bitmask indicating root views with bound dynamic buffers
356  Uint64 m_DynamicRootBuffersMask = Uint64{0};
357 
358  // The bitmask indicating root views with bound non-dynamic buffers
359  Uint64 m_NonDynamicRootBuffersMask = Uint64{0};
360 };
361 
362 } // namespace Diligent
Diligent::ResourceCacheContentType
ResourceCacheContentType
The type of the content that is stored in the shader resource cache.
Definition: ShaderResourceCacheCommon.hpp:39
ShaderResourceCacheCommon.hpp
Diligent::ShaderResourceCacheD3D12::Resource::IsNull
bool IsNull() const
Definition: ShaderResourceCacheD3D12.hpp:170
Diligent::ShaderResourceCacheD3D12::GetContentType
ResourceCacheContentType GetContentType() const
Definition: ShaderResourceCacheD3D12.hpp:303
Diligent::ShaderResourceCacheD3D12::Resource::Resource
Resource() noexcept
Definition: ShaderResourceCacheD3D12.hpp:163
DescriptorHeap.hpp
Diligent::SHADER_RESOURCE_TYPE
SHADER_RESOURCE_TYPE
Describes shader resource type.
Definition: Shader.h:356
Diligent::ROOT_PARAMETER_GROUP
ROOT_PARAMETER_GROUP
Definition: RootParamsManager.hpp:43
Shader.h
Diligent::ShaderResourceCacheD3D12::Resource::Type
SHADER_RESOURCE_TYPE Type
Definition: ShaderResourceCacheD3D12.hpp:165
Diligent::Uint64
uint64_t Uint64
64-bit unsigned integer
Definition: BasicTypes.h:50
Diligent::ShaderResourceCacheD3D12::GetDescriptorTableHandle
HandleType GetDescriptorTableHandle(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, ROOT_PARAMETER_GROUP Group, Uint32 RootParamInd, Uint32 OffsetFromTableStart=0) const
Definition: ShaderResourceCacheD3D12.hpp:269
Diligent::ShaderResourceCacheD3D12::RootTable::GetResource
const Resource & GetResource(Uint32 OffsetFromTableStart) const
Definition: ShaderResourceCacheD3D12.hpp:200
Diligent::ShaderResourceCacheD3D12::GetDescriptorAllocation
const DescriptorHeapAllocation & GetDescriptorAllocation(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, ROOT_PARAMETER_GROUP Group) const
Definition: ShaderResourceCacheD3D12.hpp:286
Diligent::ShaderResourceCacheD3D12::RootTable::RootTable
RootTable(Uint32 _NumResources, Resource *_pResources, bool _IsRootView, Uint32 _TableStartOffset=InvalidDescriptorOffset) noexcept
Definition: ShaderResourceCacheD3D12.hpp:184
Diligent::ShaderResourceCacheD3D12::Initialize
void Initialize(IMemoryAllocator &MemAllocator, Uint32 NumTables, const Uint32 TableSizes[])
Definition: ShaderResourceCacheD3D12.cpp:122
Diligent::CommandContext
Definition: CommandContext.hpp:66
Diligent::ShaderResourceCacheD3D12::InvalidDescriptorOffset
static constexpr Uint32 InvalidDescriptorOffset
Definition: ShaderResourceCacheD3D12.hpp:159
Diligent::ShaderResourceCacheD3D12::GetMemoryRequirements
static MemoryRequirements GetMemoryRequirements(const RootParamsManager &RootParams)
Definition: ShaderResourceCacheD3D12.cpp:44
Diligent::ShaderResourceCacheD3D12::StateTransitionMode::Transition
@ Transition
Diligent::ShaderResourceCacheD3D12::RootTable::GetSize
Uint32 GetSize() const
Definition: ShaderResourceCacheD3D12.hpp:206
Diligent::ShaderResourceCacheD3D12::MemoryRequirements::NumDescriptorAllocations
Uint32 NumDescriptorAllocations
Definition: ShaderResourceCacheD3D12.hpp:142
Diligent::RenderDeviceD3D12Impl
Render device implementation in Direct3D12 backend.
Definition: RenderDeviceD3D12Impl.hpp:70
Diligent::ShaderResourceCacheD3D12
Definition: ShaderResourceCacheD3D12.hpp:119
Diligent::ShaderResourceCacheD3D12::MemoryRequirements::NumTables
Uint32 NumTables
Definition: ShaderResourceCacheD3D12.hpp:140
Diligent::ShaderResourceCacheD3D12::GetNumRootTables
Uint32 GetNumRootTables() const
Definition: ShaderResourceCacheD3D12.hpp:259
Diligent::ShaderResourceCacheD3D12::ResetResource
const Resource & ResetResource(Uint32 RootIndex, Uint32 OffsetFromTableStart)
Definition: ShaderResourceCacheD3D12.hpp:247
Diligent::ShaderResourceCacheD3D12::Resource
Definition: ShaderResourceCacheD3D12.hpp:161
Diligent::ShaderResourceCacheD3D12::operator=
ShaderResourceCacheD3D12 & operator=(const ShaderResourceCacheD3D12 &)=delete
Diligent::ShaderResourceCacheD3D12::CopyResource
const Resource & CopyResource(Uint32 RootIndex, Uint32 OffsetFromTableStart, const Resource &SrcRes)
Definition: ShaderResourceCacheD3D12.hpp:239
Diligent::ShaderResourceCacheD3D12::RootTable
Definition: ShaderResourceCacheD3D12.hpp:181
Diligent::RefCntAutoPtr
Template class that implements reference counting.
Definition: RefCntAutoPtr.hpp:73
Type
const D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type
Definition: PipelineStateD3D12Impl.cpp:69
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:51
Diligent::ShaderResourceCacheD3D12::SetResource
const Resource & SetResource(Uint32 RootIndex, Uint32 OffsetFromTableStart, SHADER_RESOURCE_TYPE Type, D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle, RefCntAutoPtr< IDeviceObject > &&pObject)
Definition: ShaderResourceCacheD3D12.cpp:296
Diligent::DescriptorHeapAllocation::GetDescriptorHeap
ID3D12DescriptorHeap * GetDescriptorHeap() const
Definition: DescriptorHeap.hpp:199
Diligent::ShaderResourceCacheD3D12::TransitionResourceStates
void TransitionResourceStates(CommandContext &Ctx, StateTransitionMode Mode)
Definition: ShaderResourceCacheD3D12.cpp:620
Diligent::ShaderResourceCacheD3D12::GetDynamicRootBuffersMask
Uint64 GetDynamicRootBuffersMask() const
Definition: ShaderResourceCacheD3D12.hpp:306
Diligent::ShaderResourceCacheD3D12::StateTransitionMode
StateTransitionMode
Definition: ShaderResourceCacheD3D12.hpp:295
Diligent::ShaderResourceCacheD3D12::Resource::CPUDescriptorHandle
D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle
Definition: ShaderResourceCacheD3D12.hpp:167
Diligent::ShaderResourceCacheD3D12::GetNonDynamicRootBuffersMask
Uint64 GetNonDynamicRootBuffersMask() const
Definition: ShaderResourceCacheD3D12.hpp:309
Diligent::ShaderResourceCacheD3D12::MemoryRequirements
Definition: ShaderResourceCacheD3D12.hpp:138
Diligent::ShaderResourceCacheD3D12::StateTransitionMode::Verify
@ Verify
Diligent::ShaderResourceCacheD3D12::RootTable::IsRootView
bool IsRootView() const
Definition: ShaderResourceCacheD3D12.hpp:208
Diligent::ShaderResourceCacheD3D12::ShaderResourceCacheD3D12
ShaderResourceCacheD3D12(ResourceCacheContentType ContentType) noexcept
Definition: ShaderResourceCacheD3D12.hpp:122
Diligent::IMemoryAllocator
Base interface for a raw memory allocator.
Definition: MemoryAllocator.h:41
Diligent::ShaderResourceCacheD3D12::MemoryRequirements::TotalResources
Uint32 TotalResources
Definition: ShaderResourceCacheD3D12.hpp:141
Diligent::ShaderResourceCacheD3D12::~ShaderResourceCacheD3D12
~ShaderResourceCacheD3D12()
Definition: ShaderResourceCacheD3D12.cpp:281
Diligent::Uint16
uint16_t Uint16
16-bit unsigned integer
Definition: BasicTypes.h:52
Diligent::ShaderResourceCacheD3D12::Resource::pObject
RefCntAutoPtr< IDeviceObject > pObject
Definition: ShaderResourceCacheD3D12.hpp:168
Diligent::Uint8
uint8_t Uint8
8-bit unsigned integer
Definition: BasicTypes.h:53
VERIFY_EXPR
#define VERIFY_EXPR(...)
Definition: DebugUtilities.hpp:79
RootParamsManager.hpp
VERIFY
#define VERIFY(...)
Definition: DebugUtilities.hpp:76
Diligent::ShaderResourceCacheD3D12::GetRootTable
const RootTable & GetRootTable(Uint32 RootIndex) const
Definition: ShaderResourceCacheD3D12.hpp:253
Diligent::ShaderResourceCacheD3D12::GetDescriptorHeap
ID3D12DescriptorHeap * GetDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE HeapType, ROOT_PARAMETER_GROUP Group) const
Definition: ShaderResourceCacheD3D12.hpp:261
Diligent::DescriptorHeapAllocation
Definition: DescriptorHeap.hpp:67
Diligent::ShaderResourceCacheD3D12::RootTable::GetStartOffset
Uint32 GetStartOffset() const
Definition: ShaderResourceCacheD3D12.hpp:207
Diligent::SHADER_RESOURCE_TYPE_UNKNOWN
@ SHADER_RESOURCE_TYPE_UNKNOWN
Shader resource type is unknown.
Definition: Shader.h:359
Diligent::ShaderResourceCacheD3D12::Resource::TransitionResource
__forceinline void TransitionResource(CommandContext &Ctx)
Definition: ShaderResourceCacheD3D12.cpp:429
Diligent::RootParamsManager
Container for root parameters.
Definition: RootParamsManager.hpp:127
Diligent::DescriptorHeapAllocation::GetHandle
HandleType GetHandle(Uint32 Offset=0) const
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37
Diligent::ShaderResourceCacheD3D12::MemoryRequirements::TotalSize
size_t TotalSize
Definition: ShaderResourceCacheD3D12.hpp:143