Skip to content

Commit 69d2f73

Browse files
ShaderResourceCacheD3D12: allocate space for inline constant values (#672)
1 parent 2d41af2 commit 69d2f73

File tree

3 files changed

+145
-29
lines changed

3 files changed

+145
-29
lines changed

Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
// m_pMemory | m_pResources, m_NumResources == m |
3939
// | | |
4040
// V | V
41-
// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | DescriptorHeapAllocation[0] | ...
41+
// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | Descriptor Heap Allocations | Inline constant values |
4242
// | A \
4343
// | | \
4444
// |________________________________________________| \RefCntAutoPtr
@@ -70,6 +70,7 @@
7070
// DESCRIPTOR_HEAP_TYPE_SAMPLER
7171
//
7272
//
73+
// Root constant parameters use CPUDescriptorHandle.ptr to store pointer to the raw data.
7374
//
7475
// The allocation is inexed by the offset from the beginning of the root table.
7576
// Each root table is assigned the space to store exactly m_NumResources resources.
@@ -138,18 +139,29 @@ class ShaderResourceCacheD3D12 : public ShaderResourceCacheBase
138139

139140
struct MemoryRequirements
140141
{
141-
Uint32 NumTables = 0;
142-
Uint32 TotalResources = 0;
143-
Uint32 NumDescriptorAllocations = 0;
144-
size_t TotalSize = 0;
142+
Uint32 NumTables = 0;
143+
Uint32 TotalResources = 0;
144+
Uint32 NumDescriptorAllocations = 0;
145+
Uint32 TotalInlineConstantValues = 0;
146+
size_t TotalSize = 0;
145147
};
146148
static MemoryRequirements GetMemoryRequirements(const RootParamsManager& RootParams);
147149

150+
151+
struct InlineConstantParamInfo
152+
{
153+
Uint32 RootIndex = 0;
154+
Uint32 OffsetFromTableStart = 0;
155+
Uint32 NumValues = 0;
156+
};
157+
using InlineConstantInfoVectorType = std::vector<InlineConstantParamInfo>;
158+
148159
// Initializes resource cache to hold the given number of root tables, no descriptor space
149160
// is allocated (this is used to initialize the cache for a pipeline resource signature).
150-
void Initialize(IMemoryAllocator& MemAllocator,
151-
Uint32 NumTables,
152-
const Uint32 TableSizes[]);
161+
void Initialize(IMemoryAllocator& MemAllocator,
162+
Uint32 NumTables,
163+
const Uint32 TableSizes[],
164+
const InlineConstantInfoVectorType& InlineConstants);
153165

154166
// Initializes resource cache to hold the resources of a root parameters manager
155167
// (this is used to initialize the cache for an SRB).
@@ -192,6 +204,7 @@ class ShaderResourceCacheD3D12 : public ShaderResourceCacheBase
192204

193205
// CPU descriptor handle of a cached resource in CPU-only descriptor heap.
194206
// This handle may be null for CBVs that address the buffer range.
207+
// For root constant parameters, ptr stores pointer to the raw data.
195208
D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {};
196209
RefCntAutoPtr<IDeviceObject> pObject;
197210

@@ -289,7 +302,7 @@ class ShaderResourceCacheD3D12 : public ShaderResourceCacheBase
289302
const RootTable& GetRootTable(Uint32 RootIndex) const
290303
{
291304
VERIFY_EXPR(RootIndex < m_NumTables);
292-
return reinterpret_cast<const RootTable*>(m_pMemory.get())[RootIndex];
305+
return GetRootTableStorage()[RootIndex];
293306
}
294307

295308
Uint32 GetNumRootTables() const { return m_NumTables; }
@@ -362,7 +375,7 @@ class ShaderResourceCacheD3D12 : public ShaderResourceCacheBase
362375
RootTable& GetRootTable(Uint32 RootIndex)
363376
{
364377
VERIFY_EXPR(RootIndex < m_NumTables);
365-
return reinterpret_cast<RootTable*>(m_pMemory.get())[RootIndex];
378+
return GetRootTableStorage()[RootIndex];
366379
}
367380

368381
Resource& GetResource(Uint32 Idx)
@@ -371,7 +384,33 @@ class ShaderResourceCacheD3D12 : public ShaderResourceCacheBase
371384
return reinterpret_cast<Resource*>(reinterpret_cast<RootTable*>(m_pMemory.get()) + m_NumTables)[Idx];
372385
}
373386

374-
size_t AllocateMemory(IMemoryAllocator& MemAllocator);
387+
size_t AllocateMemory(IMemoryAllocator& MemAllocator,
388+
Uint32 TotalInlineConstantValues);
389+
390+
// Memory layout:
391+
//
392+
// | Root tables | Resources | DescriptorHeapAllocations | Inline constant values |
393+
//
394+
RootTable* GetRootTableStorage()
395+
{
396+
return reinterpret_cast<RootTable*>(m_pMemory.get());
397+
}
398+
const RootTable* GetRootTableStorage() const
399+
{
400+
return reinterpret_cast<const RootTable*>(m_pMemory.get());
401+
}
402+
Resource* GetResourceStorage()
403+
{
404+
return reinterpret_cast<Resource*>(GetRootTableStorage() + m_NumTables);
405+
}
406+
DescriptorHeapAllocation* GetDescriptorAllocationStorage()
407+
{
408+
return reinterpret_cast<DescriptorHeapAllocation*>(GetResourceStorage() + m_TotalResourceCount);
409+
}
410+
Uint32* GetInlineConstantStorage()
411+
{
412+
return reinterpret_cast<Uint32*>(GetDescriptorAllocationStorage() + m_NumDescriptorAllocations);
413+
}
375414

376415
private:
377416
static constexpr Uint32 MaxRootTables = 64;

Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ void PipelineResourceSignatureD3D12Impl::AllocateRootParameters(const bool IsSer
193193
// Cache table sizes for static resources
194194
std::array<Uint32, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER + 1> StaticResCacheTblSizes{};
195195

196+
ShaderResourceCacheD3D12::InlineConstantInfoVectorType StaticResInlineConstInfo;
197+
196198
// Allocate registers for immutable samplers first
197199
for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i)
198200
{
@@ -253,7 +255,22 @@ void PipelineResourceSignatureD3D12Impl::AllocateRootParameters(const bool IsSer
253255
// Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER (3)
254256
SigRootIndex = d3d12DescriptorRangeType;
255257
SigOffsetFromTableStart = StaticResCacheTblSizes[SigRootIndex];
256-
StaticResCacheTblSizes[SigRootIndex] += ResDesc.ArraySize;
258+
259+
if ((ResDesc.Flags & PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) != 0)
260+
{
261+
ShaderResourceCacheD3D12::InlineConstantParamInfo InlineConstInfo;
262+
InlineConstInfo.RootIndex = SigRootIndex;
263+
InlineConstInfo.OffsetFromTableStart = SigOffsetFromTableStart;
264+
InlineConstInfo.NumValues = ResDesc.ArraySize;
265+
StaticResInlineConstInfo.push_back(InlineConstInfo);
266+
267+
// For inline constants, count only one resource as the ArraySize is the number of 4-byte constants
268+
StaticResCacheTblSizes[SigRootIndex] += 1;
269+
}
270+
else
271+
{
272+
StaticResCacheTblSizes[SigRootIndex] += ResDesc.ArraySize;
273+
}
257274
}
258275

259276
if (IsRTSizedArray)
@@ -337,7 +354,7 @@ void PipelineResourceSignatureD3D12Impl::AllocateRootParameters(const bool IsSer
337354
SigRootIndex,
338355
SigOffsetFromTableStart,
339356
SrcImmutableSamplerInd != InvalidImmutableSamplerIndex,
340-
d3d12RootParamType //
357+
d3d12RootParamType,
341358
};
342359
}
343360
else
@@ -366,7 +383,7 @@ void PipelineResourceSignatureD3D12Impl::AllocateRootParameters(const bool IsSer
366383

367384
if (GetNumStaticResStages() > 0)
368385
{
369-
m_pStaticResCache->Initialize(GetRawAllocator(), static_cast<Uint32>(StaticResCacheTblSizes.size()), StaticResCacheTblSizes.data());
386+
m_pStaticResCache->Initialize(GetRawAllocator(), static_cast<Uint32>(StaticResCacheTblSizes.size()), StaticResCacheTblSizes.data(), StaticResInlineConstInfo);
370387
}
371388
else
372389
{

Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ ShaderResourceCacheD3D12::MemoryRequirements ShaderResourceCacheD3D12::GetMemory
4545
{
4646
const Uint32 NumRootTables = RootParams.GetNumRootTables();
4747
const Uint32 NumRootViews = RootParams.GetNumRootViews();
48+
const Uint32 NumRootConsts = RootParams.GetNumRootConstants();
4849

4950
MemoryRequirements MemReqs;
5051

@@ -61,17 +62,26 @@ ShaderResourceCacheD3D12::MemoryRequirements ShaderResourceCacheD3D12::GetMemory
6162
}
6263
}
6364
}
64-
// Root views' resources are stored in one-descriptor tables
65+
// Root views and root constants resources are stored in one-descriptor tables
6566
MemReqs.TotalResources += NumRootViews;
67+
MemReqs.TotalResources += NumRootConsts;
6668

6769
static_assert(sizeof(RootTable) % sizeof(void*) == 0, "sizeof(RootTable) is not aligned by the sizeof(void*)");
6870
static_assert(sizeof(Resource) % sizeof(void*) == 0, "sizeof(Resource) is not aligned by the sizeof(void*)");
6971

70-
MemReqs.NumTables = NumRootTables + NumRootViews;
72+
MemReqs.NumTables = NumRootTables + NumRootViews + NumRootConsts;
73+
74+
MemReqs.TotalInlineConstantValues = 0;
75+
for (Uint32 i = 0; i < NumRootConsts; ++i)
76+
{
77+
const RootParameter& RootConsts = RootParams.GetRootConstants(i);
78+
MemReqs.TotalInlineConstantValues += RootConsts.d3d12RootParam.Constants.Num32BitValues;
79+
}
7180

7281
MemReqs.TotalSize = (MemReqs.NumTables * sizeof(RootTable) +
7382
MemReqs.TotalResources * sizeof(Resource) +
74-
MemReqs.NumDescriptorAllocations * sizeof(DescriptorHeapAllocation));
83+
MemReqs.NumDescriptorAllocations * sizeof(DescriptorHeapAllocation) +
84+
MemReqs.TotalInlineConstantValues * sizeof(Uint32));
7585

7686
return MemReqs;
7787
}
@@ -82,21 +92,23 @@ ShaderResourceCacheD3D12::MemoryRequirements ShaderResourceCacheD3D12::GetMemory
8292
// m_pMemory | m_pResources, m_NumResources |
8393
// | | |
8494
// V | V
85-
// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | DescriptorHeapAllocation[0] | ...
95+
// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | Descriptor Heap Allocations | Inline cnstant values |
8696
// | A
8797
// | |
8898
// |________________________________________________|
8999
// m_pResources, m_NumResources
90100
//
91101

92-
size_t ShaderResourceCacheD3D12::AllocateMemory(IMemoryAllocator& MemAllocator)
102+
size_t ShaderResourceCacheD3D12::AllocateMemory(IMemoryAllocator& MemAllocator,
103+
Uint32 TotalInlineConstantValues)
93104
{
94105
VERIFY(!m_pMemory, "Memory has already been allocated");
95106

96107
const size_t MemorySize =
97108
(m_NumTables * sizeof(RootTable) +
98109
m_TotalResourceCount * sizeof(Resource) +
99-
m_NumDescriptorAllocations * sizeof(DescriptorHeapAllocation));
110+
m_NumDescriptorAllocations * sizeof(DescriptorHeapAllocation) +
111+
TotalInlineConstantValues * sizeof(Uint32));
100112

101113
if (MemorySize > 0)
102114
{
@@ -105,12 +117,13 @@ size_t ShaderResourceCacheD3D12::AllocateMemory(IMemoryAllocator& MemAllocator)
105117
STDDeleter<void, IMemoryAllocator>(MemAllocator) //
106118
};
107119

108-
RootTable* const pTables = reinterpret_cast<RootTable*>(m_pMemory.get());
109-
Resource* const pResources = reinterpret_cast<Resource*>(pTables + m_NumTables);
110-
m_DescriptorAllocations = m_NumDescriptorAllocations > 0 ? reinterpret_cast<DescriptorHeapAllocation*>(pResources + m_TotalResourceCount) : nullptr;
120+
Resource* const pResources = GetResourceStorage();
121+
m_DescriptorAllocations = m_NumDescriptorAllocations > 0 ? GetDescriptorAllocationStorage() : nullptr;
111122

112123
for (Uint32 res = 0; res < m_TotalResourceCount; ++res)
124+
{
113125
new (pResources + res) Resource{};
126+
}
114127

115128
for (Uint32 i = 0; i < m_NumDescriptorAllocations; ++i)
116129
new (m_DescriptorAllocations + i) DescriptorHeapAllocation{};
@@ -119,9 +132,10 @@ size_t ShaderResourceCacheD3D12::AllocateMemory(IMemoryAllocator& MemAllocator)
119132
return MemorySize;
120133
}
121134

122-
void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator,
123-
Uint32 NumTables,
124-
const Uint32 TableSizes[])
135+
void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator,
136+
Uint32 NumTables,
137+
const Uint32 TableSizes[],
138+
const InlineConstantInfoVectorType& InlineConstants)
125139
{
126140
VERIFY(GetContentType() == ResourceCacheContentType::Signature,
127141
"This method should be called to initialize the cache to store resources of a pipeline resource signature");
@@ -137,7 +151,13 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator,
137151

138152
m_DescriptorAllocations = 0;
139153

140-
AllocateMemory(MemAllocator);
154+
Uint32 TotalInlineConstantValues = 0;
155+
for (const InlineConstantParamInfo& InlineConstInfo : InlineConstants)
156+
{
157+
TotalInlineConstantValues += InlineConstInfo.NumValues;
158+
}
159+
160+
AllocateMemory(MemAllocator, TotalInlineConstantValues);
141161

142162
Uint32 ResIdx = 0;
143163
for (Uint32 t = 0; t < m_NumTables; ++t)
@@ -146,6 +166,15 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator,
146166
ResIdx += TableSizes[t];
147167
}
148168
VERIFY_EXPR(ResIdx == m_TotalResourceCount);
169+
170+
Uint32* pCurrInlineConstValueStorage = GetInlineConstantStorage();
171+
for (const InlineConstantParamInfo& InlineConstInfo : InlineConstants)
172+
{
173+
Resource& Res = GetRootTable(InlineConstInfo.RootIndex).GetResource(InlineConstInfo.OffsetFromTableStart);
174+
Res.CPUDescriptorHandle.ptr = reinterpret_cast<SIZE_T>(pCurrInlineConstValueStorage);
175+
pCurrInlineConstValueStorage += InlineConstInfo.NumValues;
176+
}
177+
VERIFY_EXPR(pCurrInlineConstValueStorage == GetInlineConstantStorage() + TotalInlineConstantValues);
149178
}
150179

151180

@@ -168,7 +197,7 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator,
168197
m_NumDescriptorAllocations = static_cast<decltype(m_NumDescriptorAllocations)>(MemReq.NumDescriptorAllocations);
169198
VERIFY_EXPR(m_NumDescriptorAllocations == MemReq.NumDescriptorAllocations);
170199

171-
const size_t MemSize = AllocateMemory(MemAllocator);
200+
const size_t MemSize = AllocateMemory(MemAllocator, MemReq.TotalInlineConstantValues);
172201
VERIFY_EXPR(MemSize == MemReq.TotalSize);
173202

174203
#ifdef DILIGENT_DEBUG
@@ -177,7 +206,7 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator,
177206

178207
Uint32 ResIdx = 0;
179208

180-
// Initialize root tables
209+
// Initialize root tables.
181210
for (Uint32 i = 0; i < RootParams.GetNumRootTables(); ++i)
182211
{
183212
const RootParameter& RootTbl = RootParams.GetRootTable(i);
@@ -220,6 +249,37 @@ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator,
220249
RootTableInitFlags[RootView.RootIndex] = true;
221250
#endif
222251
}
252+
253+
if (Uint32 NumRootConstants = RootParams.GetNumRootConstants())
254+
{
255+
Uint32* pCurrInlineConstValueStorage = GetInlineConstantStorage();
256+
257+
// Initialize one-descriptor tables for root constants
258+
for (Uint32 i = 0; i < NumRootConstants; ++i)
259+
{
260+
const RootParameter& RootConsts = RootParams.GetRootConstants(i);
261+
VERIFY(!RootTableInitFlags[RootConsts.RootIndex], "Root table at index ", RootConsts.RootIndex, " has already been initialized.");
262+
VERIFY_EXPR(RootConsts.TableOffsetInGroupAllocation == RootParameter::InvalidTableOffsetInGroupAllocation);
263+
VERIFY_EXPR(RootConsts.d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS);
264+
265+
GetResource(ResIdx).CPUDescriptorHandle.ptr = reinterpret_cast<SIZE_T>(pCurrInlineConstValueStorage);
266+
pCurrInlineConstValueStorage += RootConsts.d3d12RootParam.Constants.Num32BitValues;
267+
268+
new (&GetRootTable(RootConsts.RootIndex)) RootTable{
269+
1,
270+
&GetResource(ResIdx),
271+
false //IsRootView
272+
};
273+
++ResIdx;
274+
275+
#ifdef DILIGENT_DEBUG
276+
RootTableInitFlags[RootConsts.RootIndex] = true;
277+
#endif
278+
}
279+
280+
VERIFY_EXPR(pCurrInlineConstValueStorage == GetInlineConstantStorage() + MemReq.TotalInlineConstantValues);
281+
}
282+
223283
VERIFY_EXPR(ResIdx == m_TotalResourceCount);
224284

225285
#ifdef DILIGENT_DEBUG

0 commit comments

Comments
 (0)