DX12Shader.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  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(
  241. const unsigned char* shaderBytes, int shaderBytesSize)
  242. : ReferenceCounter(),
  243. shaderBytes(shaderBytes),
  244. shaderBytesSize(shaderBytesSize),
  245. libraryDesc(new D3D12_DXIL_LIBRARY_DESC())
  246. {
  247. libraryDesc->DXILLibrary.pShaderBytecode = shaderBytes;
  248. libraryDesc->DXILLibrary.BytecodeLength = shaderBytesSize;
  249. libraryDesc->NumExports = 0;
  250. libraryDesc->pExports = 0;
  251. }
  252. Framework::DX12Shader::~DX12Shader()
  253. {
  254. delete[] libraryDesc->pExports;
  255. delete libraryDesc;
  256. }
  257. void Framework::DX12Shader::addFunction(DX12ShaderFunction* function)
  258. {
  259. functions.add(function);
  260. }
  261. int Framework::DX12Shader::getShaderBytesSize() const
  262. {
  263. return shaderBytesSize;
  264. }
  265. const unsigned char* Framework::DX12Shader::getShaderBytes() const
  266. {
  267. return shaderBytes;
  268. }
  269. const RCArray<DX12ShaderFunction>& Framework::DX12Shader::getFunctions() const
  270. {
  271. return functions;
  272. }
  273. D3D12_DXIL_LIBRARY_DESC* Framework::DX12Shader::zLibraryDesc() const
  274. {
  275. if (libraryDesc->NumExports != functions.getEntryCount())
  276. {
  277. delete[] libraryDesc->pExports;
  278. libraryDesc->NumExports = functions.getEntryCount();
  279. D3D12_EXPORT_DESC* pExports
  280. = new D3D12_EXPORT_DESC[functions.getEntryCount()];
  281. int index = 0;
  282. for (const auto& function : functions)
  283. {
  284. memcpy(pExports + index,
  285. function->zExportDesc(),
  286. sizeof(D3D12_EXPORT_DESC));
  287. index++;
  288. }
  289. libraryDesc->pExports = pExports;
  290. }
  291. return libraryDesc;
  292. }
  293. Framework::DX12ShaderHitGroup::DX12ShaderHitGroup(const Text name)
  294. : ReferenceCounter(),
  295. name(name),
  296. closestHitShaderFunction(0),
  297. anyHitShaderFunction(0),
  298. intersectionShaderFunction(0),
  299. payloadSize(0),
  300. attributeSize(0),
  301. hitGroupDesc(new D3D12_HIT_GROUP_DESC())
  302. {
  303. wchar_t* wc = new wchar_t[name.getLength() + 1];
  304. mbtowc(wc, name.getText(), name.getLength() + 1);
  305. wc[name.getLength()] = 0;
  306. hitGroupDesc->HitGroupExport = wc;
  307. hitGroupDesc->IntersectionShaderImport = 0;
  308. hitGroupDesc->AnyHitShaderImport = 0;
  309. hitGroupDesc->ClosestHitShaderImport = 0;
  310. }
  311. Framework::DX12ShaderHitGroup::~DX12ShaderHitGroup()
  312. {
  313. delete[] hitGroupDesc->HitGroupExport;
  314. delete hitGroupDesc;
  315. if (closestHitShaderFunction)
  316. {
  317. closestHitShaderFunction->release();
  318. }
  319. if (anyHitShaderFunction)
  320. {
  321. anyHitShaderFunction->release();
  322. }
  323. if (intersectionShaderFunction)
  324. {
  325. intersectionShaderFunction->release();
  326. }
  327. }
  328. void Framework::DX12ShaderHitGroup::setClosestHitShaderFunction(
  329. DX12ShaderFunction* closestHitShaderFunction)
  330. {
  331. if (anyHitShaderFunction
  332. && anyHitShaderFunction->zSignature()
  333. != closestHitShaderFunction->zSignature())
  334. {
  335. Logging::error()
  336. << "Any-hit shader function and closest-hit shader "
  337. "function must have the same root signature when they are "
  338. "combined in the same hit group. HitGroup Name: '"
  339. << name << "' Any Hit Shader Function: '"
  340. << anyHitShaderFunction->getFunctionName().getText()
  341. << "' Closest Hit Shader Function: '"
  342. << closestHitShaderFunction->getFunctionName().getText() << "'";
  343. throw std::runtime_error("Incompatible root signatures in hit group");
  344. }
  345. if (intersectionShaderFunction
  346. && intersectionShaderFunction->zSignature()
  347. != closestHitShaderFunction->zSignature())
  348. {
  349. Logging::error()
  350. << "Intersection shader function and closest-hit shader "
  351. "function must have the same root signature when they are "
  352. "combined in the same hit group. HitGroup Name: '"
  353. << name << "' Intersection Shader Function: '"
  354. << intersectionShaderFunction->getFunctionName().getText()
  355. << "' Closest Hit Shader Function: '"
  356. << closestHitShaderFunction->getFunctionName().getText() << "'";
  357. throw std::runtime_error("Incompatible root signatures in hit group");
  358. }
  359. if (this->closestHitShaderFunction)
  360. {
  361. this->closestHitShaderFunction->release();
  362. }
  363. this->closestHitShaderFunction = closestHitShaderFunction;
  364. hitGroupDesc->ClosestHitShaderImport = 0;
  365. if (closestHitShaderFunction)
  366. {
  367. hitGroupDesc->ClosestHitShaderImport
  368. = closestHitShaderFunction->zExportDesc()->Name;
  369. }
  370. }
  371. void Framework::DX12ShaderHitGroup::setAnyHitShaderFunction(
  372. DX12ShaderFunction* anyHitShaderFunction)
  373. {
  374. if (closestHitShaderFunction
  375. && closestHitShaderFunction->zSignature()
  376. != anyHitShaderFunction->zSignature())
  377. {
  378. Logging::error()
  379. << "Any-hit shader function and closest-hit shader "
  380. "function must have the same root signature when they are "
  381. "combined in the same hit group. HitGroup Name: '"
  382. << name << "' Any Hit Shader Function: '"
  383. << anyHitShaderFunction->getFunctionName().getText()
  384. << "' Closest Hit Shader Function: '"
  385. << closestHitShaderFunction->getFunctionName().getText() << "'";
  386. throw std::runtime_error("Incompatible root signatures in hit group");
  387. }
  388. if (intersectionShaderFunction
  389. && intersectionShaderFunction->zSignature()
  390. != anyHitShaderFunction->zSignature())
  391. {
  392. Logging::error()
  393. << "Intersection shader function and any-hit shader "
  394. "function must have the same root signature when they are "
  395. "combined in the same hit group. HitGroup Name: '"
  396. << name << "' Intersection Shader Function: '"
  397. << intersectionShaderFunction->getFunctionName().getText()
  398. << "' Any Hit Shader Function: '"
  399. << anyHitShaderFunction->getFunctionName().getText() << "'";
  400. throw std::runtime_error("Incompatible root signatures in hit group");
  401. }
  402. if (this->anyHitShaderFunction)
  403. {
  404. this->anyHitShaderFunction->release();
  405. }
  406. this->anyHitShaderFunction = anyHitShaderFunction;
  407. hitGroupDesc->AnyHitShaderImport = 0;
  408. if (anyHitShaderFunction)
  409. {
  410. hitGroupDesc->AnyHitShaderImport
  411. = anyHitShaderFunction->zExportDesc()->Name;
  412. }
  413. }
  414. void Framework::DX12ShaderHitGroup::setIntersectionShaderFunction(
  415. DX12ShaderFunction* zIntersectionShaderFunction)
  416. {
  417. if (closestHitShaderFunction
  418. && closestHitShaderFunction->zSignature()
  419. != zIntersectionShaderFunction->zSignature())
  420. {
  421. Logging::error()
  422. << "Intersection shader function and closest-hit shader "
  423. "function must have the same root signature when they are "
  424. "combined in the same hit group. HitGroup Name: '"
  425. << name << "' Intersection Shader Function: '"
  426. << zIntersectionShaderFunction->getFunctionName().getText()
  427. << "' Closest Hit Shader Function: '"
  428. << closestHitShaderFunction->getFunctionName().getText() << "'";
  429. throw std::runtime_error("Incompatible root signatures in hit group");
  430. }
  431. if (anyHitShaderFunction
  432. && anyHitShaderFunction->zSignature()
  433. != zIntersectionShaderFunction->zSignature())
  434. {
  435. Logging::error()
  436. << "Intersection shader function and any-hit shader "
  437. "function must have the same root signature when they are "
  438. "combined in the same hit group. HitGroup Name: '"
  439. << name << "' Intersection Shader Function: '"
  440. << zIntersectionShaderFunction->getFunctionName().getText()
  441. << "' Any Hit Shader Function: '"
  442. << anyHitShaderFunction->getFunctionName().getText() << "'";
  443. throw std::runtime_error("Incompatible root signatures in hit group");
  444. }
  445. if (intersectionShaderFunction)
  446. {
  447. intersectionShaderFunction->release();
  448. }
  449. intersectionShaderFunction = dynamic_cast<DX12ShaderFunction*>(
  450. zIntersectionShaderFunction->getThis());
  451. hitGroupDesc->IntersectionShaderImport = 0;
  452. if (intersectionShaderFunction)
  453. {
  454. hitGroupDesc->IntersectionShaderImport
  455. = intersectionShaderFunction->zExportDesc()->Name;
  456. }
  457. }
  458. void Framework::DX12ShaderHitGroup::setPayloadSize(int payloadSize)
  459. {
  460. this->payloadSize = payloadSize;
  461. }
  462. void Framework::DX12ShaderHitGroup::setAttributeSize(int attributeSize)
  463. {
  464. this->attributeSize = attributeSize;
  465. }
  466. const Text& Framework::DX12ShaderHitGroup::getName() const
  467. {
  468. return name;
  469. }
  470. DX12ShaderFunction*
  471. Framework::DX12ShaderHitGroup::zClosestHitShaderFunction() const
  472. {
  473. return closestHitShaderFunction;
  474. }
  475. DX12ShaderFunction* Framework::DX12ShaderHitGroup::zAnyHitShaderFunction() const
  476. {
  477. return anyHitShaderFunction;
  478. }
  479. DX12ShaderFunction*
  480. Framework::DX12ShaderHitGroup::zIntersectionShaderFunction() const
  481. {
  482. return intersectionShaderFunction;
  483. }
  484. int Framework::DX12ShaderHitGroup::getPayloadSize() const
  485. {
  486. return payloadSize;
  487. }
  488. int Framework::DX12ShaderHitGroup::getAttributeSize() const
  489. {
  490. return attributeSize;
  491. }
  492. D3D12_HIT_GROUP_DESC* Framework::DX12ShaderHitGroup::zHitGroupDesc() const
  493. {
  494. if (hitGroupDesc->IntersectionShaderImport)
  495. {
  496. hitGroupDesc->Type = D3D12_HIT_GROUP_TYPE_PROCEDURAL_PRIMITIVE;
  497. }
  498. else
  499. {
  500. hitGroupDesc->Type = D3D12_HIT_GROUP_TYPE_TRIANGLES;
  501. }
  502. return hitGroupDesc;
  503. }
  504. Framework::DX12Pipeline::DX12Pipeline()
  505. : ReferenceCounter(),
  506. emptyGlobalRootSignature(0),
  507. emptyLocalRootSignature(0),
  508. pipelineState(0),
  509. maxRecursionDepth(0)
  510. {}
  511. Framework::DX12Pipeline::~DX12Pipeline()
  512. {
  513. if (emptyGlobalRootSignature)
  514. {
  515. emptyGlobalRootSignature->Release();
  516. }
  517. if (emptyLocalRootSignature)
  518. {
  519. emptyLocalRootSignature->Release();
  520. }
  521. if (pipelineState)
  522. {
  523. pipelineState->Release();
  524. }
  525. }
  526. void Framework::DX12Pipeline::addShader(DX12Shader* shader)
  527. {
  528. shaders.add(shader);
  529. }
  530. void Framework::DX12Pipeline::addHitGroup(DX12ShaderHitGroup* hitGroup)
  531. {
  532. hitGroups.add(hitGroup);
  533. }
  534. void Framework::DX12Pipeline::setMaxRecursionDepth(int maxRecursionDepth)
  535. {
  536. this->maxRecursionDepth = maxRecursionDepth;
  537. }
  538. void Framework::DX12Pipeline::createPipelineState(ID3D12Device5* zDevice,
  539. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfnD3D12SerializeRootSignature)
  540. {
  541. if (!emptyGlobalRootSignature)
  542. {
  543. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  544. rootDesc.NumParameters = 0;
  545. rootDesc.pParameters = 0;
  546. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
  547. ID3DBlob* pSigBlob = 0;
  548. ID3DBlob* pErrorBlob = 0;
  549. HRESULT hr = pfnD3D12SerializeRootSignature(
  550. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  551. if (pSigBlob)
  552. {
  553. zDevice->CreateRootSignature(0,
  554. pSigBlob->GetBufferPointer(),
  555. pSigBlob->GetBufferSize(),
  556. __uuidof(ID3D12RootSignature),
  557. (void**)&emptyGlobalRootSignature);
  558. pSigBlob->Release();
  559. }
  560. if (pErrorBlob)
  561. {
  562. std::string errorMessage(
  563. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  564. pErrorBlob->GetBufferSize());
  565. Logging::error()
  566. << "Failed to serialize empty root signature: " << errorMessage;
  567. pErrorBlob->Release();
  568. }
  569. }
  570. if (!emptyLocalRootSignature)
  571. {
  572. D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
  573. rootDesc.NumParameters = 0;
  574. rootDesc.pParameters = 0;
  575. rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
  576. ID3DBlob* pSigBlob = 0;
  577. ID3DBlob* pErrorBlob = 0;
  578. HRESULT hr = pfnD3D12SerializeRootSignature(
  579. &rootDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &pSigBlob, &pErrorBlob);
  580. if (pSigBlob)
  581. {
  582. zDevice->CreateRootSignature(0,
  583. pSigBlob->GetBufferPointer(),
  584. pSigBlob->GetBufferSize(),
  585. __uuidof(ID3D12RootSignature),
  586. (void**)&emptyGlobalRootSignature);
  587. pSigBlob->Release();
  588. }
  589. if (pErrorBlob)
  590. {
  591. std::string errorMessage(
  592. static_cast<const char*>(pErrorBlob->GetBufferPointer()),
  593. pErrorBlob->GetBufferSize());
  594. Logging::error()
  595. << "Failed to serialize empty root signature: " << errorMessage;
  596. pErrorBlob->Release();
  597. }
  598. }
  599. unsigned int subobjectCount
  600. = shaders.getEntryCount() + hitGroups.getEntryCount() + 5;
  601. Array<DX12ShaderSignature*> distinctSignatures;
  602. for (const DX12Shader* shader : shaders)
  603. {
  604. for (const DX12ShaderFunction* function : shader->getFunctions())
  605. {
  606. DX12ShaderSignature* signature = function->zSignature();
  607. if (distinctSignatures.getValueIndex(signature) < 0)
  608. {
  609. distinctSignatures.add(signature);
  610. }
  611. }
  612. }
  613. subobjectCount += distinctSignatures.getEntryCount()
  614. * 2; // Local root signatures for each distinct signature
  615. D3D12_STATE_SUBOBJECT* subobjects
  616. = new D3D12_STATE_SUBOBJECT[subobjectCount];
  617. int index = 0;
  618. for (const DX12Shader* shader : shaders)
  619. {
  620. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY;
  621. subobjects[index].pDesc = shader->zLibraryDesc();
  622. index++;
  623. }
  624. int maxPayloadSize = 0;
  625. int maxAttributeSize = 0;
  626. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  627. {
  628. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP;
  629. subobjects[index].pDesc = hitGroup->zHitGroupDesc();
  630. if (hitGroup->getPayloadSize() > maxPayloadSize)
  631. {
  632. maxPayloadSize = hitGroup->getPayloadSize();
  633. }
  634. if (hitGroup->getAttributeSize() > maxAttributeSize)
  635. {
  636. maxAttributeSize = hitGroup->getAttributeSize();
  637. }
  638. index++;
  639. }
  640. D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = {};
  641. shaderDesc.MaxPayloadSizeInBytes = maxPayloadSize;
  642. shaderDesc.MaxAttributeSizeInBytes = maxAttributeSize;
  643. subobjects[index].Type
  644. = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG;
  645. subobjects[index].pDesc = &shaderDesc;
  646. index++;
  647. // create export list for hole pipeline with all hitgroups and all functions
  648. // that are not part of a hit group
  649. Array<const DX12ShaderFunction*> functionsWithoutHitGroups;
  650. for (const DX12Shader* shader : shaders)
  651. {
  652. for (const DX12ShaderFunction* function : shader->getFunctions())
  653. {
  654. bool found = 0;
  655. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  656. {
  657. if (hitGroup->zClosestHitShaderFunction() == function
  658. || hitGroup->zAnyHitShaderFunction() == function
  659. || hitGroup->zIntersectionShaderFunction() == function)
  660. {
  661. found = 1;
  662. break;
  663. }
  664. }
  665. if (!found)
  666. {
  667. functionsWithoutHitGroups.add(function);
  668. }
  669. }
  670. }
  671. const wchar_t** functionAndHitGroupNames
  672. = new const wchar_t*[functionsWithoutHitGroups.getEntryCount()
  673. + hitGroups.getEntryCount()];
  674. int nameIndex = 0;
  675. for (const DX12ShaderFunction* function : functionsWithoutHitGroups)
  676. {
  677. functionAndHitGroupNames[nameIndex]
  678. = const_cast<wchar_t*>(function->zExportDesc()->Name);
  679. nameIndex++;
  680. }
  681. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  682. {
  683. functionAndHitGroupNames[nameIndex]
  684. = const_cast<wchar_t*>(hitGroup->zHitGroupDesc()->HitGroupExport);
  685. nameIndex++;
  686. }
  687. D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};
  688. shaderPayloadAssociation.NumExports
  689. = functionsWithoutHitGroups.getEntryCount() + hitGroups.getEntryCount();
  690. shaderPayloadAssociation.pExports = functionAndHitGroupNames;
  691. shaderPayloadAssociation.pSubobjectToAssociate
  692. = &subobjects[index - 1]; // shader config
  693. subobjects[index].Type
  694. = D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
  695. subobjects[index].pDesc = &shaderPayloadAssociation;
  696. index++;
  697. D3D12_LOCAL_ROOT_SIGNATURE* localRootSignatures
  698. = new D3D12_LOCAL_ROOT_SIGNATURE[distinctSignatures.getEntryCount()];
  699. int rootSignatureIndex = 0;
  700. const wchar_t*** rootSignatureExports
  701. = new const wchar_t**[distinctSignatures.getEntryCount()];
  702. D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION* localRootAssociations
  703. = new D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION[distinctSignatures
  704. .getEntryCount()];
  705. for (DX12ShaderSignature* signature : distinctSignatures)
  706. {
  707. signature->createSignature(zDevice, pfnD3D12SerializeRootSignature);
  708. subobjects[index].Type
  709. = D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE;
  710. localRootSignatures[rootSignatureIndex].pLocalRootSignature
  711. = signature->zSignature();
  712. subobjects[index].pDesc = &localRootSignatures[rootSignatureIndex];
  713. index++;
  714. Array<const DX12ShaderFunction*> functionsWithThisSignature;
  715. for (const DX12Shader* shader : shaders)
  716. {
  717. for (const DX12ShaderFunction* function : shader->getFunctions())
  718. {
  719. if (function->zSignature() == signature)
  720. {
  721. bool found = 0;
  722. for (DX12ShaderHitGroup* hitGroup : hitGroups)
  723. {
  724. if (hitGroup->zClosestHitShaderFunction() == function
  725. || hitGroup->zAnyHitShaderFunction() == function
  726. || hitGroup->zIntersectionShaderFunction()
  727. == function)
  728. {
  729. found = 1;
  730. break;
  731. }
  732. }
  733. if (!found)
  734. {
  735. functionsWithThisSignature.add(function);
  736. }
  737. }
  738. }
  739. }
  740. Array<const DX12ShaderHitGroup*> hitGroupsWithThisSignature;
  741. for (const DX12ShaderHitGroup* hitGroup : hitGroups)
  742. {
  743. if (hitGroup->zClosestHitShaderFunction()
  744. && hitGroup->zClosestHitShaderFunction()->zSignature()
  745. == signature)
  746. {
  747. hitGroupsWithThisSignature.add(hitGroup);
  748. }
  749. else if (hitGroup->zAnyHitShaderFunction()
  750. && hitGroup->zAnyHitShaderFunction()->zSignature()
  751. == signature)
  752. {
  753. hitGroupsWithThisSignature.add(hitGroup);
  754. }
  755. else if (hitGroup->zIntersectionShaderFunction()
  756. && hitGroup->zIntersectionShaderFunction()->zSignature()
  757. == signature)
  758. {
  759. hitGroupsWithThisSignature.add(hitGroup);
  760. }
  761. }
  762. rootSignatureExports[rootSignatureIndex]
  763. = new const wchar_t*[functionsWithThisSignature.getEntryCount()
  764. + hitGroupsWithThisSignature.getEntryCount()];
  765. int nameIndex = 0;
  766. for (const DX12ShaderFunction* function : functionsWithThisSignature)
  767. {
  768. rootSignatureExports[rootSignatureIndex][nameIndex]
  769. = function->zExportDesc()->Name;
  770. nameIndex++;
  771. }
  772. for (const DX12ShaderHitGroup* hitGroup : hitGroupsWithThisSignature)
  773. {
  774. rootSignatureExports[rootSignatureIndex][nameIndex]
  775. = hitGroup->zHitGroupDesc()->HitGroupExport;
  776. nameIndex++;
  777. }
  778. localRootAssociations[rootSignatureIndex].NumExports
  779. = functionsWithThisSignature.getEntryCount()
  780. + hitGroupsWithThisSignature.getEntryCount();
  781. localRootAssociations[rootSignatureIndex].pExports
  782. = rootSignatureExports[rootSignatureIndex];
  783. localRootAssociations[rootSignatureIndex].pSubobjectToAssociate
  784. = &subobjects[index - 1]; // local root signature
  785. subobjects[index].Type
  786. = D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
  787. subobjects[index].pDesc = &localRootAssociations[rootSignatureIndex];
  788. index++;
  789. rootSignatureIndex++;
  790. }
  791. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE;
  792. subobjects[index].pDesc = &emptyGlobalRootSignature;
  793. index++;
  794. subobjects[index].Type = D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE;
  795. subobjects[index].pDesc = &emptyLocalRootSignature;
  796. index++;
  797. D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = {};
  798. pipelineConfig.MaxTraceRecursionDepth = maxRecursionDepth;
  799. subobjects[index].Type
  800. = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG;
  801. subobjects[index].pDesc = &pipelineConfig;
  802. index++;
  803. D3D12_STATE_OBJECT_DESC pipelineDesc = {};
  804. pipelineDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
  805. pipelineDesc.NumSubobjects = subobjectCount;
  806. pipelineDesc.pSubobjects = subobjects;
  807. HRESULT hr = zDevice->CreateStateObject(
  808. &pipelineDesc, __uuidof(ID3D12StateObject), (void**)&pipelineState);
  809. if (FAILED(hr))
  810. {
  811. Logging::error()
  812. << "Failed to create raytracing pipeline state object: " << std::hex
  813. << hr;
  814. throw std::logic_error("Could not create the raytracing state object");
  815. }
  816. delete[] functionAndHitGroupNames;
  817. delete[] localRootSignatures;
  818. for (int i = 0; i < distinctSignatures.getEntryCount(); i++)
  819. {
  820. delete[] rootSignatureExports[i];
  821. }
  822. delete[] rootSignatureExports;
  823. delete[] localRootAssociations;
  824. }
  825. ID3D12StateObject* Framework::DX12Pipeline::zPipelineState() const
  826. {
  827. return pipelineState;
  828. }
  829. DX12ShaderBindingTable* Framework::DX12Pipeline::createShaderBindingTable()
  830. {
  831. return new DX12ShaderBindingTable(dynamic_cast<DX12Pipeline*>(getThis()));
  832. }
  833. DX12GlobalDescriptorHeap* Framework::DX12Pipeline::createGlobalDescriptorHeap()
  834. {
  835. return new DX12GlobalDescriptorHeap(dynamic_cast<DX12Pipeline*>(getThis()));
  836. }
  837. Framework::DX12GlobalDescriptorHeap::DX12GlobalDescriptorHeap(
  838. DX12Pipeline* pipeline)
  839. : ReferenceCounter(),
  840. descriptorHeap(0),
  841. lastDescriptorHeapSize(0)
  842. {}
  843. Framework::DX12GlobalDescriptorHeap::~DX12GlobalDescriptorHeap()
  844. {
  845. pipeline->release();
  846. if (descriptorHeap)
  847. {
  848. descriptorHeap->Release();
  849. }
  850. for (const DX12ShaderRegisterInput* input : registerInputs)
  851. {
  852. input->inputResource->release();
  853. delete input;
  854. }
  855. }
  856. void Framework::DX12GlobalDescriptorHeap::addInput(
  857. DX12ShaderRegister type, ReferenceCounter* inputResource)
  858. {
  859. bool found = 0;
  860. for (DX12Shader* shader : pipeline->getShaders())
  861. {
  862. for (DX12ShaderFunction* function : shader->getFunctions())
  863. {
  864. for (const DX12ShaderRegisterUsage& usage :
  865. function->zSignature()->getRegisterUsages())
  866. {
  867. if (usage.descriptorHeapIndex == registerInputs.getEntryCount())
  868. {
  869. if (usage.registerType != type)
  870. {
  871. Logging::error()
  872. << "Register type mismatch for register index "
  873. << usage.registerIndex << ", space index "
  874. << usage.spaceIndex << ". Expected register type: "
  875. << usage.registerType
  876. << ", given register type: " << type
  877. << ". The register type is specified in the "
  878. "signature of shader function '"
  879. << function->getFunctionName() << "'";
  880. throw std::logic_error(
  881. "Register type mismatch for shader input");
  882. }
  883. else
  884. {
  885. found = 1;
  886. break;
  887. }
  888. }
  889. }
  890. if (found)
  891. {
  892. break;
  893. }
  894. }
  895. if (found)
  896. {
  897. break;
  898. }
  899. }
  900. registerInputs.add(
  901. new DX12ShaderRegisterInput{type, inputResource->getThis()});
  902. }
  903. void Framework::DX12GlobalDescriptorHeap::addTextureInput(
  904. DX12ShaderRegister type, Texture* zTexture)
  905. {
  906. addInput(type, zTexture);
  907. }
  908. void Framework::DX12GlobalDescriptorHeap::addBufferInput(
  909. DX12ShaderRegister type, DXBuffer* zBuffer)
  910. {
  911. addInput(type, zBuffer);
  912. }
  913. void Framework::DX12GlobalDescriptorHeap::addTLASInput(
  914. DX12ShaderRegister type, DX12TLAS* zTLAS)
  915. {
  916. addInput(type, zTLAS);
  917. }
  918. void Framework::DX12GlobalDescriptorHeap::updateDescriptorHeap(
  919. ID3D12Device5* zDevice)
  920. {
  921. if (!descriptorHeap
  922. || lastDescriptorHeapSize != registerInputs.getEntryCount())
  923. {
  924. if (descriptorHeap)
  925. {
  926. descriptorHeap->Release();
  927. }
  928. D3D12_DESCRIPTOR_HEAP_DESC desc = {};
  929. desc.NumDescriptors = registerInputs.getEntryCount();
  930. desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  931. desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  932. desc.NodeMask = 0;
  933. HRESULT r = zDevice->CreateDescriptorHeap(
  934. &desc, __uuidof(ID3D12DescriptorHeap), (void**)&descriptorHeap);
  935. lastDescriptorHeapSize = registerInputs.getEntryCount();
  936. }
  937. D3D12_CPU_DESCRIPTOR_HANDLE descriptorHeapHandle
  938. = descriptorHeap->GetCPUDescriptorHandleForHeapStart();
  939. for (const DX12ShaderRegisterInput* input : registerInputs)
  940. {
  941. DX12TLAS* zTLAS = dynamic_cast<DX12TLAS*>(input->inputResource);
  942. DX12Texture* zTexture
  943. = dynamic_cast<DX12Texture*>(input->inputResource);
  944. DX12Buffer* zBuffer = dynamic_cast<DX12Buffer*>(input->inputResource);
  945. switch (input->registerType)
  946. {
  947. case DX12_SHADER_REGISTER_B_CONST_BUFFER:
  948. {
  949. D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
  950. if (!zBuffer)
  951. {
  952. Logging::error()
  953. << "Expected a buffer resource for register type "
  954. << input->registerType;
  955. throw std::logic_error(
  956. "Expected a buffer resource for register type "
  957. + std::to_string(input->registerType));
  958. }
  959. cbvDesc.BufferLocation
  960. = zBuffer->zBuffer()->GetGPUVirtualAddress();
  961. cbvDesc.SizeInBytes = (unsigned)zBuffer->getElementCount()
  962. * zBuffer->getElementLength();
  963. zDevice->CreateConstantBufferView(
  964. &cbvDesc, descriptorHeapHandle);
  965. break;
  966. }
  967. case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
  968. {
  969. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
  970. srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  971. if (zTLAS)
  972. {
  973. srvDesc.ViewDimension
  974. = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE;
  975. srvDesc.RaytracingAccelerationStructure.Location
  976. = zTLAS->zResultBuffer()
  977. ->zBuffer()
  978. ->GetGPUVirtualAddress();
  979. }
  980. else if (zTexture)
  981. {
  982. srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  983. srvDesc.Texture2D.MipLevels = 0;
  984. srvDesc.Texture2D.MostDetailedMip = 0;
  985. srvDesc.Texture2D.PlaneSlice = 0;
  986. srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  987. }
  988. else if (zBuffer)
  989. {
  990. srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
  991. srvDesc.Buffer.FirstElement = 0;
  992. srvDesc.Buffer.NumElements
  993. = (unsigned)zBuffer->getElementCount();
  994. srvDesc.Buffer.StructureByteStride
  995. = zBuffer->getElementLength();
  996. srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
  997. }
  998. srvDesc.Shader4ComponentMapping
  999. = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  1000. zDevice->CreateShaderResourceView(
  1001. zTexture ? zTexture->zResource()
  1002. : (zBuffer ? zBuffer->zBuffer() : 0),
  1003. &srvDesc,
  1004. descriptorHeapHandle);
  1005. break;
  1006. }
  1007. case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
  1008. {
  1009. D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  1010. if (zTexture)
  1011. {
  1012. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
  1013. uavDesc.Format = DXGI_FORMAT_UNKNOWN;
  1014. uavDesc.Texture2D.MipSlice = 0;
  1015. uavDesc.Texture2D.PlaneSlice = 0;
  1016. }
  1017. else if (zBuffer)
  1018. {
  1019. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
  1020. uavDesc.Buffer.FirstElement = 0;
  1021. uavDesc.Buffer.NumElements
  1022. = (unsigned)zBuffer->getElementCount();
  1023. uavDesc.Buffer.StructureByteStride
  1024. = zBuffer->getElementLength();
  1025. uavDesc.Buffer.CounterOffsetInBytes = 0;
  1026. uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
  1027. }
  1028. else
  1029. {
  1030. Logging::error()
  1031. << "Expected a texture or buffer resource for "
  1032. "register type "
  1033. << input->registerType;
  1034. throw std::logic_error(
  1035. "Expected a texture or buffer resource for register "
  1036. "type "
  1037. + std::to_string(input->registerType));
  1038. }
  1039. zDevice->CreateUnorderedAccessView(
  1040. zTexture ? zTexture->zResource() : zBuffer->zBuffer(),
  1041. 0,
  1042. &uavDesc,
  1043. descriptorHeapHandle);
  1044. break;
  1045. }
  1046. }
  1047. descriptorHeapHandle.ptr += zDevice->GetDescriptorHandleIncrementSize(
  1048. D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  1049. }
  1050. }
  1051. DX12Pipeline* Framework::DX12GlobalDescriptorHeap::zPipeline() const
  1052. {
  1053. return pipeline;
  1054. }
  1055. ID3D12DescriptorHeap*
  1056. Framework::DX12GlobalDescriptorHeap::zDescriptorHeap() const
  1057. {
  1058. return descriptorHeap;
  1059. }
  1060. Framework::DX12ShaderBindingTable::DX12ShaderBindingTable(
  1061. DX12Pipeline* pipeline)
  1062. : ReferenceCounter(),
  1063. pipeline(pipeline)
  1064. {}