D3DDescriptor.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/D3D/D3DDescriptor.h>
  6. #include <AnKi/Core/CVarSet.h>
  7. namespace anki {
  8. static NumericCVar<U16> g_maxRtvDescriptors(CVarSubsystem::kGr, "MaxRvtDescriptors", 128, 8, kMaxU16, "Max number of RTVs");
  9. static NumericCVar<U16> g_maxDsvDescriptors(CVarSubsystem::kGr, "MaxDsvDescriptors", 128, 8, kMaxU16, "Max number of DSVs");
  10. static NumericCVar<U16> g_maxCpuCbvSrvUavDescriptors(CVarSubsystem::kGr, "MaxCpuCbvSrvUavDescriptors", 1024, 8, kMaxU16,
  11. "Max number of CBV/SRV/UAV descriptors");
  12. static NumericCVar<U16> g_maxCpuSamplerDescriptors(CVarSubsystem::kGr, "MaxCpuSamplerDescriptors", 64, 8, kMaxU16,
  13. "Max number of sampler descriptors");
  14. static NumericCVar<U16> g_maxGpuCbvSrvUavDescriptors(CVarSubsystem::kGr, "MaxGpuCbvSrvUavDescriptors", 2 * 1024, 8, kMaxU16,
  15. "Max number of CBV/SRV/UAV descriptors");
  16. static NumericCVar<U16> g_maxGpuSamplerDescriptors(CVarSubsystem::kGr, "MaxGpuSamplerDescriptors", 128, 8, kMaxU16,
  17. "Max number of sampler descriptors");
  18. static Error createDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags, U32 descriptorCount,
  19. ID3D12DescriptorHeap*& heap, D3D12_CPU_DESCRIPTOR_HANDLE& cpuHeapStart, D3D12_GPU_DESCRIPTOR_HANDLE& gpuHeapStart,
  20. U32& descriptorSize)
  21. {
  22. D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
  23. heapDesc.NumDescriptors = descriptorCount;
  24. heapDesc.Type = type;
  25. heapDesc.Flags = flags;
  26. ANKI_D3D_CHECK(getDevice().CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&heap)));
  27. cpuHeapStart = heap->GetCPUDescriptorHandleForHeapStart();
  28. if(flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
  29. {
  30. gpuHeapStart = heap->GetGPUDescriptorHandleForHeapStart();
  31. }
  32. else
  33. {
  34. gpuHeapStart = {};
  35. }
  36. ANKI_ASSERT(cpuHeapStart.ptr != 0 || gpuHeapStart.ptr != 0);
  37. descriptorSize = getDevice().GetDescriptorHandleIncrementSize(type);
  38. return Error::kNone;
  39. }
  40. void PersistentDescriptorAllocator::init(D3D12_CPU_DESCRIPTOR_HANDLE cpuHeapStart, D3D12_GPU_DESCRIPTOR_HANDLE gpuHeapStart, U32 descriptorSize,
  41. U16 descriptorCount)
  42. {
  43. ANKI_ASSERT(descriptorSize > 0);
  44. ANKI_ASSERT(descriptorCount > 0);
  45. ANKI_ASSERT(cpuHeapStart.ptr != 0 || gpuHeapStart.ptr != 0);
  46. m_cpuHeapStart = cpuHeapStart;
  47. m_gpuHeapStart = gpuHeapStart;
  48. m_descriptorSize = descriptorSize;
  49. m_freeDescriptors.resize(descriptorCount);
  50. for(U16 i = 0; i < descriptorCount; ++i)
  51. {
  52. m_freeDescriptors[i] = i;
  53. }
  54. m_freeDescriptorsHead = 0;
  55. }
  56. DescriptorHeapHandle PersistentDescriptorAllocator::allocate()
  57. {
  58. ANKI_ASSERT(m_descriptorSize > 0);
  59. U16 idx;
  60. {
  61. LockGuard lock(m_mtx);
  62. if(m_freeDescriptorsHead == m_freeDescriptors.getSize())
  63. {
  64. ANKI_D3D_LOGF("Out of descriptors");
  65. }
  66. idx = m_freeDescriptorsHead;
  67. ++m_freeDescriptorsHead;
  68. }
  69. idx = m_freeDescriptors[idx];
  70. DescriptorHeapHandle out;
  71. out.m_cpuHandle.ptr = (m_cpuHeapStart.ptr) ? (m_cpuHeapStart.ptr + PtrSize(idx) * m_descriptorSize) : 0;
  72. out.m_gpuHandle.ptr = (m_gpuHeapStart.ptr) ? (m_gpuHeapStart.ptr + PtrSize(idx) * m_descriptorSize) : 0;
  73. #if ANKI_ASSERTIONS_ENABLED
  74. out.m_heapCpuStart = m_cpuHeapStart;
  75. out.m_heapGpuStart = m_gpuHeapStart;
  76. out.m_heapSize = m_descriptorSize * m_freeDescriptors.getSize();
  77. #endif
  78. return out;
  79. }
  80. void PersistentDescriptorAllocator::free(DescriptorHeapHandle& handle)
  81. {
  82. ANKI_ASSERT(m_descriptorSize > 0);
  83. if(!handle.isCreated()) [[unlikely]]
  84. {
  85. return;
  86. }
  87. handle.validate();
  88. ANKI_ASSERT(handle.m_heapCpuStart.ptr == m_cpuHeapStart.ptr);
  89. const PtrSize descriptorOffsetFromStart = handle.m_cpuHandle.ptr - m_cpuHeapStart.ptr;
  90. const U16 idx = U16(descriptorOffsetFromStart / m_descriptorSize);
  91. LockGuard lock(m_mtx);
  92. ANKI_ASSERT(m_freeDescriptorsHead > 0);
  93. --m_freeDescriptorsHead;
  94. m_freeDescriptors[m_freeDescriptorsHead] = idx;
  95. handle = {};
  96. }
  97. void RingDescriptorAllocator::init(D3D12_CPU_DESCRIPTOR_HANDLE cpuHeapStart, D3D12_GPU_DESCRIPTOR_HANDLE gpuHeapStart, U32 descriptorSize,
  98. U32 descriptorCount)
  99. {
  100. ANKI_ASSERT(descriptorSize > 0);
  101. ANKI_ASSERT(descriptorCount > 0);
  102. ANKI_ASSERT(cpuHeapStart.ptr != 0 || gpuHeapStart.ptr != 0);
  103. m_cpuHeapStart = cpuHeapStart;
  104. m_gpuHeapStart = gpuHeapStart;
  105. m_descriptorSize = descriptorSize;
  106. m_descriptorCount = descriptorCount;
  107. }
  108. DescriptorHeapHandle RingDescriptorAllocator::allocate(U32 descriptorCount)
  109. {
  110. ANKI_ASSERT(m_descriptorSize > 0);
  111. U32 firstDescriptor;
  112. Bool allocationPassesEnd = false;
  113. do
  114. {
  115. firstDescriptor = m_increment.fetchAdd(descriptorCount) % m_descriptorCount;
  116. allocationPassesEnd = firstDescriptor + descriptorCount > m_descriptorCount;
  117. } while(allocationPassesEnd);
  118. DescriptorHeapHandle out;
  119. out.m_cpuHandle.ptr = (m_cpuHeapStart.ptr) ? (m_cpuHeapStart.ptr + firstDescriptor * m_descriptorSize) : 0;
  120. out.m_gpuHandle.ptr = (m_gpuHeapStart.ptr) ? (m_gpuHeapStart.ptr + firstDescriptor * m_descriptorSize) : 0;
  121. #if ANKI_ASSERTIONS_ENABLED
  122. out.m_heapCpuStart = m_cpuHeapStart;
  123. out.m_heapGpuStart = m_gpuHeapStart;
  124. out.m_heapSize = m_descriptorSize * m_descriptorCount;
  125. #endif
  126. return out;
  127. }
  128. void RingDescriptorAllocator::endFrame()
  129. {
  130. const U64 crntIncrement = m_increment.load();
  131. const U32 descriptorsAllocatedThisFrame = U32(crntIncrement - m_incrementAtFrameStart);
  132. const U32 maxFramesInFlight = kMaxFramesInFlight + 1; // Be very conservative
  133. if(descriptorsAllocatedThisFrame > m_descriptorCount / maxFramesInFlight)
  134. {
  135. ANKI_D3D_LOGW("Allocated too many descriptors this frame");
  136. }
  137. m_incrementAtFrameStart = crntIncrement;
  138. }
  139. DescriptorFactory::~DescriptorFactory()
  140. {
  141. for(ID3D12DescriptorHeap* h : m_descriptorHeaps)
  142. {
  143. safeRelease(h);
  144. }
  145. }
  146. Error DescriptorFactory::init()
  147. {
  148. // Init CPU descriptors first
  149. auto createHeapAndAllocator = [this](D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags, U16 descriptorCount,
  150. PersistentDescriptorAllocator& alloc) -> Error {
  151. ID3D12DescriptorHeap* heap;
  152. D3D12_CPU_DESCRIPTOR_HANDLE cpuHeapStart;
  153. D3D12_GPU_DESCRIPTOR_HANDLE gpuHeapStart;
  154. U32 descriptorSize;
  155. ANKI_CHECK(createDescriptorHeap(type, flags, descriptorCount, heap, cpuHeapStart, gpuHeapStart, descriptorSize));
  156. alloc.init(cpuHeapStart, gpuHeapStart, descriptorSize, descriptorCount);
  157. m_descriptorHeaps.emplaceBack(heap);
  158. return Error::kNone;
  159. };
  160. ANKI_CHECK(createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxCpuCbvSrvUavDescriptors.get(),
  161. m_cpuPersistent.m_cbvSrvUav));
  162. ANKI_CHECK(createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxCpuSamplerDescriptors.get(),
  163. m_cpuPersistent.m_sampler));
  164. ANKI_CHECK(
  165. createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxRtvDescriptors.get(), m_cpuPersistent.m_rtv));
  166. ANKI_CHECK(
  167. createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxDsvDescriptors.get(), m_cpuPersistent.m_dsv));
  168. // Init GPU visible heaps
  169. ID3D12DescriptorHeap* heap;
  170. D3D12_CPU_DESCRIPTOR_HANDLE cpuHeapStart;
  171. D3D12_GPU_DESCRIPTOR_HANDLE gpuHeapStart;
  172. U32 descriptorSize;
  173. ANKI_CHECK(createDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
  174. g_maxGpuCbvSrvUavDescriptors.get() + kMaxBindlessTextures, heap, cpuHeapStart, gpuHeapStart, descriptorSize));
  175. m_descriptorHeaps.emplaceBack(heap);
  176. m_gpuPersistent.m_cbvSrvUav.init(cpuHeapStart, gpuHeapStart, descriptorSize, kMaxBindlessTextures);
  177. cpuHeapStart.ptr += descriptorSize * kMaxBindlessTextures;
  178. gpuHeapStart.ptr += descriptorSize * kMaxBindlessTextures;
  179. m_gpuRing.m_cbvSrvUav.init(cpuHeapStart, gpuHeapStart, descriptorSize, g_maxGpuCbvSrvUavDescriptors.get());
  180. ANKI_CHECK(createDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, g_maxGpuSamplerDescriptors.get(),
  181. heap, cpuHeapStart, gpuHeapStart, descriptorSize));
  182. m_descriptorHeaps.emplaceBack(heap);
  183. m_gpuRing.m_sampler.init(cpuHeapStart, gpuHeapStart, descriptorSize, g_maxGpuSamplerDescriptors.get());
  184. // Misc
  185. for(D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE(0); type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
  186. type = D3D12_DESCRIPTOR_HEAP_TYPE(type + 1))
  187. {
  188. m_descriptorHandleIncrementSizes[type] = getDevice().GetDescriptorHandleIncrementSize(type);
  189. }
  190. return Error::kNone;
  191. }
  192. RootSignatureFactory::~RootSignatureFactory()
  193. {
  194. for(auto sig : m_signatures)
  195. {
  196. safeRelease(sig->m_rootSignature);
  197. deleteInstance(GrMemoryPool::getSingleton(), sig);
  198. }
  199. }
  200. Error RootSignatureFactory::getOrCreateRootSignature(const ShaderReflection& refl, RootSignature*& signature)
  201. {
  202. // Compute the hash
  203. const U64 hash = computeHash(&refl.m_descriptor, sizeof(refl.m_descriptor));
  204. // Search if exists
  205. LockGuard lock(m_mtx);
  206. for(RootSignature* s : m_signatures)
  207. {
  208. if(s->m_hash == hash)
  209. {
  210. signature = s;
  211. return Error::kNone;
  212. }
  213. }
  214. // Not found, create one
  215. GrDynamicArray<D3D12_ROOT_PARAMETER1> rootParameters;
  216. // Create the tables
  217. Array<GrDynamicArray<D3D12_DESCRIPTOR_RANGE1>, kMaxBindingsPerRegisterSpace * 2> tableRanges; // One per descriptor table
  218. U32 tableRangesCount = 0;
  219. for(U32 space = 0; space < kMaxRegisterSpaces; ++space)
  220. {
  221. if(refl.m_descriptor.m_bindingCounts[space] == 0)
  222. {
  223. continue;
  224. }
  225. GrDynamicArray<D3D12_DESCRIPTOR_RANGE1>& nonSamplerRanges = tableRanges[tableRangesCount++];
  226. GrDynamicArray<D3D12_DESCRIPTOR_RANGE1>& samplerRanges = tableRanges[tableRangesCount++];
  227. // Create the ranges
  228. for(U32 bindingIdx = 0; bindingIdx < refl.m_descriptor.m_bindingCounts[space]; ++bindingIdx)
  229. {
  230. const ShaderReflectionBinding& akBinding = refl.m_descriptor.m_bindings[space][bindingIdx];
  231. const Bool isSampler = (akBinding.m_type == DescriptorType::kSampler);
  232. akBinding.validate();
  233. D3D12_DESCRIPTOR_RANGE1& range = (isSampler) ? *samplerRanges.emplaceBack() : *nonSamplerRanges.emplaceBack();
  234. const HlslResourceType hlslRsrcType = descriptorTypeToHlslResourceType(akBinding.m_type);
  235. range = {};
  236. range.NumDescriptors = akBinding.m_arraySize;
  237. range.BaseShaderRegister = akBinding.m_registerBindingPoint;
  238. range.RegisterSpace = space;
  239. range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
  240. range.Flags = {};
  241. if(!isSampler)
  242. {
  243. range.Flags |= D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
  244. }
  245. if(hlslRsrcType == HlslResourceType::kCbv)
  246. {
  247. range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
  248. }
  249. else if(hlslRsrcType == HlslResourceType::kSampler)
  250. {
  251. range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
  252. }
  253. else if(hlslRsrcType == HlslResourceType::kSrv)
  254. {
  255. range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
  256. }
  257. else
  258. {
  259. ANKI_ASSERT(hlslRsrcType == HlslResourceType::kUav);
  260. range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
  261. }
  262. }
  263. // Add the root parameter
  264. if(nonSamplerRanges.getSize())
  265. {
  266. D3D12_ROOT_PARAMETER1& table = *rootParameters.emplaceBack();
  267. table = {};
  268. table.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
  269. table.DescriptorTable.NumDescriptorRanges = nonSamplerRanges.getSize();
  270. table.DescriptorTable.pDescriptorRanges = nonSamplerRanges.getBegin();
  271. table.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  272. }
  273. // Add the root parameter
  274. if(samplerRanges.getSize())
  275. {
  276. D3D12_ROOT_PARAMETER1& table = *rootParameters.emplaceBack();
  277. table = {};
  278. table.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
  279. table.DescriptorTable.NumDescriptorRanges = samplerRanges.getSize();
  280. table.DescriptorTable.pDescriptorRanges = samplerRanges.getBegin();
  281. table.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  282. }
  283. }
  284. // Root constants
  285. if(refl.m_descriptor.m_fastConstantsSize)
  286. {
  287. D3D12_ROOT_PARAMETER1& rootParam = *rootParameters.emplaceBack();
  288. rootParam = {};
  289. rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
  290. ANKI_ASSERT((refl.m_descriptor.m_fastConstantsSize % 4) == 0);
  291. rootParam.Constants.Num32BitValues = refl.m_descriptor.m_fastConstantsSize / 4;
  292. rootParam.Constants.RegisterSpace = 3000;
  293. rootParam.Constants.ShaderRegister = 0;
  294. rootParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  295. }
  296. D3D12_VERSIONED_ROOT_SIGNATURE_DESC verSigDesc = {};
  297. verSigDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;
  298. D3D12_ROOT_SIGNATURE_DESC1& sigDesc = verSigDesc.Desc_1_1;
  299. sigDesc.NumParameters = rootParameters.getSize();
  300. sigDesc.pParameters = rootParameters.getBegin();
  301. sigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED | D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
  302. ComPtr<ID3DBlob> signatureBlob;
  303. ComPtr<ID3DBlob> errorBlob;
  304. const HRESULT ret = D3D12SerializeVersionedRootSignature(&verSigDesc, &signatureBlob, &errorBlob);
  305. if(ret != S_OK)
  306. {
  307. const Char* errc = reinterpret_cast<const Char*>(errorBlob->GetBufferPointer());
  308. ANKI_D3D_LOGE("D3D12SerializeVersionedRootSignature() failed: %s", errc);
  309. }
  310. ID3D12RootSignature* dxRootSig;
  311. ANKI_D3D_CHECK(getDevice().CreateRootSignature(0, signatureBlob->GetBufferPointer(), signatureBlob->GetBufferSize(), IID_PPV_ARGS(&dxRootSig)));
  312. // Create the signature
  313. signature = newInstance<RootSignature>(GrMemoryPool::getSingleton());
  314. signature->m_hash = hash;
  315. signature->m_rootSignature = dxRootSig;
  316. U8 rootParameterIdx = 0;
  317. for(U32 spaceIdx = 0; spaceIdx < kMaxRegisterSpaces; ++spaceIdx)
  318. {
  319. if(refl.m_descriptor.m_bindingCounts[spaceIdx] == 0)
  320. {
  321. continue;
  322. }
  323. RootSignature::Space& outSpace = signature->m_spaces[spaceIdx];
  324. for(U32 bindingIdx = 0; bindingIdx < refl.m_descriptor.m_bindingCounts[spaceIdx]; ++bindingIdx)
  325. {
  326. const ShaderReflectionBinding& inBinding = refl.m_descriptor.m_bindings[spaceIdx][bindingIdx];
  327. inBinding.validate();
  328. const HlslResourceType hlslResourceType = descriptorTypeToHlslResourceType(inBinding.m_type);
  329. if(hlslResourceType < HlslResourceType::kSampler)
  330. {
  331. outSpace.m_cbvSrvUavCount += inBinding.m_arraySize;
  332. }
  333. else
  334. {
  335. outSpace.m_samplerCount += inBinding.m_arraySize;
  336. }
  337. for(U32 arrayIdx = 0; arrayIdx < inBinding.m_arraySize; ++arrayIdx)
  338. {
  339. const U32 idxInDescriptorsArr = inBinding.m_registerBindingPoint + arrayIdx;
  340. if(idxInDescriptorsArr >= signature->m_spaces[spaceIdx].m_descriptors[hlslResourceType].getSize())
  341. {
  342. signature->m_spaces[spaceIdx].m_descriptors[hlslResourceType].resize(idxInDescriptorsArr + 1); // Account for holes
  343. }
  344. RootSignature::Descriptor& outDescriptor = signature->m_spaces[spaceIdx].m_descriptors[hlslResourceType][idxInDescriptorsArr];
  345. outDescriptor.m_type = inBinding.m_type;
  346. if(outDescriptor.m_type == DescriptorType::kSrvStructuredBuffer || outDescriptor.m_type == DescriptorType::kUavStructuredBuffer)
  347. {
  348. ANKI_ASSERT(inBinding.m_d3dStructuredBufferStride < kMaxU16);
  349. outDescriptor.m_structuredBufferStride = inBinding.m_d3dStructuredBufferStride;
  350. }
  351. }
  352. }
  353. if(outSpace.m_cbvSrvUavCount)
  354. {
  355. outSpace.m_cbvSrvUavDescriptorTableRootParameterIdx = rootParameterIdx++;
  356. }
  357. if(outSpace.m_samplerCount)
  358. {
  359. outSpace.m_samplersDescriptorTableRootParameterIdx = rootParameterIdx++;
  360. }
  361. }
  362. signature->m_rootConstantsSize = refl.m_descriptor.m_fastConstantsSize;
  363. if(signature->m_rootConstantsSize)
  364. {
  365. signature->m_rootConstantsParameterIdx = rootParameterIdx++;
  366. }
  367. m_signatures.emplaceBack(signature);
  368. return Error::kNone;
  369. }
  370. void DescriptorState::init(StackMemoryPool* tempPool)
  371. {
  372. for(auto& s : m_spaces)
  373. {
  374. for(auto& d : s.m_descriptors)
  375. {
  376. d = DynamicArray<Descriptor, MemoryPoolPtrWrapper<StackMemoryPool>>(tempPool);
  377. }
  378. }
  379. }
  380. void DescriptorState::bindRootSignature(const RootSignature* rootSignature, Bool isCompute)
  381. {
  382. ANKI_ASSERT(rootSignature);
  383. if(rootSignature == m_rootSignature)
  384. {
  385. ANKI_ASSERT(m_rootSignatureNeedsRebinding == false);
  386. return;
  387. }
  388. for(U32 space = 0; space < kMaxRegisterSpaces; ++space)
  389. {
  390. if(!rootSignature->m_spaces[space].isEmpty())
  391. {
  392. m_spaces[space].m_cbvSrvUavDirty = true;
  393. m_spaces[space].m_samplersDirty = true;
  394. }
  395. }
  396. m_rootSignature = rootSignature;
  397. m_rootSignatureNeedsRebinding = true;
  398. m_rootSignatureIsCompute = isCompute;
  399. }
  400. void DescriptorState::flush(ID3D12GraphicsCommandList& cmdList)
  401. {
  402. // Rebind the root signature
  403. ANKI_ASSERT(m_rootSignature);
  404. const Bool rootSignatureNeedsRebinding = m_rootSignatureNeedsRebinding;
  405. if(m_rootSignatureNeedsRebinding)
  406. {
  407. if(m_rootSignatureIsCompute)
  408. {
  409. cmdList.SetComputeRootSignature(m_rootSignature->m_rootSignature);
  410. }
  411. else
  412. {
  413. cmdList.SetGraphicsRootSignature(m_rootSignature->m_rootSignature);
  414. }
  415. m_rootSignatureNeedsRebinding = false;
  416. }
  417. // Populate the heaps
  418. for(U32 spaceIdx = 0; spaceIdx < kMaxRegisterSpaces; ++spaceIdx)
  419. {
  420. const RootSignature::Space& rootSignatureSpace = m_rootSignature->m_spaces[spaceIdx];
  421. if(rootSignatureSpace.isEmpty())
  422. {
  423. continue;
  424. }
  425. Space& stateSpace = m_spaces[spaceIdx];
  426. Bool skip = true;
  427. // Allocate descriptor memory (doesn't include holes)
  428. if(stateSpace.m_cbvSrvUavDirty && rootSignatureSpace.m_cbvSrvUavCount)
  429. {
  430. stateSpace.m_cbvSrvUavHeapHandle = DescriptorFactory::getSingleton().allocateTransient(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
  431. rootSignatureSpace.m_cbvSrvUavCount, true);
  432. skip = false;
  433. }
  434. if(stateSpace.m_samplersDirty && rootSignatureSpace.m_samplerCount)
  435. {
  436. stateSpace.m_samplerHeapHandle =
  437. DescriptorFactory::getSingleton().allocateTransient(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, rootSignatureSpace.m_samplerCount, true);
  438. skip = false;
  439. }
  440. if(skip)
  441. {
  442. continue;
  443. }
  444. // Populate descriptors
  445. DescriptorHeapHandle cbvSrvUavHeapOffset = stateSpace.m_cbvSrvUavHeapHandle;
  446. DescriptorHeapHandle samplerHeapOffset = stateSpace.m_samplerHeapHandle;
  447. for(HlslResourceType hlslResourceType : EnumIterable<HlslResourceType>())
  448. {
  449. for(U32 registerBinding = 0; registerBinding < rootSignatureSpace.m_descriptors[hlslResourceType].getSize(); ++registerBinding)
  450. {
  451. const RootSignature::Descriptor& inDescriptor = rootSignatureSpace.m_descriptors[hlslResourceType][registerBinding];
  452. if(inDescriptor.m_type == DescriptorType::kCount)
  453. {
  454. // Skip a hole
  455. continue;
  456. }
  457. const Descriptor& outDescriptor = stateSpace.m_descriptors[hlslResourceType][registerBinding];
  458. ANKI_ASSERT(inDescriptor.m_type == outDescriptor.m_type && "Have bound the wrong thing");
  459. ANKI_ASSERT(descriptorTypeToHlslResourceType(inDescriptor.m_type) == hlslResourceType);
  460. if(inDescriptor.m_type == DescriptorType::kConstantBuffer)
  461. {
  462. // ConstantBuffer
  463. ANKI_ASSERT(!outDescriptor.m_isHandle);
  464. const BufferView& view = outDescriptor.m_bufferView;
  465. D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {};
  466. desc.BufferLocation = view.m_resource->GetGPUVirtualAddress() + view.m_offset;
  467. desc.SizeInBytes = U32(getAlignedRoundUp(256, view.m_range));
  468. getDevice().CreateConstantBufferView(&desc, cbvSrvUavHeapOffset.getCpuOffset());
  469. }
  470. else if(inDescriptor.m_type == DescriptorType::kSrvTexture || inDescriptor.m_type == DescriptorType::kUavTexture)
  471. {
  472. // Texture2D or RWTexture2D
  473. ANKI_ASSERT(outDescriptor.m_isHandle);
  474. getDevice().CopyDescriptorsSimple(1, cbvSrvUavHeapOffset.getCpuOffset(), outDescriptor.m_heapOffset,
  475. D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  476. }
  477. else if(inDescriptor.m_type == DescriptorType::kSampler)
  478. {
  479. // SamplerState
  480. ANKI_ASSERT(outDescriptor.m_isHandle);
  481. getDevice().CopyDescriptorsSimple(1, samplerHeapOffset.getCpuOffset(), outDescriptor.m_heapOffset,
  482. D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
  483. }
  484. else if(inDescriptor.m_type == DescriptorType::kUavByteAddressBuffer)
  485. {
  486. // RWByteAddressBuffer
  487. ANKI_ASSERT(!outDescriptor.m_isHandle);
  488. const BufferView& view = outDescriptor.m_bufferView;
  489. D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  490. uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
  491. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
  492. uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
  493. ANKI_ASSERT((view.m_offset % sizeof(U32)) == 0);
  494. uavDesc.Buffer.FirstElement = view.m_offset / sizeof(U32);
  495. ANKI_ASSERT((view.m_range % inDescriptor.m_structuredBufferStride) == 0);
  496. ANKI_ASSERT((view.m_range % sizeof(U32)) == 0);
  497. uavDesc.Buffer.NumElements = U32(view.m_range / sizeof(U32));
  498. getDevice().CreateUnorderedAccessView(view.m_resource, nullptr, &uavDesc, cbvSrvUavHeapOffset.getCpuOffset());
  499. }
  500. else if(inDescriptor.m_type == DescriptorType::kUavStructuredBuffer)
  501. {
  502. // RWStructuredBuffer
  503. ANKI_ASSERT(!outDescriptor.m_isHandle);
  504. const BufferView& view = outDescriptor.m_bufferView;
  505. D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  506. uavDesc.Format = DXGI_FORMAT_UNKNOWN;
  507. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
  508. ANKI_ASSERT((view.m_offset % inDescriptor.m_structuredBufferStride) == 0);
  509. uavDesc.Buffer.FirstElement = view.m_offset / inDescriptor.m_structuredBufferStride;
  510. ANKI_ASSERT((view.m_range % inDescriptor.m_structuredBufferStride) == 0);
  511. uavDesc.Buffer.NumElements = U32(view.m_range / inDescriptor.m_structuredBufferStride);
  512. uavDesc.Buffer.StructureByteStride = inDescriptor.m_structuredBufferStride;
  513. getDevice().CreateUnorderedAccessView(view.m_resource, nullptr, &uavDesc, cbvSrvUavHeapOffset.getCpuOffset());
  514. }
  515. else if(inDescriptor.m_type == DescriptorType::kSrvByteAddressBuffer)
  516. {
  517. // ByteAddressBuffer
  518. ANKI_ASSERT(!outDescriptor.m_isHandle);
  519. const BufferView& view = outDescriptor.m_bufferView;
  520. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  521. srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
  522. srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
  523. srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
  524. srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  525. ANKI_ASSERT((view.m_offset % sizeof(U32)) == 0);
  526. srvDesc.Buffer.FirstElement = view.m_offset / sizeof(U32);
  527. ANKI_ASSERT((view.m_range % inDescriptor.m_structuredBufferStride) == 0);
  528. ANKI_ASSERT((view.m_range % sizeof(U32)) == 0);
  529. srvDesc.Buffer.NumElements = U32(view.m_range / sizeof(U32));
  530. getDevice().CreateShaderResourceView(view.m_resource, &srvDesc, cbvSrvUavHeapOffset.getCpuOffset());
  531. }
  532. else if(inDescriptor.m_type == DescriptorType::kSrvStructuredBuffer)
  533. {
  534. // StructuredBuffer
  535. ANKI_ASSERT(!outDescriptor.m_isHandle);
  536. const BufferView& view = outDescriptor.m_bufferView;
  537. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  538. srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  539. srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
  540. srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  541. ANKI_ASSERT((view.m_offset % inDescriptor.m_structuredBufferStride) == 0);
  542. srvDesc.Buffer.FirstElement = view.m_offset / inDescriptor.m_structuredBufferStride;
  543. ANKI_ASSERT((view.m_range % inDescriptor.m_structuredBufferStride) == 0);
  544. srvDesc.Buffer.NumElements = U32(view.m_range / inDescriptor.m_structuredBufferStride);
  545. srvDesc.Buffer.StructureByteStride = inDescriptor.m_structuredBufferStride;
  546. getDevice().CreateShaderResourceView(view.m_resource, &srvDesc, cbvSrvUavHeapOffset.getCpuOffset());
  547. }
  548. else if(inDescriptor.m_type == DescriptorType::kUavTexelBuffer)
  549. {
  550. // RWBuffer
  551. ANKI_ASSERT(!outDescriptor.m_isHandle);
  552. const BufferView& view = outDescriptor.m_bufferView;
  553. D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  554. uavDesc.Format = convertFormat(view.m_format);
  555. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
  556. const U32 texelSize = getFormatInfo(Format(view.m_format)).m_texelSize;
  557. ANKI_ASSERT((view.m_offset % texelSize) == 0);
  558. uavDesc.Buffer.FirstElement = view.m_offset / texelSize;
  559. ANKI_ASSERT((view.m_range % texelSize) == 0);
  560. uavDesc.Buffer.NumElements = U32(view.m_range / texelSize);
  561. getDevice().CreateUnorderedAccessView(view.m_resource, nullptr, &uavDesc, cbvSrvUavHeapOffset.getCpuOffset());
  562. }
  563. else if(inDescriptor.m_type == DescriptorType::kSrvTexelBuffer)
  564. {
  565. // Buffer
  566. ANKI_ASSERT(!outDescriptor.m_isHandle);
  567. const BufferView& view = outDescriptor.m_bufferView;
  568. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  569. srvDesc.Format = convertFormat(view.m_format);
  570. srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
  571. srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  572. const U32 texelSize = getFormatInfo(Format(view.m_format)).m_texelSize;
  573. ANKI_ASSERT((view.m_offset % texelSize) == 0);
  574. srvDesc.Buffer.FirstElement = view.m_offset / texelSize;
  575. ANKI_ASSERT((view.m_range % texelSize) == 0);
  576. srvDesc.Buffer.NumElements = U32(view.m_range / texelSize);
  577. getDevice().CreateShaderResourceView(view.m_resource, &srvDesc, cbvSrvUavHeapOffset.getCpuOffset());
  578. }
  579. else
  580. {
  581. ANKI_ASSERT(!"TODO");
  582. }
  583. if(hlslResourceType == HlslResourceType::kSampler)
  584. {
  585. samplerHeapOffset.increment(1);
  586. }
  587. else
  588. {
  589. cbvSrvUavHeapOffset.increment(1);
  590. }
  591. }
  592. }
  593. }
  594. // Bind root parameters
  595. for(U32 spaceIdx = 0; spaceIdx < kMaxRegisterSpaces; ++spaceIdx)
  596. {
  597. const RootSignature::Space& rootSignatureSpace = m_rootSignature->m_spaces[spaceIdx];
  598. if(rootSignatureSpace.isEmpty())
  599. {
  600. continue;
  601. }
  602. Space& stateSpace = m_spaces[spaceIdx];
  603. if(rootSignatureSpace.m_cbvSrvUavCount && (stateSpace.m_cbvSrvUavDirty || rootSignatureNeedsRebinding))
  604. {
  605. ANKI_ASSERT(rootSignatureSpace.m_cbvSrvUavDescriptorTableRootParameterIdx < kMaxU8);
  606. if(m_rootSignatureIsCompute)
  607. {
  608. cmdList.SetComputeRootDescriptorTable(rootSignatureSpace.m_cbvSrvUavDescriptorTableRootParameterIdx,
  609. stateSpace.m_cbvSrvUavHeapHandle.getGpuOffset());
  610. }
  611. else
  612. {
  613. cmdList.SetGraphicsRootDescriptorTable(rootSignatureSpace.m_cbvSrvUavDescriptorTableRootParameterIdx,
  614. stateSpace.m_cbvSrvUavHeapHandle.getGpuOffset());
  615. }
  616. stateSpace.m_cbvSrvUavDirty = false;
  617. }
  618. if(rootSignatureSpace.m_descriptors[HlslResourceType::kSampler].getSize() && (stateSpace.m_samplersDirty || rootSignatureNeedsRebinding))
  619. {
  620. ANKI_ASSERT(rootSignatureSpace.m_samplersDescriptorTableRootParameterIdx < kMaxU8);
  621. if(m_rootSignatureIsCompute)
  622. {
  623. cmdList.SetComputeRootDescriptorTable(rootSignatureSpace.m_samplersDescriptorTableRootParameterIdx,
  624. stateSpace.m_samplerHeapHandle.getGpuOffset());
  625. }
  626. else
  627. {
  628. cmdList.SetGraphicsRootDescriptorTable(rootSignatureSpace.m_samplersDescriptorTableRootParameterIdx,
  629. stateSpace.m_samplerHeapHandle.getGpuOffset());
  630. }
  631. stateSpace.m_samplersDirty = false;
  632. }
  633. }
  634. // Set root constants
  635. if(m_rootSignature->m_rootConstantsSize && (m_rootConstsDirty || rootSignatureNeedsRebinding))
  636. {
  637. ANKI_ASSERT(m_rootSignature->m_rootConstantsParameterIdx != kMaxU8);
  638. if(m_rootSignatureIsCompute)
  639. {
  640. cmdList.SetComputeRoot32BitConstants(m_rootSignature->m_rootConstantsParameterIdx, m_rootConstSize / sizeof(U32), m_rootConsts.getBegin(),
  641. 0);
  642. }
  643. else
  644. {
  645. cmdList.SetGraphicsRoot32BitConstants(m_rootSignature->m_rootConstantsParameterIdx, m_rootConstSize / sizeof(U32),
  646. m_rootConsts.getBegin(), 0);
  647. }
  648. m_rootConstsDirty = false;
  649. }
  650. }
  651. } // end namespace anki