DX12Shader.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. #include "DX12Shader.h"
  2. #include "Logging.h"
  3. using namespace Framework;
  4. Framework::DX12ShaderSignature::DX12ShaderSignature()
  5. : ReferenceCounter(),
  6. signature(0),
  7. changed(1)
  8. {}
  9. Framework::DX12ShaderSignature::~DX12ShaderSignature()
  10. {
  11. if (signature)
  12. {
  13. signature->Release();
  14. }
  15. }
  16. void Framework::DX12ShaderSignature::addRegisterUsage(
  17. DX12ShaderRegister registerType, int registerIndex)
  18. {
  19. addRegisterUsage(registerType, registerIndex, 0);
  20. }
  21. void Framework::DX12ShaderSignature::addRegisterUsage(
  22. DX12ShaderRegister registerType, int registerIndex, int spaceIndex)
  23. {
  24. registerUsages.add({registerType, registerIndex, spaceIndex});
  25. changed = 1;
  26. }
  27. void Framework::DX12ShaderSignature::createSignature(ID3D12Device5* zDevice,
  28. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfnD3D12SerializeRootSignature)
  29. {
  30. if (!changed)
  31. {
  32. return;
  33. }
  34. changed = 0;
  35. if (signature)
  36. {
  37. signature->Release();
  38. signature = 0;
  39. }
  40. D3D12_ROOT_PARAMETER descriptorTable;
  41. descriptorTable.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
  42. descriptorTable.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  43. descriptorTable.DescriptorTable.NumDescriptorRanges
  44. = registerUsages.getEntryCount();
  45. D3D12_DESCRIPTOR_RANGE* descriptorRanges
  46. = new D3D12_DESCRIPTOR_RANGE[registerUsages.getEntryCount()];
  47. int index = 0;
  48. for (const auto& usage : registerUsages)
  49. {
  50. D3D12_DESCRIPTOR_RANGE* range = &descriptorRanges[index];
  51. switch (usage.registerType)
  52. {
  53. case DX12_SHADER_REGISTER_B_CONST_BUFFER:
  54. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
  55. break;
  56. case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
  57. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
  58. break;
  59. case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
  60. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
  61. break;
  62. default:
  63. Logging::error() << "Unknown register type for root signature: "
  64. << usage.registerType;
  65. range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
  66. }
  67. range->NumDescriptors
  68. = 1; // TODO: optimize when multiple descriptors are used in a row
  69. // e.g. u0, u1, u2 with the same range then NumDescriptors can
  70. // be 3 for u0 and u1 and u2 would not be needed in this array
  71. range->BaseShaderRegister = usage.registerIndex;
  72. range->RegisterSpace = usage.spaceIndex;
  73. range->OffsetInDescriptorsFromTableStart = index;
  74. index++;
  75. }
  76. descriptorTable.DescriptorTable.pDescriptorRanges = descriptorRanges;
  77. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  78. rootDesc.NumParameters = 1;
  79. rootDesc.pParameters = &descriptorTable;
  80. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
  81. ID3DBlob* pSigBlob = 0;
  82. ID3DBlob* pErrorBlob = 0;
  83. HRESULT hr = pfnD3D12SerializeRootSignature(
  84. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  85. if (pSigBlob)
  86. {
  87. zDevice->CreateRootSignature(0,
  88. pSigBlob->GetBufferPointer(),
  89. pSigBlob->GetBufferSize(),
  90. __uuidof(ID3D12RootSignature),
  91. (void**)&signature);
  92. pSigBlob->Release();
  93. }
  94. if (pErrorBlob)
  95. {
  96. std::string errorMessage(
  97. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  98. pErrorBlob->GetBufferSize());
  99. Logging::error() << "Failed to serialize root signature: "
  100. << errorMessage;
  101. pErrorBlob->Release();
  102. }
  103. delete[] descriptorRanges;
  104. }
  105. ID3D12RootSignature* Framework::DX12ShaderSignature::zSignature() const
  106. {
  107. return signature;
  108. }
  109. Framework::DX12ShaderFunction::DX12ShaderFunction(
  110. const Text& functionName, DX12ShaderSignature* signature)
  111. : ReferenceCounter(),
  112. functionName(functionName),
  113. signature(signature),
  114. exportDesc(new D3D12_EXPORT_DESC())
  115. {
  116. wchar_t* wc = new wchar_t[functionName.getLength() + 1];
  117. mbtowc(wc, functionName.getText(), functionName.getLength() + 1);
  118. wc[functionName.getLength()] = 0;
  119. exportDesc->Name = wc;
  120. exportDesc->ExportToRename = 0;
  121. exportDesc->Flags = D3D12_EXPORT_FLAG_NONE;
  122. }
  123. Framework::DX12ShaderFunction::~DX12ShaderFunction()
  124. {
  125. signature->release();
  126. delete[] exportDesc->Name;
  127. delete exportDesc;
  128. }
  129. const Text& Framework::DX12ShaderFunction::getFunctionName() const
  130. {
  131. return functionName;
  132. }
  133. DX12ShaderSignature* Framework::DX12ShaderFunction::zSignature() const
  134. {
  135. return signature;
  136. }
  137. D3D12_EXPORT_DESC* Framework::DX12ShaderFunction::zExportDesc() const
  138. {
  139. return exportDesc;
  140. }
  141. Framework::DX12Shader::DX12Shader(const char* shaderBytes, int shaderBytesSize)
  142. : ReferenceCounter(),
  143. shaderBytes(shaderBytes),
  144. shaderBytesSize(shaderBytesSize),
  145. libraryDesc(new D3D12_DXIL_LIBRARY_DESC())
  146. {
  147. libraryDesc->DXILLibrary.pShaderBytecode = shaderBytes;
  148. libraryDesc->DXILLibrary.BytecodeLength = shaderBytesSize;
  149. libraryDesc->NumExports = 0;
  150. libraryDesc->pExports = 0;
  151. }
  152. Framework::DX12Shader::~DX12Shader()
  153. {
  154. delete[] libraryDesc->pExports;
  155. delete libraryDesc;
  156. }
  157. void Framework::DX12Shader::addFunction(DX12ShaderFunction* function)
  158. {
  159. functions.add(function);
  160. }
  161. int Framework::DX12Shader::getShaderBytesSize() const
  162. {
  163. return shaderBytesSize;
  164. }
  165. const char* Framework::DX12Shader::getShaderBytes() const
  166. {
  167. return shaderBytes;
  168. }
  169. const RCArray<DX12ShaderFunction>& Framework::DX12Shader::getFunctions() const
  170. {
  171. return functions;
  172. }
  173. D3D12_DXIL_LIBRARY_DESC* Framework::DX12Shader::zLibraryDesc() const
  174. {
  175. if (libraryDesc->NumExports != functions.getEntryCount())
  176. {
  177. delete[] libraryDesc->pExports;
  178. libraryDesc->NumExports = functions.getEntryCount();
  179. D3D12_EXPORT_DESC* pExports
  180. = new D3D12_EXPORT_DESC[functions.getEntryCount()];
  181. int index = 0;
  182. for (const auto& function : functions)
  183. {
  184. memcpy(pExports + index,
  185. function->zExportDesc(),
  186. sizeof(D3D12_EXPORT_DESC));
  187. index++;
  188. }
  189. libraryDesc->pExports = pExports;
  190. }
  191. return libraryDesc;
  192. }
  193. Framework::DX12ShaderHitGroup::DX12ShaderHitGroup(const Text name)
  194. : ReferenceCounter(),
  195. name(name),
  196. closestHitShaderFunction(0),
  197. anyHitShaderFunction(0),
  198. intersectionShaderFunction(0),
  199. payloadSize(0),
  200. attributeSize(0),
  201. hitGroupDesc(new D3D12_HIT_GROUP_DESC())
  202. {
  203. wchar_t* wc = new wchar_t[name.getLength() + 1];
  204. mbtowc(wc, name.getText(), name.getLength() + 1);
  205. wc[name.getLength()] = 0;
  206. hitGroupDesc->HitGroupExport = wc;
  207. hitGroupDesc->IntersectionShaderImport = 0;
  208. hitGroupDesc->AnyHitShaderImport = 0;
  209. hitGroupDesc->ClosestHitShaderImport = 0;
  210. }
  211. Framework::DX12ShaderHitGroup::~DX12ShaderHitGroup()
  212. {
  213. delete[] hitGroupDesc->HitGroupExport;
  214. delete hitGroupDesc;
  215. if (closestHitShaderFunction)
  216. {
  217. closestHitShaderFunction->release();
  218. }
  219. if (anyHitShaderFunction)
  220. {
  221. anyHitShaderFunction->release();
  222. }
  223. if (intersectionShaderFunction)
  224. {
  225. intersectionShaderFunction->release();
  226. }
  227. }
  228. void Framework::DX12ShaderHitGroup::setClosestHitShaderFunction(
  229. DX12ShaderFunction* closestHitShaderFunction)
  230. {
  231. if (anyHitShaderFunction
  232. && anyHitShaderFunction->zSignature()
  233. != closestHitShaderFunction->zSignature())
  234. {
  235. Logging::error()
  236. << "Any-hit shader function and closest-hit shader "
  237. "function must have the same root signature when they are "
  238. "combined in the same hit group. HitGroup Name: '"
  239. << name << "' Any Hit Shader Function: '"
  240. << anyHitShaderFunction->getFunctionName().getText()
  241. << "' Closest Hit Shader Function: '"
  242. << closestHitShaderFunction->getFunctionName().getText() << "'";
  243. throw std::runtime_error("Incompatible root signatures in hit group");
  244. }
  245. if (intersectionShaderFunction
  246. && intersectionShaderFunction->zSignature()
  247. != closestHitShaderFunction->zSignature())
  248. {
  249. Logging::error()
  250. << "Intersection shader function and closest-hit shader "
  251. "function must have the same root signature when they are "
  252. "combined in the same hit group. HitGroup Name: '"
  253. << name << "' Intersection Shader Function: '"
  254. << intersectionShaderFunction->getFunctionName().getText()
  255. << "' Closest Hit Shader Function: '"
  256. << closestHitShaderFunction->getFunctionName().getText() << "'";
  257. throw std::runtime_error("Incompatible root signatures in hit group");
  258. }
  259. if (this->closestHitShaderFunction)
  260. {
  261. this->closestHitShaderFunction->release();
  262. }
  263. this->closestHitShaderFunction = closestHitShaderFunction;
  264. hitGroupDesc->ClosestHitShaderImport = 0;
  265. if (closestHitShaderFunction)
  266. {
  267. hitGroupDesc->ClosestHitShaderImport
  268. = closestHitShaderFunction->zExportDesc()->Name;
  269. }
  270. }
  271. void Framework::DX12ShaderHitGroup::setAnyHitShaderFunction(
  272. DX12ShaderFunction* anyHitShaderFunction)
  273. {
  274. if (closestHitShaderFunction
  275. && closestHitShaderFunction->zSignature()
  276. != anyHitShaderFunction->zSignature())
  277. {
  278. Logging::error()
  279. << "Any-hit shader function and closest-hit shader "
  280. "function must have the same root signature when they are "
  281. "combined in the same hit group. HitGroup Name: '"
  282. << name << "' Any Hit Shader Function: '"
  283. << anyHitShaderFunction->getFunctionName().getText()
  284. << "' Closest Hit Shader Function: '"
  285. << closestHitShaderFunction->getFunctionName().getText() << "'";
  286. throw std::runtime_error("Incompatible root signatures in hit group");
  287. }
  288. if (intersectionShaderFunction
  289. && intersectionShaderFunction->zSignature()
  290. != anyHitShaderFunction->zSignature())
  291. {
  292. Logging::error()
  293. << "Intersection shader function and any-hit shader "
  294. "function must have the same root signature when they are "
  295. "combined in the same hit group. HitGroup Name: '"
  296. << name << "' Intersection Shader Function: '"
  297. << intersectionShaderFunction->getFunctionName().getText()
  298. << "' Any Hit Shader Function: '"
  299. << anyHitShaderFunction->getFunctionName().getText() << "'";
  300. throw std::runtime_error("Incompatible root signatures in hit group");
  301. }
  302. if (this->anyHitShaderFunction)
  303. {
  304. this->anyHitShaderFunction->release();
  305. }
  306. this->anyHitShaderFunction = anyHitShaderFunction;
  307. hitGroupDesc->AnyHitShaderImport = 0;
  308. if (anyHitShaderFunction)
  309. {
  310. hitGroupDesc->AnyHitShaderImport
  311. = anyHitShaderFunction->zExportDesc()->Name;
  312. }
  313. }
  314. void Framework::DX12ShaderHitGroup::setIntersectionShaderFunction(
  315. DX12ShaderFunction* intersectionShaderFunction)
  316. {
  317. if (closestHitShaderFunction
  318. && closestHitShaderFunction->zSignature()
  319. != intersectionShaderFunction->zSignature())
  320. {
  321. Logging::error()
  322. << "Intersection shader function and closest-hit shader "
  323. "function must have the same root signature when they are "
  324. "combined in the same hit group. HitGroup Name: '"
  325. << name << "' Intersection Shader Function: '"
  326. << intersectionShaderFunction->getFunctionName().getText()
  327. << "' Closest Hit Shader Function: '"
  328. << closestHitShaderFunction->getFunctionName().getText() << "'";
  329. throw std::runtime_error("Incompatible root signatures in hit group");
  330. }
  331. if (anyHitShaderFunction
  332. && anyHitShaderFunction->zSignature()
  333. != intersectionShaderFunction->zSignature())
  334. {
  335. Logging::error()
  336. << "Intersection shader function and any-hit shader "
  337. "function must have the same root signature when they are "
  338. "combined in the same hit group. HitGroup Name: '"
  339. << name << "' Intersection Shader Function: '"
  340. << intersectionShaderFunction->getFunctionName().getText()
  341. << "' Any Hit Shader Function: '"
  342. << anyHitShaderFunction->getFunctionName().getText() << "'";
  343. throw std::runtime_error("Incompatible root signatures in hit group");
  344. }
  345. if (this->intersectionShaderFunction)
  346. {
  347. this->intersectionShaderFunction->release();
  348. }
  349. this->intersectionShaderFunction = intersectionShaderFunction;
  350. hitGroupDesc->IntersectionShaderImport = 0;
  351. if (intersectionShaderFunction)
  352. {
  353. hitGroupDesc->IntersectionShaderImport
  354. = intersectionShaderFunction->zExportDesc()->Name;
  355. }
  356. }
  357. void Framework::DX12ShaderHitGroup::setPayloadSize(int payloadSize)
  358. {
  359. this->payloadSize = payloadSize;
  360. }
  361. void Framework::DX12ShaderHitGroup::setAttributeSize(int attributeSize)
  362. {
  363. this->attributeSize = attributeSize;
  364. }
  365. const Text& Framework::DX12ShaderHitGroup::getName() const
  366. {
  367. return name;
  368. }
  369. DX12ShaderFunction*
  370. Framework::DX12ShaderHitGroup::zClosestHitShaderFunction() const
  371. {
  372. return closestHitShaderFunction;
  373. }
  374. DX12ShaderFunction* Framework::DX12ShaderHitGroup::zAnyHitShaderFunction() const
  375. {
  376. return anyHitShaderFunction;
  377. }
  378. DX12ShaderFunction*
  379. Framework::DX12ShaderHitGroup::zIntersectionShaderFunction() const
  380. {
  381. return intersectionShaderFunction;
  382. }
  383. int Framework::DX12ShaderHitGroup::getPayloadSize() const
  384. {
  385. return payloadSize;
  386. }
  387. int Framework::DX12ShaderHitGroup::getAttributeSize() const
  388. {
  389. return attributeSize;
  390. }
  391. D3D12_HIT_GROUP_DESC* Framework::DX12ShaderHitGroup::zHitGroupDesc() const
  392. {
  393. if (hitGroupDesc->IntersectionShaderImport)
  394. {
  395. hitGroupDesc->Type = D3D12_HIT_GROUP_TYPE_PROCEDURAL_PRIMITIVE;
  396. }
  397. else
  398. {
  399. hitGroupDesc->Type = D3D12_HIT_GROUP_TYPE_TRIANGLES;
  400. }
  401. return hitGroupDesc;
  402. }
  403. Framework::DX12Pipeline::DX12Pipeline()
  404. : ReferenceCounter(),
  405. emptyGlobalRootSignature(0),
  406. emptyLocalRootSignature(0),
  407. pipelineState(0),
  408. maxRecursionDepth(0)
  409. {}
  410. Framework::DX12Pipeline::~DX12Pipeline()
  411. {
  412. if (emptyGlobalRootSignature)
  413. {
  414. emptyGlobalRootSignature->Release();
  415. }
  416. if (emptyLocalRootSignature)
  417. {
  418. emptyLocalRootSignature->Release();
  419. }
  420. if (pipelineState)
  421. {
  422. pipelineState->Release();
  423. }
  424. }
  425. void Framework::DX12Pipeline::addShader(DX12Shader* shader)
  426. {
  427. shaders.add(shader);
  428. }
  429. void Framework::DX12Pipeline::addHitGroup(DX12ShaderHitGroup* hitGroup)
  430. {
  431. hitGroups.add(hitGroup);
  432. }
  433. void Framework::DX12Pipeline::setMaxRecursionDepth(int maxRecursionDepth)
  434. {
  435. this->maxRecursionDepth = maxRecursionDepth;
  436. }
  437. void Framework::DX12Pipeline::createPipelineState(ID3D12Device5* zDevice,
  438. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfnD3D12SerializeRootSignature)
  439. {
  440. if (!emptyGlobalRootSignature)
  441. {
  442. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  443. rootDesc.NumParameters = 0;
  444. rootDesc.pParameters = 0;
  445. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
  446. ID3DBlob* pSigBlob = 0;
  447. ID3DBlob* pErrorBlob = 0;
  448. HRESULT hr = pfnD3D12SerializeRootSignature(
  449. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  450. if (pSigBlob)
  451. {
  452. zDevice->CreateRootSignature(0,
  453. pSigBlob->GetBufferPointer(),
  454. pSigBlob->GetBufferSize(),
  455. __uuidof(ID3D12RootSignature),
  456. (void**)&emptyGlobalRootSignature);
  457. pSigBlob->Release();
  458. }
  459. if (pErrorBlob)
  460. {
  461. std::string errorMessage(
  462. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  463. pErrorBlob->GetBufferSize());
  464. Logging::error()
  465. << "Failed to serialize empty root signature: " << errorMessage;
  466. pErrorBlob->Release();
  467. }
  468. }
  469. if (!emptyLocalRootSignature)
  470. {
  471. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  472. rootDesc.NumParameters = 0;
  473. rootDesc.pParameters = 0;
  474. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
  475. ID3DBlob* pSigBlob = 0;
  476. ID3DBlob* pErrorBlob = 0;
  477. HRESULT hr = pfnD3D12SerializeRootSignature(
  478. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  479. if (pSigBlob)
  480. {
  481. zDevice->CreateRootSignature(0,
  482. pSigBlob->GetBufferPointer(),
  483. pSigBlob->GetBufferSize(),
  484. __uuidof(ID3D12RootSignature),
  485. (void**)&emptyGlobalRootSignature);
  486. pSigBlob->Release();
  487. }
  488. if (pErrorBlob)
  489. {
  490. std::string errorMessage(
  491. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  492. pErrorBlob->GetBufferSize());
  493. Logging::error()
  494. << "Failed to serialize empty root signature: " << errorMessage;
  495. pErrorBlob->Release();
  496. }
  497. }
  498. unsigned int subobjectCount
  499. = shaders.getEntryCount() + hitGroups.getEntryCount() + 5;
  500. Array<DX12ShaderSignature*> distinctSignatures;
  501. for (const DX12Shader* shader : shaders)
  502. {
  503. for (const DX12ShaderFunction* function : shader->getFunctions())
  504. {
  505. DX12ShaderSignature* signature = function->zSignature();
  506. if (distinctSignatures.getValueIndex(signature) < 0)
  507. {
  508. distinctSignatures.add(signature);
  509. }
  510. }
  511. }
  512. subobjectCount += distinctSignatures.getEntryCount()
  513. * 2; // Local root signatures for each distinct signature
  514. D3D12_STATE_SUBOBJECT* subobjects
  515. = new D3D12_STATE_SUBOBJECT[subobjectCount];
  516. int index = 0;
  517. for (const DX12Shader* shader : shaders)
  518. {
  519. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY;
  520. subobjects[index].pDesc = shader->zLibraryDesc();
  521. index++;
  522. }
  523. int maxPayloadSize = 0;
  524. int maxAttributeSize = 0;
  525. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  526. {
  527. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP;
  528. subobjects[index].pDesc = hitGroup->zHitGroupDesc();
  529. if (hitGroup->getPayloadSize() > maxPayloadSize)
  530. {
  531. maxPayloadSize = hitGroup->getPayloadSize();
  532. }
  533. if (hitGroup->getAttributeSize() > maxAttributeSize)
  534. {
  535. maxAttributeSize = hitGroup->getAttributeSize();
  536. }
  537. index++;
  538. }
  539. D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = {};
  540. shaderDesc.MaxPayloadSizeInBytes = maxPayloadSize;
  541. shaderDesc.MaxAttributeSizeInBytes = maxAttributeSize;
  542. subobjects[index].Type
  543. = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG;
  544. subobjects[index].pDesc = &shaderDesc;
  545. index++;
  546. // create export list for hole pipeline with all hitgroups and all functions
  547. // that are not part of a hit group
  548. Array<const DX12ShaderFunction*> functionsWithoutHitGroups;
  549. for (const DX12Shader* shader : shaders)
  550. {
  551. for (const DX12ShaderFunction* function : shader->getFunctions())
  552. {
  553. bool found = 0;
  554. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  555. {
  556. if (hitGroup->zClosestHitShaderFunction() == function
  557. || hitGroup->zAnyHitShaderFunction() == function
  558. || hitGroup->zIntersectionShaderFunction() == function)
  559. {
  560. found = 1;
  561. break;
  562. }
  563. }
  564. if (!found)
  565. {
  566. functionsWithoutHitGroups.add(function);
  567. }
  568. }
  569. }
  570. wchar_t** functionAndHitGroupNames
  571. = new wchar_t*[functionsWithoutHitGroups.getEntryCount()
  572. + hitGroups.getEntryCount()];
  573. int nameIndex = 0;
  574. for (const DX12ShaderFunction* function : functionsWithoutHitGroups)
  575. {
  576. functionAndHitGroupNames[nameIndex]
  577. = const_cast<wchar_t*>(function->zExportDesc()->Name);
  578. nameIndex++;
  579. }
  580. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  581. {
  582. functionAndHitGroupNames[nameIndex]
  583. = const_cast<wchar_t*>(hitGroup->zHitGroupDesc()->HitGroupExport);
  584. nameIndex++;
  585. }
  586. D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};
  587. shaderPayloadAssociation.NumExports
  588. = functionsWithoutHitGroups.getEntryCount() + hitGroups.getEntryCount();
  589. shaderPayloadAssociation.pExports = functionAndHitGroupNames;
  590. shaderPayloadAssociation.pSubobjectToAssociate
  591. = &subobjects[index - 1]; // shader config
  592. subobjects[index].Type
  593. = D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
  594. subobjects[index].pDesc = &shaderPayloadAssociation;
  595. index++;
  596. D3D12_LOCAL_ROOT_SIGNATURE* localRootSignatures
  597. = new D3D12_LOCAL_ROOT_SIGNATURE[distinctSignatures.getEntryCount()];
  598. int rootSignatureIndex = 0;
  599. const wchar_t*** rootSignatureExports
  600. = new const wchar_t**[distinctSignatures.getEntryCount()];
  601. D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION* localRootAssociations
  602. = new D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION[distinctSignatures
  603. .getEntryCount()];
  604. for (DX12ShaderSignature* signature : distinctSignatures)
  605. {
  606. signature->createSignature(zDevice, pfnD3D12SerializeRootSignature);
  607. subobjects[index].Type
  608. = D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE;
  609. localRootSignatures[rootSignatureIndex].pLocalRootSignature
  610. = signature->zSignature();
  611. subobjects[index].pDesc = &localRootSignatures[rootSignatureIndex];
  612. index++;
  613. Array<const DX12ShaderFunction*> functionsWithThisSignature;
  614. for (const DX12Shader* shader : shaders)
  615. {
  616. for (const DX12ShaderFunction* function : shader->getFunctions())
  617. {
  618. if (function->zSignature() == signature)
  619. {
  620. bool found = 0;
  621. for (DX12ShaderHitGroup* hitGroup : hitGroups)
  622. {
  623. if (hitGroup->zClosestHitShaderFunction() == function
  624. || hitGroup->zAnyHitShaderFunction() == function
  625. || hitGroup->zIntersectionShaderFunction()
  626. == function)
  627. {
  628. found = 1;
  629. break;
  630. }
  631. }
  632. if (!found)
  633. {
  634. functionsWithThisSignature.add(function);
  635. }
  636. }
  637. }
  638. }
  639. Array<const DX12ShaderHitGroup*> hitGroupsWithThisSignature;
  640. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  641. {
  642. if (hitGroup->zClosestHitShaderFunction()
  643. && hitGroup->zClosestHitShaderFunction()->zSignature()
  644. == signature)
  645. {
  646. hitGroupsWithThisSignature.add(hitGroup);
  647. }
  648. else if (hitGroup->zAnyHitShaderFunction()
  649. && hitGroup->zAnyHitShaderFunction()->zSignature()
  650. == signature)
  651. {
  652. hitGroupsWithThisSignature.add(hitGroup);
  653. }
  654. else if (hitGroup->zIntersectionShaderFunction()
  655. && hitGroup->zIntersectionShaderFunction()->zSignature()
  656. == signature)
  657. {
  658. hitGroupsWithThisSignature.add(hitGroup);
  659. }
  660. }
  661. rootSignatureExports[rootSignatureIndex]
  662. = new const wchar_t*[functionsWithThisSignature.getEntryCount()
  663. + hitGroupsWithThisSignature.getEntryCount()];
  664. int nameIndex = 0;
  665. for (const DX12ShaderFunction* function : functionsWithThisSignature)
  666. {
  667. rootSignatureExports[rootSignatureIndex][nameIndex]
  668. = function->zExportDesc()->Name;
  669. nameIndex++;
  670. }
  671. for (const DX12ShaderHitGroup* hitGroup : hitGroupsWithThisSignature)
  672. {
  673. rootSignatureExports[rootSignatureIndex][nameIndex]
  674. = hitGroup->zHitGroupDesc()->HitGroupExport;
  675. nameIndex++;
  676. }
  677. localRootAssociations[rootSignatureIndex].NumExports
  678. = functionsWithThisSignature.getEntryCount()
  679. + hitGroupsWithThisSignature.getEntryCount();
  680. localRootAssociations[rootSignatureIndex].pExports
  681. = rootSignatureExports[rootSignatureIndex];
  682. localRootAssociations[rootSignatureIndex].pSubobjectToAssociate
  683. = &subobjects[index - 1]; // local root signature
  684. subobjects[index].Type
  685. = D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
  686. subobjects[index].pDesc = &localRootAssociations[rootSignatureIndex];
  687. index++;
  688. rootSignatureIndex++;
  689. }
  690. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE;
  691. subobjects[index].pDesc = &emptyGlobalRootSignature;
  692. index++;
  693. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE;
  694. subobjects[index].pDesc = &emptyLocalRootSignature;
  695. index++;
  696. D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = {};
  697. pipelineConfig.MaxTraceRecursionDepth = maxRecursionDepth;
  698. subobjects[index].Type
  699. = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG;
  700. subobjects[index].pDesc = &pipelineConfig;
  701. index++;
  702. D3D12_STATE_OBJECT_DESC pipelineDesc = {};
  703. pipelineDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
  704. pipelineDesc.NumSubobjects = subobjectCount;
  705. pipelineDesc.pSubobjects = subobjects;
  706. HRESULT hr = zDevice->CreateStateObject(
  707. &pipelineDesc, __uuidof(ID3D12StateObject), (void**)&pipelineState);
  708. if (FAILED(hr))
  709. {
  710. Logging::error()
  711. << "Failed to create raytracing pipeline state object: " << std::hex
  712. << hr;
  713. throw std::logic_error("Could not create the raytracing state object");
  714. }
  715. delete[] functionAndHitGroupNames;
  716. delete[] localRootSignatures;
  717. for (int i = 0; i < distinctSignatures.getEntryCount(); i++)
  718. {
  719. delete[] rootSignatureExports[i];
  720. }
  721. delete[] rootSignatureExports;
  722. delete[] localRootAssociations;
  723. }
  724. ID3D12StateObject* Framework::DX12Pipeline::zPipelineState() const
  725. {
  726. return pipelineState;
  727. }