DX12Shader.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. #include "DX12Shader.h"
  2. #include "DX12Texture.h"
  3. #include "DX12TLAS.h"
  4. #include "Logging.h"
  5. using namespace Framework;
  6. Framework::DX12ShaderSignature::DX12ShaderSignature()
  7. : ReferenceCounter(),
  8. signature(0),
  9. changed(1)
  10. {}
  11. Framework::DX12ShaderSignature::~DX12ShaderSignature()
  12. {
  13. if (signature)
  14. {
  15. signature->Release();
  16. }
  17. }
  18. void Framework::DX12ShaderSignature::addRegisterUsageLinkedToShaderBindingTable(
  19. DX12ShaderRegister registerType, int registerIndex, int spaceIndex)
  20. {
  21. addRegisterUsageLinkedToDescriptorHeap(
  22. -1, registerType, registerIndex, spaceIndex);
  23. }
  24. void Framework::DX12ShaderSignature::addRegisterUsageLinkedToDescriptorHeap(
  25. int descriptorHeapIndex,
  26. DX12ShaderRegister registerType,
  27. int registerIndex,
  28. int spaceIndex)
  29. {
  30. // register usages sould be sorted by registerType -> spaceIndex ->
  31. // registerIndex
  32. ArrayIterator<DX12ShaderRegisterUsage> it = registerUsages.begin();
  33. bool found = 0;
  34. while (it)
  35. {
  36. const DX12ShaderRegisterUsage& usage = it.val();
  37. if (usage.registerType > registerType)
  38. {
  39. found = 1;
  40. break;
  41. }
  42. if (usage.registerType == registerType)
  43. {
  44. if (usage.spaceIndex > spaceIndex)
  45. {
  46. found = 1;
  47. break;
  48. }
  49. if (usage.spaceIndex == spaceIndex)
  50. {
  51. if (usage.registerIndex >= registerIndex)
  52. {
  53. found = 1;
  54. break;
  55. }
  56. }
  57. }
  58. ++it;
  59. }
  60. if (found)
  61. {
  62. if (it.val().registerIndex == registerIndex)
  63. {
  64. Logging::error()
  65. << "Duplicate register usage in root signature: "
  66. << registerType << " " << registerIndex << " " << spaceIndex;
  67. return;
  68. }
  69. it.addBefore(
  70. {registerType, registerIndex, spaceIndex, descriptorHeapIndex});
  71. }
  72. else
  73. {
  74. registerUsages.add(
  75. {registerType, registerIndex, spaceIndex, descriptorHeapIndex});
  76. }
  77. changed = 1;
  78. }
  79. void Framework::DX12ShaderSignature::createSignature(ID3D12Device5* zDevice,
  80. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfnD3D12SerializeRootSignature)
  81. {
  82. if (!changed)
  83. {
  84. return;
  85. }
  86. changed = 0;
  87. if (signature)
  88. {
  89. signature->Release();
  90. signature = 0;
  91. }
  92. D3D12_ROOT_PARAMETER* descriptorTable
  93. = new D3D12_ROOT_PARAMETER[registerUsages.getEntryCount()];
  94. D3D12_DESCRIPTOR_RANGE* descriptorRanges
  95. = new D3D12_DESCRIPTOR_RANGE[registerUsages.getEntryCount()];
  96. ArrayIterator<DX12ShaderRegisterUsage> it = registerUsages.begin();
  97. int index = 0;
  98. while (it)
  99. {
  100. const auto& usage = it.val();
  101. if (usage.descriptorHeapIndex >= 0)
  102. {
  103. descriptorTable[index].ParameterType
  104. = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
  105. descriptorTable[index].ShaderVisibility
  106. = D3D12_SHADER_VISIBILITY_ALL;
  107. descriptorTable[index].DescriptorTable.NumDescriptorRanges
  108. = registerUsages.getEntryCount();
  109. D3D12_DESCRIPTOR_RANGE* range = &descriptorRanges[index];
  110. switch (usage.registerType)
  111. {
  112. case DX12_SHADER_REGISTER_B_CONST_BUFFER:
  113. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
  114. break;
  115. case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
  116. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
  117. break;
  118. case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
  119. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
  120. break;
  121. default:
  122. Logging::error() << "Unknown register type for root signature: "
  123. << usage.registerType;
  124. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
  125. }
  126. ArrayIterator<DX12ShaderRegisterUsage> next = it.next();
  127. int size = 1;
  128. while (next && next.val().registerType == usage.registerType
  129. && next.val().spaceIndex == usage.spaceIndex
  130. && next.val().registerIndex == usage.registerIndex + size
  131. && next.val().descriptorHeapIndex
  132. == usage.descriptorHeapIndex + size)
  133. {
  134. ++size;
  135. it = next;
  136. ++next;
  137. }
  138. range->NumDescriptors = size;
  139. range->BaseShaderRegister = usage.registerIndex;
  140. range->RegisterSpace = usage.spaceIndex;
  141. range->OffsetInDescriptorsFromTableStart
  142. = usage.descriptorHeapIndex;
  143. descriptorTable[index].DescriptorTable.pDescriptorRanges = range;
  144. }
  145. else
  146. {
  147. switch (usage.registerType)
  148. {
  149. case DX12_SHADER_REGISTER_B_CONST_BUFFER:
  150. descriptorTable[index].ParameterType
  151. = D3D12_ROOT_PARAMETER_TYPE_CBV;
  152. break;
  153. case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
  154. descriptorTable[index].ParameterType
  155. = D3D12_ROOT_PARAMETER_TYPE_SRV;
  156. break;
  157. case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
  158. descriptorTable[index].ParameterType
  159. = D3D12_ROOT_PARAMETER_TYPE_UAV;
  160. break;
  161. }
  162. descriptorTable[index].ShaderVisibility
  163. = D3D12_SHADER_VISIBILITY_ALL;
  164. descriptorTable[index].Descriptor.ShaderRegister
  165. = usage.registerIndex;
  166. descriptorTable[index].Descriptor.RegisterSpace = usage.spaceIndex;
  167. }
  168. ++it;
  169. ++index;
  170. }
  171. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  172. rootDesc.NumParameters = index;
  173. rootDesc.pParameters = descriptorTable;
  174. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
  175. ID3DBlob* pSigBlob = 0;
  176. ID3DBlob* pErrorBlob = 0;
  177. HRESULT hr = pfnD3D12SerializeRootSignature(
  178. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  179. if (pSigBlob)
  180. {
  181. zDevice->CreateRootSignature(0,
  182. pSigBlob->GetBufferPointer(),
  183. pSigBlob->GetBufferSize(),
  184. __uuidof(ID3D12RootSignature),
  185. (void**)&signature);
  186. pSigBlob->Release();
  187. }
  188. if (pErrorBlob)
  189. {
  190. std::string errorMessage(
  191. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  192. pErrorBlob->GetBufferSize());
  193. Logging::error() << "Failed to serialize root signature: "
  194. << errorMessage;
  195. pErrorBlob->Release();
  196. }
  197. delete[] descriptorRanges;
  198. }
  199. ID3D12RootSignature* Framework::DX12ShaderSignature::zSignature() const
  200. {
  201. return signature;
  202. }
  203. const Array<DX12ShaderRegisterUsage>&
  204. Framework::DX12ShaderSignature::getRegisterUsages() const
  205. {
  206. return registerUsages;
  207. }
  208. Framework::DX12ShaderFunction::DX12ShaderFunction(
  209. const Text& functionName, DX12ShaderSignature* signature)
  210. : ReferenceCounter(),
  211. functionName(functionName),
  212. signature(signature),
  213. exportDesc(new D3D12_EXPORT_DESC())
  214. {
  215. wchar_t* wc = new wchar_t[functionName.getLength() + 1];
  216. mbtowc(wc, functionName.getText(), functionName.getLength() + 1);
  217. wc[functionName.getLength()] = 0;
  218. exportDesc->Name = wc;
  219. exportDesc->ExportToRename = 0;
  220. exportDesc->Flags = D3D12_EXPORT_FLAG_NONE;
  221. }
  222. Framework::DX12ShaderFunction::~DX12ShaderFunction()
  223. {
  224. signature->release();
  225. delete[] exportDesc->Name;
  226. delete exportDesc;
  227. }
  228. const Text& Framework::DX12ShaderFunction::getFunctionName() const
  229. {
  230. return functionName;
  231. }
  232. DX12ShaderSignature* Framework::DX12ShaderFunction::zSignature() const
  233. {
  234. return signature;
  235. }
  236. D3D12_EXPORT_DESC* Framework::DX12ShaderFunction::zExportDesc() const
  237. {
  238. return exportDesc;
  239. }
  240. Framework::DX12Shader::DX12Shader(const char* shaderBytes, int shaderBytesSize)
  241. : ReferenceCounter(),
  242. shaderBytes(shaderBytes),
  243. shaderBytesSize(shaderBytesSize),
  244. libraryDesc(new D3D12_DXIL_LIBRARY_DESC())
  245. {
  246. libraryDesc->DXILLibrary.pShaderBytecode = shaderBytes;
  247. libraryDesc->DXILLibrary.BytecodeLength = shaderBytesSize;
  248. libraryDesc->NumExports = 0;
  249. libraryDesc->pExports = 0;
  250. }
  251. Framework::DX12Shader::~DX12Shader()
  252. {
  253. delete[] libraryDesc->pExports;
  254. delete libraryDesc;
  255. }
  256. void Framework::DX12Shader::addFunction(DX12ShaderFunction* function)
  257. {
  258. functions.add(function);
  259. }
  260. int Framework::DX12Shader::getShaderBytesSize() const
  261. {
  262. return shaderBytesSize;
  263. }
  264. const char* Framework::DX12Shader::getShaderBytes() const
  265. {
  266. return shaderBytes;
  267. }
  268. const RCArray<DX12ShaderFunction>& Framework::DX12Shader::getFunctions() const
  269. {
  270. return functions;
  271. }
  272. D3D12_DXIL_LIBRARY_DESC* Framework::DX12Shader::zLibraryDesc() const
  273. {
  274. if (libraryDesc->NumExports != functions.getEntryCount())
  275. {
  276. delete[] libraryDesc->pExports;
  277. libraryDesc->NumExports = functions.getEntryCount();
  278. D3D12_EXPORT_DESC* pExports
  279. = new D3D12_EXPORT_DESC[functions.getEntryCount()];
  280. int index = 0;
  281. for (const auto& function : functions)
  282. {
  283. memcpy(pExports + index,
  284. function->zExportDesc(),
  285. sizeof(D3D12_EXPORT_DESC));
  286. index++;
  287. }
  288. libraryDesc->pExports = pExports;
  289. }
  290. return libraryDesc;
  291. }
  292. Framework::DX12ShaderHitGroup::DX12ShaderHitGroup(const Text name)
  293. : ReferenceCounter(),
  294. name(name),
  295. closestHitShaderFunction(0),
  296. anyHitShaderFunction(0),
  297. intersectionShaderFunction(0),
  298. payloadSize(0),
  299. attributeSize(0),
  300. hitGroupDesc(new D3D12_HIT_GROUP_DESC())
  301. {
  302. wchar_t* wc = new wchar_t[name.getLength() + 1];
  303. mbtowc(wc, name.getText(), name.getLength() + 1);
  304. wc[name.getLength()] = 0;
  305. hitGroupDesc->HitGroupExport = wc;
  306. hitGroupDesc->IntersectionShaderImport = 0;
  307. hitGroupDesc->AnyHitShaderImport = 0;
  308. hitGroupDesc->ClosestHitShaderImport = 0;
  309. }
  310. Framework::DX12ShaderHitGroup::~DX12ShaderHitGroup()
  311. {
  312. delete[] hitGroupDesc->HitGroupExport;
  313. delete hitGroupDesc;
  314. if (closestHitShaderFunction)
  315. {
  316. closestHitShaderFunction->release();
  317. }
  318. if (anyHitShaderFunction)
  319. {
  320. anyHitShaderFunction->release();
  321. }
  322. if (intersectionShaderFunction)
  323. {
  324. intersectionShaderFunction->release();
  325. }
  326. }
  327. void Framework::DX12ShaderHitGroup::setClosestHitShaderFunction(
  328. DX12ShaderFunction* closestHitShaderFunction)
  329. {
  330. if (anyHitShaderFunction
  331. && anyHitShaderFunction->zSignature()
  332. != closestHitShaderFunction->zSignature())
  333. {
  334. Logging::error()
  335. << "Any-hit shader function and closest-hit shader "
  336. "function must have the same root signature when they are "
  337. "combined in the same hit group. HitGroup Name: '"
  338. << name << "' Any Hit Shader Function: '"
  339. << anyHitShaderFunction->getFunctionName().getText()
  340. << "' Closest Hit Shader Function: '"
  341. << closestHitShaderFunction->getFunctionName().getText() << "'";
  342. throw std::runtime_error("Incompatible root signatures in hit group");
  343. }
  344. if (intersectionShaderFunction
  345. && intersectionShaderFunction->zSignature()
  346. != closestHitShaderFunction->zSignature())
  347. {
  348. Logging::error()
  349. << "Intersection shader function and closest-hit shader "
  350. "function must have the same root signature when they are "
  351. "combined in the same hit group. HitGroup Name: '"
  352. << name << "' Intersection Shader Function: '"
  353. << intersectionShaderFunction->getFunctionName().getText()
  354. << "' Closest Hit Shader Function: '"
  355. << closestHitShaderFunction->getFunctionName().getText() << "'";
  356. throw std::runtime_error("Incompatible root signatures in hit group");
  357. }
  358. if (this->closestHitShaderFunction)
  359. {
  360. this->closestHitShaderFunction->release();
  361. }
  362. this->closestHitShaderFunction = closestHitShaderFunction;
  363. hitGroupDesc->ClosestHitShaderImport = 0;
  364. if (closestHitShaderFunction)
  365. {
  366. hitGroupDesc->ClosestHitShaderImport
  367. = closestHitShaderFunction->zExportDesc()->Name;
  368. }
  369. }
  370. void Framework::DX12ShaderHitGroup::setAnyHitShaderFunction(
  371. DX12ShaderFunction* anyHitShaderFunction)
  372. {
  373. if (closestHitShaderFunction
  374. && closestHitShaderFunction->zSignature()
  375. != anyHitShaderFunction->zSignature())
  376. {
  377. Logging::error()
  378. << "Any-hit shader function and closest-hit shader "
  379. "function must have the same root signature when they are "
  380. "combined in the same hit group. HitGroup Name: '"
  381. << name << "' Any Hit Shader Function: '"
  382. << anyHitShaderFunction->getFunctionName().getText()
  383. << "' Closest Hit Shader Function: '"
  384. << closestHitShaderFunction->getFunctionName().getText() << "'";
  385. throw std::runtime_error("Incompatible root signatures in hit group");
  386. }
  387. if (intersectionShaderFunction
  388. && intersectionShaderFunction->zSignature()
  389. != anyHitShaderFunction->zSignature())
  390. {
  391. Logging::error()
  392. << "Intersection shader function and any-hit shader "
  393. "function must have the same root signature when they are "
  394. "combined in the same hit group. HitGroup Name: '"
  395. << name << "' Intersection Shader Function: '"
  396. << intersectionShaderFunction->getFunctionName().getText()
  397. << "' Any Hit Shader Function: '"
  398. << anyHitShaderFunction->getFunctionName().getText() << "'";
  399. throw std::runtime_error("Incompatible root signatures in hit group");
  400. }
  401. if (this->anyHitShaderFunction)
  402. {
  403. this->anyHitShaderFunction->release();
  404. }
  405. this->anyHitShaderFunction = anyHitShaderFunction;
  406. hitGroupDesc->AnyHitShaderImport = 0;
  407. if (anyHitShaderFunction)
  408. {
  409. hitGroupDesc->AnyHitShaderImport
  410. = anyHitShaderFunction->zExportDesc()->Name;
  411. }
  412. }
  413. void Framework::DX12ShaderHitGroup::setIntersectionShaderFunction(
  414. DX12ShaderFunction* intersectionShaderFunction)
  415. {
  416. if (closestHitShaderFunction
  417. && closestHitShaderFunction->zSignature()
  418. != intersectionShaderFunction->zSignature())
  419. {
  420. Logging::error()
  421. << "Intersection shader function and closest-hit shader "
  422. "function must have the same root signature when they are "
  423. "combined in the same hit group. HitGroup Name: '"
  424. << name << "' Intersection Shader Function: '"
  425. << intersectionShaderFunction->getFunctionName().getText()
  426. << "' Closest Hit Shader Function: '"
  427. << closestHitShaderFunction->getFunctionName().getText() << "'";
  428. throw std::runtime_error("Incompatible root signatures in hit group");
  429. }
  430. if (anyHitShaderFunction
  431. && anyHitShaderFunction->zSignature()
  432. != intersectionShaderFunction->zSignature())
  433. {
  434. Logging::error()
  435. << "Intersection shader function and any-hit shader "
  436. "function must have the same root signature when they are "
  437. "combined in the same hit group. HitGroup Name: '"
  438. << name << "' Intersection Shader Function: '"
  439. << intersectionShaderFunction->getFunctionName().getText()
  440. << "' Any Hit Shader Function: '"
  441. << anyHitShaderFunction->getFunctionName().getText() << "'";
  442. throw std::runtime_error("Incompatible root signatures in hit group");
  443. }
  444. if (this->intersectionShaderFunction)
  445. {
  446. this->intersectionShaderFunction->release();
  447. }
  448. this->intersectionShaderFunction = intersectionShaderFunction;
  449. hitGroupDesc->IntersectionShaderImport = 0;
  450. if (intersectionShaderFunction)
  451. {
  452. hitGroupDesc->IntersectionShaderImport
  453. = intersectionShaderFunction->zExportDesc()->Name;
  454. }
  455. }
  456. void Framework::DX12ShaderHitGroup::setPayloadSize(int payloadSize)
  457. {
  458. this->payloadSize = payloadSize;
  459. }
  460. void Framework::DX12ShaderHitGroup::setAttributeSize(int attributeSize)
  461. {
  462. this->attributeSize = attributeSize;
  463. }
  464. const Text& Framework::DX12ShaderHitGroup::getName() const
  465. {
  466. return name;
  467. }
  468. DX12ShaderFunction*
  469. Framework::DX12ShaderHitGroup::zClosestHitShaderFunction() const
  470. {
  471. return closestHitShaderFunction;
  472. }
  473. DX12ShaderFunction* Framework::DX12ShaderHitGroup::zAnyHitShaderFunction() const
  474. {
  475. return anyHitShaderFunction;
  476. }
  477. DX12ShaderFunction*
  478. Framework::DX12ShaderHitGroup::zIntersectionShaderFunction() const
  479. {
  480. return intersectionShaderFunction;
  481. }
  482. int Framework::DX12ShaderHitGroup::getPayloadSize() const
  483. {
  484. return payloadSize;
  485. }
  486. int Framework::DX12ShaderHitGroup::getAttributeSize() const
  487. {
  488. return attributeSize;
  489. }
  490. D3D12_HIT_GROUP_DESC* Framework::DX12ShaderHitGroup::zHitGroupDesc() const
  491. {
  492. if (hitGroupDesc->IntersectionShaderImport)
  493. {
  494. hitGroupDesc->Type = D3D12_HIT_GROUP_TYPE_PROCEDURAL_PRIMITIVE;
  495. }
  496. else
  497. {
  498. hitGroupDesc->Type = D3D12_HIT_GROUP_TYPE_TRIANGLES;
  499. }
  500. return hitGroupDesc;
  501. }
  502. Framework::DX12Pipeline::DX12Pipeline()
  503. : ReferenceCounter(),
  504. emptyGlobalRootSignature(0),
  505. emptyLocalRootSignature(0),
  506. pipelineState(0),
  507. maxRecursionDepth(0)
  508. {}
  509. Framework::DX12Pipeline::~DX12Pipeline()
  510. {
  511. if (emptyGlobalRootSignature)
  512. {
  513. emptyGlobalRootSignature->Release();
  514. }
  515. if (emptyLocalRootSignature)
  516. {
  517. emptyLocalRootSignature->Release();
  518. }
  519. if (pipelineState)
  520. {
  521. pipelineState->Release();
  522. }
  523. }
  524. void Framework::DX12Pipeline::addShader(DX12Shader* shader)
  525. {
  526. shaders.add(shader);
  527. }
  528. void Framework::DX12Pipeline::addHitGroup(DX12ShaderHitGroup* hitGroup)
  529. {
  530. hitGroups.add(hitGroup);
  531. }
  532. void Framework::DX12Pipeline::setMaxRecursionDepth(int maxRecursionDepth)
  533. {
  534. this->maxRecursionDepth = maxRecursionDepth;
  535. }
  536. void Framework::DX12Pipeline::createPipelineState(ID3D12Device5* zDevice,
  537. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfnD3D12SerializeRootSignature)
  538. {
  539. if (!emptyGlobalRootSignature)
  540. {
  541. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  542. rootDesc.NumParameters = 0;
  543. rootDesc.pParameters = 0;
  544. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
  545. ID3DBlob* pSigBlob = 0;
  546. ID3DBlob* pErrorBlob = 0;
  547. HRESULT hr = pfnD3D12SerializeRootSignature(
  548. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  549. if (pSigBlob)
  550. {
  551. zDevice->CreateRootSignature(0,
  552. pSigBlob->GetBufferPointer(),
  553. pSigBlob->GetBufferSize(),
  554. __uuidof(ID3D12RootSignature),
  555. (void**)&emptyGlobalRootSignature);
  556. pSigBlob->Release();
  557. }
  558. if (pErrorBlob)
  559. {
  560. std::string errorMessage(
  561. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  562. pErrorBlob->GetBufferSize());
  563. Logging::error()
  564. << "Failed to serialize empty root signature: " << errorMessage;
  565. pErrorBlob->Release();
  566. }
  567. }
  568. if (!emptyLocalRootSignature)
  569. {
  570. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  571. rootDesc.NumParameters = 0;
  572. rootDesc.pParameters = 0;
  573. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
  574. ID3DBlob* pSigBlob = 0;
  575. ID3DBlob* pErrorBlob = 0;
  576. HRESULT hr = pfnD3D12SerializeRootSignature(
  577. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  578. if (pSigBlob)
  579. {
  580. zDevice->CreateRootSignature(0,
  581. pSigBlob->GetBufferPointer(),
  582. pSigBlob->GetBufferSize(),
  583. __uuidof(ID3D12RootSignature),
  584. (void**)&emptyGlobalRootSignature);
  585. pSigBlob->Release();
  586. }
  587. if (pErrorBlob)
  588. {
  589. std::string errorMessage(
  590. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  591. pErrorBlob->GetBufferSize());
  592. Logging::error()
  593. << "Failed to serialize empty root signature: " << errorMessage;
  594. pErrorBlob->Release();
  595. }
  596. }
  597. unsigned int subobjectCount
  598. = shaders.getEntryCount() + hitGroups.getEntryCount() + 5;
  599. Array<DX12ShaderSignature*> distinctSignatures;
  600. for (const DX12Shader* shader : shaders)
  601. {
  602. for (const DX12ShaderFunction* function : shader->getFunctions())
  603. {
  604. DX12ShaderSignature* signature = function->zSignature();
  605. if (distinctSignatures.getValueIndex(signature) < 0)
  606. {
  607. distinctSignatures.add(signature);
  608. }
  609. }
  610. }
  611. subobjectCount += distinctSignatures.getEntryCount()
  612. * 2; // Local root signatures for each distinct signature
  613. D3D12_STATE_SUBOBJECT* subobjects
  614. = new D3D12_STATE_SUBOBJECT[subobjectCount];
  615. int index = 0;
  616. for (const DX12Shader* shader : shaders)
  617. {
  618. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY;
  619. subobjects[index].pDesc = shader->zLibraryDesc();
  620. index++;
  621. }
  622. int maxPayloadSize = 0;
  623. int maxAttributeSize = 0;
  624. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  625. {
  626. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP;
  627. subobjects[index].pDesc = hitGroup->zHitGroupDesc();
  628. if (hitGroup->getPayloadSize() > maxPayloadSize)
  629. {
  630. maxPayloadSize = hitGroup->getPayloadSize();
  631. }
  632. if (hitGroup->getAttributeSize() > maxAttributeSize)
  633. {
  634. maxAttributeSize = hitGroup->getAttributeSize();
  635. }
  636. index++;
  637. }
  638. D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = {};
  639. shaderDesc.MaxPayloadSizeInBytes = maxPayloadSize;
  640. shaderDesc.MaxAttributeSizeInBytes = maxAttributeSize;
  641. subobjects[index].Type
  642. = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG;
  643. subobjects[index].pDesc = &shaderDesc;
  644. index++;
  645. // create export list for hole pipeline with all hitgroups and all functions
  646. // that are not part of a hit group
  647. Array<const DX12ShaderFunction*> functionsWithoutHitGroups;
  648. for (const DX12Shader* shader : shaders)
  649. {
  650. for (const DX12ShaderFunction* function : shader->getFunctions())
  651. {
  652. bool found = 0;
  653. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  654. {
  655. if (hitGroup->zClosestHitShaderFunction() == function
  656. || hitGroup->zAnyHitShaderFunction() == function
  657. || hitGroup->zIntersectionShaderFunction() == function)
  658. {
  659. found = 1;
  660. break;
  661. }
  662. }
  663. if (!found)
  664. {
  665. functionsWithoutHitGroups.add(function);
  666. }
  667. }
  668. }
  669. const wchar_t** functionAndHitGroupNames
  670. = new const wchar_t*[functionsWithoutHitGroups.getEntryCount()
  671. + hitGroups.getEntryCount()];
  672. int nameIndex = 0;
  673. for (const DX12ShaderFunction* function : functionsWithoutHitGroups)
  674. {
  675. functionAndHitGroupNames[nameIndex]
  676. = const_cast<wchar_t*>(function->zExportDesc()->Name);
  677. nameIndex++;
  678. }
  679. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  680. {
  681. functionAndHitGroupNames[nameIndex]
  682. = const_cast<wchar_t*>(hitGroup->zHitGroupDesc()->HitGroupExport);
  683. nameIndex++;
  684. }
  685. D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};
  686. shaderPayloadAssociation.NumExports
  687. = functionsWithoutHitGroups.getEntryCount() + hitGroups.getEntryCount();
  688. shaderPayloadAssociation.pExports = functionAndHitGroupNames;
  689. shaderPayloadAssociation.pSubobjectToAssociate
  690. = &subobjects[index - 1]; // shader config
  691. subobjects[index].Type
  692. = D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
  693. subobjects[index].pDesc = &shaderPayloadAssociation;
  694. index++;
  695. D3D12_LOCAL_ROOT_SIGNATURE* localRootSignatures
  696. = new D3D12_LOCAL_ROOT_SIGNATURE[distinctSignatures.getEntryCount()];
  697. int rootSignatureIndex = 0;
  698. const wchar_t*** rootSignatureExports
  699. = new const wchar_t**[distinctSignatures.getEntryCount()];
  700. D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION* localRootAssociations
  701. = new D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION[distinctSignatures
  702. .getEntryCount()];
  703. for (DX12ShaderSignature* signature : distinctSignatures)
  704. {
  705. signature->createSignature(zDevice, pfnD3D12SerializeRootSignature);
  706. subobjects[index].Type
  707. = D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE;
  708. localRootSignatures[rootSignatureIndex].pLocalRootSignature
  709. = signature->zSignature();
  710. subobjects[index].pDesc = &localRootSignatures[rootSignatureIndex];
  711. index++;
  712. Array<const DX12ShaderFunction*> functionsWithThisSignature;
  713. for (const DX12Shader* shader : shaders)
  714. {
  715. for (const DX12ShaderFunction* function : shader->getFunctions())
  716. {
  717. if (function->zSignature() == signature)
  718. {
  719. bool found = 0;
  720. for (DX12ShaderHitGroup* hitGroup : hitGroups)
  721. {
  722. if (hitGroup->zClosestHitShaderFunction() == function
  723. || hitGroup->zAnyHitShaderFunction() == function
  724. || hitGroup->zIntersectionShaderFunction()
  725. == function)
  726. {
  727. found = 1;
  728. break;
  729. }
  730. }
  731. if (!found)
  732. {
  733. functionsWithThisSignature.add(function);
  734. }
  735. }
  736. }
  737. }
  738. Array<const DX12ShaderHitGroup*> hitGroupsWithThisSignature;
  739. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  740. {
  741. if (hitGroup->zClosestHitShaderFunction()
  742. && hitGroup->zClosestHitShaderFunction()->zSignature()
  743. == signature)
  744. {
  745. hitGroupsWithThisSignature.add(hitGroup);
  746. }
  747. else if (hitGroup->zAnyHitShaderFunction()
  748. && hitGroup->zAnyHitShaderFunction()->zSignature()
  749. == signature)
  750. {
  751. hitGroupsWithThisSignature.add(hitGroup);
  752. }
  753. else if (hitGroup->zIntersectionShaderFunction()
  754. && hitGroup->zIntersectionShaderFunction()->zSignature()
  755. == signature)
  756. {
  757. hitGroupsWithThisSignature.add(hitGroup);
  758. }
  759. }
  760. rootSignatureExports[rootSignatureIndex]
  761. = new const wchar_t*[functionsWithThisSignature.getEntryCount()
  762. + hitGroupsWithThisSignature.getEntryCount()];
  763. int nameIndex = 0;
  764. for (const DX12ShaderFunction* function : functionsWithThisSignature)
  765. {
  766. rootSignatureExports[rootSignatureIndex][nameIndex]
  767. = function->zExportDesc()->Name;
  768. nameIndex++;
  769. }
  770. for (const DX12ShaderHitGroup* hitGroup : hitGroupsWithThisSignature)
  771. {
  772. rootSignatureExports[rootSignatureIndex][nameIndex]
  773. = hitGroup->zHitGroupDesc()->HitGroupExport;
  774. nameIndex++;
  775. }
  776. localRootAssociations[rootSignatureIndex].NumExports
  777. = functionsWithThisSignature.getEntryCount()
  778. + hitGroupsWithThisSignature.getEntryCount();
  779. localRootAssociations[rootSignatureIndex].pExports
  780. = rootSignatureExports[rootSignatureIndex];
  781. localRootAssociations[rootSignatureIndex].pSubobjectToAssociate
  782. = &subobjects[index - 1]; // local root signature
  783. subobjects[index].Type
  784. = D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
  785. subobjects[index].pDesc = &localRootAssociations[rootSignatureIndex];
  786. index++;
  787. rootSignatureIndex++;
  788. }
  789. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE;
  790. subobjects[index].pDesc = &emptyGlobalRootSignature;
  791. index++;
  792. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE;
  793. subobjects[index].pDesc = &emptyLocalRootSignature;
  794. index++;
  795. D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = {};
  796. pipelineConfig.MaxTraceRecursionDepth = maxRecursionDepth;
  797. subobjects[index].Type
  798. = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG;
  799. subobjects[index].pDesc = &pipelineConfig;
  800. index++;
  801. D3D12_STATE_OBJECT_DESC pipelineDesc = {};
  802. pipelineDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
  803. pipelineDesc.NumSubobjects = subobjectCount;
  804. pipelineDesc.pSubobjects = subobjects;
  805. HRESULT hr = zDevice->CreateStateObject(
  806. &pipelineDesc, __uuidof(ID3D12StateObject), (void**)&pipelineState);
  807. if (FAILED(hr))
  808. {
  809. Logging::error()
  810. << "Failed to create raytracing pipeline state object: " << std::hex
  811. << hr;
  812. throw std::logic_error("Could not create the raytracing state object");
  813. }
  814. delete[] functionAndHitGroupNames;
  815. delete[] localRootSignatures;
  816. for (int i = 0; i < distinctSignatures.getEntryCount(); i++)
  817. {
  818. delete[] rootSignatureExports[i];
  819. }
  820. delete[] rootSignatureExports;
  821. delete[] localRootAssociations;
  822. }
  823. ID3D12StateObject* Framework::DX12Pipeline::zPipelineState() const
  824. {
  825. return pipelineState;
  826. }
  827. DX12ShaderBindingTable* Framework::DX12Pipeline::createShaderBindingTable()
  828. {
  829. return new DX12ShaderBindingTable(dynamic_cast<DX12Pipeline*>(getThis()));
  830. }
  831. DX12GlobalDescriptorHeap* Framework::DX12Pipeline::createGlobalDescriptorHeap()
  832. {
  833. return new DX12GlobalDescriptorHeap(dynamic_cast<DX12Pipeline*>(getThis()));
  834. }
  835. Framework::DX12GlobalDescriptorHeap::DX12GlobalDescriptorHeap(
  836. DX12Pipeline* pipeline)
  837. : ReferenceCounter(),
  838. descriptorHeap(0),
  839. lastDescriptorHeapSize(0)
  840. {}
  841. Framework::DX12GlobalDescriptorHeap::~DX12GlobalDescriptorHeap()
  842. {
  843. pipeline->release();
  844. if (descriptorHeap)
  845. {
  846. descriptorHeap->Release();
  847. }
  848. for (const DX12ShaderRegisterInput* input : registerInputs)
  849. {
  850. input->inputResource->release();
  851. delete input;
  852. }
  853. }
  854. void Framework::DX12GlobalDescriptorHeap::addInput(
  855. DX12ShaderRegister type, ReferenceCounter* inputResource)
  856. {
  857. bool found = 0;
  858. for (DX12Shader* shader : pipeline->getShaders())
  859. {
  860. for (DX12ShaderFunction* function : shader->getFunctions())
  861. {
  862. for (const DX12ShaderRegisterUsage& usage :
  863. function->zSignature()->getRegisterUsages())
  864. {
  865. if (usage.descriptorHeapIndex == registerInputs.getEntryCount())
  866. {
  867. if (usage.registerType != type)
  868. {
  869. Logging::error()
  870. << "Register type mismatch for register index "
  871. << usage.registerIndex << ", space index "
  872. << usage.spaceIndex << ". Expected register type: "
  873. << usage.registerType
  874. << ", given register type: " << type
  875. << ". The register type is specified in the "
  876. "signature of shader function '"
  877. << function->getFunctionName() << "'";
  878. throw std::logic_error(
  879. "Register type mismatch for shader input");
  880. }
  881. else
  882. {
  883. found = 1;
  884. break;
  885. }
  886. }
  887. }
  888. if (found)
  889. {
  890. break;
  891. }
  892. }
  893. if (found)
  894. {
  895. break;
  896. }
  897. }
  898. registerInputs.add(
  899. new DX12ShaderRegisterInput{type, inputResource->getThis()});
  900. }
  901. void Framework::DX12GlobalDescriptorHeap::addTextureInput(
  902. DX12ShaderRegister type, Texture* zTexture)
  903. {
  904. addInput(type, zTexture);
  905. }
  906. void Framework::DX12GlobalDescriptorHeap::addBufferInput(
  907. DX12ShaderRegister type, DXBuffer* zBuffer)
  908. {
  909. addInput(type, zBuffer);
  910. }
  911. void Framework::DX12GlobalDescriptorHeap::addTLASInput(
  912. DX12ShaderRegister type, DX12TLAS* zTLAS)
  913. {
  914. addInput(type, zTLAS);
  915. }
  916. void Framework::DX12GlobalDescriptorHeap::updateDescriptorHeap(
  917. ID3D12Device5* zDevice)
  918. {
  919. if (!descriptorHeap
  920. || lastDescriptorHeapSize != registerInputs.getEntryCount())
  921. {
  922. if (descriptorHeap)
  923. {
  924. descriptorHeap->Release();
  925. }
  926. D3D12_DESCRIPTOR_HEAP_DESC desc = {};
  927. desc.NumDescriptors = registerInputs.getEntryCount();
  928. desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  929. desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  930. desc.NodeMask = 0;
  931. HRESULT r = zDevice->CreateDescriptorHeap(
  932. &desc, __uuidof(ID3D12DescriptorHeap), (void**)&descriptorHeap);
  933. lastDescriptorHeapSize = registerInputs.getEntryCount();
  934. }
  935. D3D12_CPU_DESCRIPTOR_HANDLE descriptorHeapHandle
  936. = descriptorHeap->GetCPUDescriptorHandleForHeapStart();
  937. for (const DX12ShaderRegisterInput* input : registerInputs)
  938. {
  939. DX12TLAS* zTLAS = dynamic_cast<DX12TLAS*>(input->inputResource);
  940. DX12Texture* zTexture
  941. = dynamic_cast<DX12Texture*>(input->inputResource);
  942. DX12Buffer* zBuffer = dynamic_cast<DX12Buffer*>(input->inputResource);
  943. switch (input->registerType)
  944. {
  945. case DX12_SHADER_REGISTER_B_CONST_BUFFER:
  946. D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
  947. if (!zBuffer)
  948. {
  949. Logging::error()
  950. << "Expected a buffer resource for register type "
  951. << input->registerType;
  952. throw std::logic_error(
  953. "Expected a buffer resource for register type "
  954. + std::to_string(input->registerType));
  955. }
  956. cbvDesc.BufferLocation = zBuffer->zBuffer()->GetGPUVirtualAddress();
  957. cbvDesc.SizeInBytes
  958. = zBuffer->getElementCount() * zBuffer->getElementLength();
  959. zDevice->CreateConstantBufferView(&cbvDesc, descriptorHeapHandle);
  960. break;
  961. case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
  962. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
  963. srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  964. if (zTLAS)
  965. {
  966. srvDesc.ViewDimension
  967. = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE;
  968. srvDesc.RaytracingAccelerationStructure.Location
  969. = zTLAS->zResultBuffer()->zBuffer()->GetGPUVirtualAddress();
  970. }
  971. else if (zTexture)
  972. {
  973. srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  974. srvDesc.Texture2D.MipLevels = 0;
  975. srvDesc.Texture2D.MostDetailedMip = 0;
  976. srvDesc.Texture2D.PlaneSlice = 0;
  977. srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  978. }
  979. else if (zBuffer)
  980. {
  981. srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
  982. srvDesc.Buffer.FirstElement = 0;
  983. srvDesc.Buffer.NumElements = zBuffer->getElementCount();
  984. srvDesc.Buffer.StructureByteStride
  985. = zBuffer->getElementLength();
  986. srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
  987. }
  988. srvDesc.Shader4ComponentMapping
  989. = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  990. zDevice->CreateShaderResourceView(
  991. zTexture ? zTexture->zResource()
  992. : (zBuffer ? zBuffer->zBuffer() : 0),
  993. &srvDesc,
  994. descriptorHeapHandle);
  995. break;
  996. case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
  997. D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  998. if (zTexture)
  999. {
  1000. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
  1001. uavDesc.Format = DXGI_FORMAT_UNKNOWN;
  1002. uavDesc.Texture2D.MipSlice = 0;
  1003. uavDesc.Texture2D.PlaneSlice = 0;
  1004. }
  1005. else if (zBuffer)
  1006. {
  1007. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
  1008. uavDesc.Buffer.FirstElement = 0;
  1009. uavDesc.Buffer.NumElements = zBuffer->getElementCount();
  1010. uavDesc.Buffer.StructureByteStride
  1011. = zBuffer->getElementLength();
  1012. uavDesc.Buffer.CounterOffsetInBytes = 0;
  1013. uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
  1014. }
  1015. else
  1016. {
  1017. Logging::error() << "Expected a texture or buffer resource for "
  1018. "register type "
  1019. << input->registerType;
  1020. throw std::logic_error(
  1021. "Expected a texture or buffer resource for register type "
  1022. + std::to_string(input->registerType));
  1023. }
  1024. zDevice->CreateUnorderedAccessView(
  1025. zTexture ? zTexture->zResource() : zBuffer->zBuffer(),
  1026. 0,
  1027. &uavDesc,
  1028. descriptorHeapHandle);
  1029. break;
  1030. }
  1031. descriptorHeapHandle.ptr += zDevice->GetDescriptorHandleIncrementSize(
  1032. D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  1033. }
  1034. }
  1035. ID3D12DescriptorHeap*
  1036. Framework::DX12GlobalDescriptorHeap::zDescriptorHeap() const
  1037. {
  1038. return descriptorHeap;
  1039. }
  1040. Framework::DX12ShaderBindingTable::DX12ShaderBindingTable(
  1041. DX12Pipeline* pipeline)
  1042. : ReferenceCounter(),
  1043. pipeline(pipeline)
  1044. {}