DX12GraphicsApi.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019
  1. #include "DX12GraphicsApi.h"
  2. #include <d3d11.h>
  3. #include <d3d12.h>
  4. #include <dxgi1_6.h>
  5. #include <dxgidebug.h>
  6. #include "Camera3D.h"
  7. #include "d3dx12.h"
  8. #include "DLLRegister.h"
  9. #include "DX12BLASModel.h"
  10. #include "DX12CommandQueue.h"
  11. #include "DX12HitShader.h"
  12. #include "DX12MissShader.h"
  13. #include "DX12RayGenShader.h"
  14. #include "DX12Shader.h"
  15. #include "DX12Texture.h"
  16. #include "DX12TLAS.h"
  17. #include "Globals.h"
  18. #include "Image.h"
  19. #include "Model3D.h"
  20. #include "Model3DList.h"
  21. #include "Screen.h"
  22. #include "TextureList.h"
  23. #include "TextureModel.h"
  24. #include "Window.h"
  25. #include "World3D.h"
  26. using namespace Framework;
  27. DirectX12::DirectX12()
  28. : GraphicsApi(DIRECTX12),
  29. debug(0),
  30. infoQueue(0),
  31. directCommandQueue(0),
  32. swapChain(0),
  33. backBufferIndex(0),
  34. tearing(0),
  35. viewPort(0),
  36. allowedRenderArea(0),
  37. signature(0),
  38. uiTexture(0),
  39. texturRegister(new TextureList()),
  40. blasModels(0),
  41. worldTLAS(0),
  42. worldShaderBindingTables(0),
  43. lastTLASId(-1),
  44. lastModelId(-1),
  45. defaultRenderTarget(0),
  46. defaultKamera(0),
  47. cameraCount(0),
  48. device(0),
  49. pfnD3D12SerializeRootSignature(0),
  50. pipeline(0),
  51. globalDescriptorHeap(0),
  52. defaultHitGroup(0),
  53. defaultRayGenerationShaderFunction(0),
  54. tlasInputOffset(0)
  55. {
  56. for (int i = 0; i < 2; i++)
  57. backBuffer[i] = 0;
  58. }
  59. DirectX12::~DirectX12()
  60. {
  61. if (blasModels)
  62. {
  63. for (int i = 0; i <= lastModelId; i++)
  64. {
  65. if (blasModels[i]) blasModels[i]->release();
  66. }
  67. delete[] blasModels;
  68. }
  69. if (worldTLAS)
  70. {
  71. for (int i = 0; i <= lastTLASId; i++)
  72. {
  73. if (worldTLAS[i]) worldTLAS[i]->release();
  74. }
  75. delete[] worldTLAS;
  76. }
  77. if (worldShaderBindingTables)
  78. {
  79. for (int i = 0; i <= lastTLASId; i++)
  80. {
  81. if (worldShaderBindingTables[i])
  82. worldShaderBindingTables[i]->release();
  83. }
  84. delete[] worldShaderBindingTables;
  85. }
  86. if (globalDescriptorHeap)
  87. {
  88. globalDescriptorHeap->release();
  89. }
  90. if (pipeline)
  91. {
  92. pipeline->release();
  93. }
  94. if (directCommandQueue)
  95. {
  96. directCommandQueue->flush();
  97. directCommandQueue->release();
  98. }
  99. texturRegister->release();
  100. if (uiTexture) uiTexture->release();
  101. if (defaultKamera) defaultKamera->release();
  102. if (defaultRenderTarget) defaultRenderTarget->release();
  103. if (signature) signature->Release();
  104. delete allowedRenderArea;
  105. delete viewPort;
  106. for (int i = 0; i < 2; i++)
  107. {
  108. if (backBuffer[i]) backBuffer[i]->Release();
  109. }
  110. if (swapChain) swapChain->Release();
  111. if (infoQueue) infoQueue->Release();
  112. if (device)
  113. {
  114. device->Release();
  115. getDLLRegister()->releaseDLL("dxgi.dll");
  116. getDLLRegister()->releaseDLL("d3d12.dll");
  117. }
  118. if (debug) debug->Release();
  119. }
  120. void DirectX12::updateBottomLevelAccelerationStructure()
  121. {
  122. bool updateRequired = 0;
  123. for (const Model3DData* model : *modelList->zModels())
  124. {
  125. if (model->wasIndexBufferChanged() || model->wasVertexBufferChanged())
  126. {
  127. updateRequired = true;
  128. break;
  129. }
  130. }
  131. int bufferCount = 0;
  132. if (updateRequired)
  133. {
  134. for (const Model3DData* model : *modelList->zModels())
  135. {
  136. int id = model->getId();
  137. blasModels[id]->calculateBuffers();
  138. bufferCount += blasModels[id]->getBufferCount();
  139. }
  140. directCommandQueue
  141. ->execute(); // TODO: check if this is realy necessary
  142. // here, because maybe the command list is
  143. // executed in the render function anyway
  144. }
  145. }
  146. void Framework::DirectX12::renderKamera(
  147. Cam3D* zKamera, DX12Texture* zTarget, bool guiVisible)
  148. {
  149. if (guiVisible)
  150. {
  151. uiTexture->updateTextur();
  152. }
  153. if (!pipeline)
  154. {
  155. setPipeline(new DX12Pipeline());
  156. }
  157. directCommandQueue->zCommandList()->RSSetViewports(
  158. 1, (D3D12_VIEWPORT*)zKamera->zViewPort());
  159. Mat4<float> identity = Mat4<float>::identity();
  160. World3D* w = zKamera->zWorld();
  161. if (w->getId() < 0)
  162. {
  163. w->setId(++lastTLASId);
  164. DX12TLAS** tmp = new DX12TLAS*[lastTLASId + 1];
  165. if (lastTLASId)
  166. {
  167. memcpy(tmp, worldTLAS, sizeof(DX12TLAS*) * lastTLASId);
  168. }
  169. tmp[lastTLASId] = new DX12TLAS(device, directCommandQueue);
  170. delete[] worldTLAS;
  171. worldTLAS = tmp;
  172. DX12ShaderBindingTable** tmpsbts
  173. = new DX12ShaderBindingTable*[lastTLASId + 1];
  174. if (lastTLASId)
  175. {
  176. memcpy(tmpsbts,
  177. worldShaderBindingTables,
  178. sizeof(DX12ShaderBindingTable*) * lastTLASId);
  179. }
  180. tmpsbts[lastTLASId] = pipeline->createShaderBindingTable();
  181. delete[] worldShaderBindingTables;
  182. worldShaderBindingTables = tmpsbts;
  183. }
  184. else if (worldShaderBindingTables[w->getId()]->zPipeline() != pipeline)
  185. {
  186. worldShaderBindingTables[w->getId()]->release();
  187. worldShaderBindingTables[w->getId()]
  188. = pipeline->createShaderBindingTable();
  189. }
  190. DX12TLAS* tlas = worldTLAS[w->getId()];
  191. DX12ShaderBindingTable* sbt = worldShaderBindingTables[w->getId()];
  192. tlas->startUpdate();
  193. sbt->startUpdate();
  194. int objectIndex = 0;
  195. int instanceIndex = 0;
  196. w->render([this, &tlas, &objectIndex, &instanceIndex, &identity, &sbt](
  197. Model3D* obj) {
  198. obj->calculateMatrices(identity, matrixBuffer);
  199. int modelId = obj->zModelData()->getId();
  200. DX12BLASModel* blasModel = blasModels[modelId];
  201. ArrayIterator<int> boneIds = blasModel->zBoneIds()->begin();
  202. for (const DX12BLAS* blas : *blasModel->zBLAS())
  203. {
  204. D3D12_RAYTRACING_INSTANCE_DESC* desc = tlas->nextInstanceDesc();
  205. desc->InstanceID = objectIndex;
  206. desc->InstanceContributionToHitGroupIndex = objectIndex;
  207. desc->Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
  208. desc->InstanceMask = 0xFF;
  209. desc->AccelerationStructure
  210. = blas->zResultBuffer()->zBuffer()->GetGPUVirtualAddress();
  211. memcpy(desc->Transform,
  212. &matrixBuffer[boneIds.val()],
  213. sizeof(float) * 12);
  214. boneIds++;
  215. instanceIndex++;
  216. }
  217. fillShaderBindingTable(sbt, obj, objectIndex);
  218. objectIndex++;
  219. });
  220. tlas->endUpdate();
  221. if (defaultRayGenerationShaderFunction)
  222. {
  223. globalDescriptorHeap->updateTextureInput(
  224. 0, DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, zTarget);
  225. sbt->setShaderInput(defaultRayGenerationShaderFunction,
  226. tlasInputOffset,
  227. tlas->zResultBuffer()->zBuffer()->GetGPUVirtualAddress());
  228. }
  229. sbt->setGlobalDescriptorHeap(dynamic_cast<DX12GlobalDescriptorHeap*>(
  230. globalDescriptorHeap->getThis()));
  231. sbt->endUpdate(device, directCommandQueue);
  232. ID3D12DescriptorHeap* heaps[] = {globalDescriptorHeap->zDescriptorHeap()};
  233. directCommandQueue->zCommandList()->SetDescriptorHeaps(1, heaps);
  234. D3D12_DISPATCH_RAYS_DESC desc;
  235. sbt->fillDispatchRaysDesc(&desc);
  236. desc.Width = zTarget->zImage()->getWidth();
  237. desc.Height = zTarget->zImage()->getHeight();
  238. desc.Depth = 1;
  239. directCommandQueue->zCommandList()->SetPipelineState1(
  240. pipeline->zPipelineState());
  241. directCommandQueue->zCommandList()->DispatchRays(&desc);
  242. }
  243. void Framework::DirectX12::initializePipeline()
  244. {
  245. if (pipeline->getShaders().getEntryCount() == 0)
  246. { // add default shaders
  247. DX12Shader* rayGenShader
  248. = new DX12Shader(DX12DefaultRayGenerationShaderBytes,
  249. sizeof(DX12DefaultRayGenerationShaderBytes));
  250. // RayGen from RayGen.hlsl
  251. DX12ShaderSignature* rayGenSignature = new DX12ShaderSignature();
  252. rayGenSignature->addRegisterUsageLinkedToDescriptorHeap(
  253. 0, DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, 0);
  254. rayGenSignature->addRegisterUsageLinkedToDescriptorHeap(
  255. 1, DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, 1);
  256. tlasInputOffset
  257. = rayGenSignature->addRegisterUsageLinkedToShaderBindingTable(
  258. DX12_SHADER_REGISTER_T_SHADER_RESOURCE, 0);
  259. defaultRayGenerationShaderFunction = new DX12ShaderFunction(
  260. "RayGen", rayGenSignature, DX12_SHADER_FUNCTION_TYPE_RAY_GEN);
  261. rayGenShader->addFunction(defaultRayGenerationShaderFunction);
  262. pipeline->addShader(rayGenShader);
  263. DX12Shader* missShader = new DX12Shader(
  264. DX12DefaultMissShaderBytes, sizeof(DX12DefaultMissShaderBytes));
  265. // Miss from Miss.hlsl
  266. missShader->addFunction(new DX12ShaderFunction(
  267. "Miss", new DX12ShaderSignature(), DX12_SHADER_FUNCTION_TYPE_MISS));
  268. pipeline->addShader(missShader);
  269. DX12Shader* hitShader = new DX12Shader(
  270. DX12DefaultHitShaderBytes, sizeof(DX12DefaultHitShaderBytes));
  271. // ClosestHit from Hit.hlsl
  272. DX12ShaderFunction* closestHitFunction
  273. = new DX12ShaderFunction("ClosestHit",
  274. new DX12ShaderSignature(),
  275. DX12_SHADER_FUNCTION_TYPE_CLOSEST_HIT);
  276. hitShader->addFunction(closestHitFunction);
  277. pipeline->addShader(hitShader);
  278. defaultHitGroup = new DX12ShaderHitGroup("HitGroup");
  279. defaultHitGroup->setAttributeSize(8);
  280. defaultHitGroup->setPayloadSize(16);
  281. defaultHitGroup->setClosestHitShaderFunction(closestHitFunction);
  282. pipeline->addHitGroup(defaultHitGroup);
  283. }
  284. pipeline->createPipelineState(device, pfnD3D12SerializeRootSignature);
  285. }
  286. void Framework::DirectX12::initializeGlobalDescriptorHeap()
  287. {
  288. globalDescriptorHeap->addTextureInput(
  289. DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, defaultRenderTarget);
  290. globalDescriptorHeap->addTextureInput(
  291. DX12_SHADER_REGISTER_U_UNORDERED_ACCESS, uiTexture);
  292. globalDescriptorHeap->updateDescriptorHeap(device);
  293. }
  294. void Framework::DirectX12::fillShaderBindingTable(
  295. DX12ShaderBindingTable* zShaderBindingTable,
  296. Model3D* zModel,
  297. int instanceIndex)
  298. {
  299. if (defaultHitGroup)
  300. {
  301. zShaderBindingTable->addHitGroup(defaultHitGroup);
  302. }
  303. }
  304. typedef HRESULT(__stdcall* CreateDXGIFactory2Function)(UINT, REFIID, void**);
  305. typedef HRESULT(__stdcall* D3D12CreateDeviceFunction)(
  306. IDXGIAdapter*, D3D_FEATURE_LEVEL, REFIID, void**);
  307. typedef HRESULT(__stdcall* D3D12GetDebugInterfaceFunction)(REFIID, void**);
  308. typedef HRESULT(__stdcall* DXGIGetDebugInterface1Function)(
  309. UINT Flags, REFIID riid, _COM_Outptr_ void** pDebug);
  310. void DirectX12::initialize(
  311. NativeWindow* fenster, Vec2<int> backBufferSize, bool fullScreen)
  312. {
  313. GraphicsApi::initialize(fenster, backBufferSize, fullScreen);
  314. HINSTANCE dxgiDLL = getDLLRegister()->loadDLL("dxgi.dll", "dxgi.dll");
  315. if (!dxgiDLL)
  316. {
  317. WMessageBox(fenster->getWindowHandle(),
  318. new Text("Fehler"),
  319. new Text("dxgi.dll konnte nicht gefunden werden."),
  320. MB_ICONERROR);
  321. return;
  322. }
  323. HINSTANCE d3d12DLL = getDLLRegister()->loadDLL("d3d12.dll", "d3d12.dll");
  324. if (!d3d12DLL)
  325. {
  326. getDLLRegister()->releaseDLL("dxgi.dll");
  327. WMessageBox(fenster->getWindowHandle(),
  328. new Text("Fehler"),
  329. new Text("DirectX 12 konnte nicht gefunden werden."),
  330. MB_ICONERROR);
  331. return;
  332. }
  333. pfnD3D12SerializeRootSignature
  334. = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress(
  335. d3d12DLL, "D3D12SerializeRootSignature");
  336. if (!pfnD3D12SerializeRootSignature)
  337. {
  338. getDLLRegister()->releaseDLL("dxgi.dll");
  339. getDLLRegister()->releaseDLL("d3d12.dll");
  340. WMessageBox(fenster->getWindowHandle(),
  341. new Text("Fehler"),
  342. new Text(
  343. "Der Einstiegspunkt D3D12SerializeRootSignature fon d3d12.dll "
  344. "konnte nicht gefunden werden."),
  345. MB_ICONERROR);
  346. return;
  347. }
  348. // CreateDXGIFactory2
  349. CreateDXGIFactory2Function createFactory
  350. = (CreateDXGIFactory2Function)GetProcAddress(
  351. dxgiDLL, "CreateDXGIFactory2");
  352. if (!createFactory)
  353. {
  354. getDLLRegister()->releaseDLL("dxgi.dll");
  355. getDLLRegister()->releaseDLL("d3d12.dll");
  356. WMessageBox(fenster->getWindowHandle(),
  357. new Text("Fehler"),
  358. new Text(
  359. "Der Einstiegspunkt CreateDXGIFactory2 fon dxgi.dll konnte "
  360. "nicht gefunden werden."),
  361. MB_ICONERROR);
  362. return;
  363. }
  364. // D3D12CreateDevice
  365. D3D12CreateDeviceFunction createDevice
  366. = (D3D12CreateDeviceFunction)GetProcAddress(
  367. d3d12DLL, "D3D12CreateDevice");
  368. if (!createDevice)
  369. {
  370. getDLLRegister()->releaseDLL("dxgi.dll");
  371. getDLLRegister()->releaseDLL("d3d12.dll");
  372. WMessageBox(fenster->getWindowHandle(),
  373. new Text("Fehler"),
  374. new Text("Der Einstiegspunkt D3D12CreateDevice fon DirectX 12 "
  375. "konnte nicht gefunden werden."),
  376. MB_ICONERROR);
  377. return;
  378. }
  379. // D3D12SerializeVersionedRootSignature
  380. PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d12svrsf
  381. = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)GetProcAddress(
  382. d3d12DLL, "D3D12SerializeVersionedRootSignature");
  383. // D3D12SerializeRootSignature
  384. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d12srsf
  385. = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress(
  386. d3d12DLL, "D3D12SerializeRootSignature");
  387. bool debugDXGI = 0;
  388. #ifdef _DEBUG
  389. IDXGIInfoQueue* dxgiInfoQueue;
  390. if (debugDX)
  391. {
  392. // D3D12GetDebugInterface
  393. D3D12GetDebugInterfaceFunction getDebugInterface
  394. = (D3D12GetDebugInterfaceFunction)GetProcAddress(
  395. d3d12DLL, "D3D12GetDebugInterface");
  396. if (SUCCEEDED(getDebugInterface(__uuidof(ID3D12Debug), (void**)&debug)))
  397. debug->EnableDebugLayer();
  398. // DXGIGetDebugInterface1
  399. DXGIGetDebugInterface1Function dxgiDebugInterface
  400. = (DXGIGetDebugInterface1Function)GetProcAddress(
  401. dxgiDLL, "DXGIGetDebugInterface1");
  402. if (SUCCEEDED(dxgiDebugInterface(
  403. 0, __uuidof(IDXGIInfoQueue), (void**)&dxgiInfoQueue)))
  404. debugDXGI = 1;
  405. }
  406. #endif
  407. IDXGIFactory6* factory;
  408. UINT createFactoryFlags = 0;
  409. #if defined(_DEBUG)
  410. if (debugDX && debugDXGI) createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG;
  411. #endif
  412. HRESULT res = createFactory(
  413. createFactoryFlags, __uuidof(IDXGIFactory6), (void**)&factory);
  414. if (FAILED(res))
  415. {
  416. getDLLRegister()->releaseDLL("dxgi.dll");
  417. getDLLRegister()->releaseDLL("d3d12.dll");
  418. Logging::error() << "ERROR DXGI: createFactory returned " << res
  419. << "\n";
  420. WMessageBox(fenster->getWindowHandle(),
  421. new Text("Fehler"),
  422. new Text("createFactory ist Fehlgeschlagen."),
  423. MB_ICONERROR);
  424. return;
  425. }
  426. IDXGIAdapter1* adapter = 0;
  427. for (UINT adapterID = 0; DXGI_ERROR_NOT_FOUND
  428. != factory->EnumAdapterByGpuPreference(adapterID,
  429. DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
  430. __uuidof(IDXGIAdapter1),
  431. (void**)&adapter);
  432. ++adapterID)
  433. {
  434. DXGI_ADAPTER_DESC1 desc;
  435. adapter->GetDesc1(&desc);
  436. if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
  437. {
  438. adapter->Release();
  439. // Don't select the Basic Render Driver adapter.
  440. continue;
  441. }
  442. // Check to see if the adapter supports Direct3D 12, but don't create
  443. // the actual device yet.
  444. if (SUCCEEDED(createDevice(adapter,
  445. D3D_FEATURE_LEVEL_12_1,
  446. _uuidof(ID3D12Device),
  447. nullptr)))
  448. {
  449. char buff[256] = {};
  450. printf_s(buff,
  451. L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n",
  452. adapterID,
  453. desc.VendorId,
  454. desc.DeviceId,
  455. desc.Description);
  456. Logging::info() << buff;
  457. break;
  458. }
  459. adapter->Release();
  460. }
  461. if (!adapter)
  462. {
  463. if (FAILED(factory->EnumWarpAdapter(
  464. _uuidof(IDXGIAdapter1), (void**)&adapter)))
  465. Logging::error()
  466. << "ERROR: WARP12 not available. Enable the 'Graphics "
  467. "Tools' optional feature";
  468. }
  469. if (!adapter)
  470. {
  471. factory->Release();
  472. getDLLRegister()->releaseDLL("dxgi.dll");
  473. getDLLRegister()->releaseDLL("d3d12.dll");
  474. WMessageBox(fenster->getWindowHandle(),
  475. new Text("Fehler"),
  476. new Text("Es wurde keine passende Grafigkarte gefunden."),
  477. MB_ICONERROR);
  478. return;
  479. }
  480. res = createDevice(adapter,
  481. D3D_FEATURE_LEVEL_12_1,
  482. __uuidof(ID3D12Device5),
  483. (void**)&device);
  484. adapter->Release();
  485. if (FAILED(res))
  486. {
  487. factory->Release();
  488. getDLLRegister()->releaseDLL("dxgi.dll");
  489. getDLLRegister()->releaseDLL("d3d12.dll");
  490. Logging::error() << "ERROR: createDevice returned " << res << "\n";
  491. WMessageBox(fenster->getWindowHandle(),
  492. new Text("Fehler"),
  493. new Text("createDevice ist Fehlgeschlagen."),
  494. MB_ICONERROR);
  495. return;
  496. }
  497. D3D12_FEATURE_DATA_D3D12_OPTIONS5 featureSupportData = {};
  498. device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5,
  499. &featureSupportData,
  500. sizeof(featureSupportData));
  501. if (featureSupportData.RaytracingTier < D3D12_RAYTRACING_TIER_1_0)
  502. {
  503. device->Release();
  504. factory->Release();
  505. getDLLRegister()->releaseDLL("dxgi.dll");
  506. getDLLRegister()->releaseDLL("d3d12.dll");
  507. Logging::error() << "ERROR: Raytracing is not available\n";
  508. WMessageBox(fenster->getWindowHandle(),
  509. new Text("Fehler"),
  510. new Text("Raytracing ist nicht verfügbar. DirectX12 kann nicht "
  511. "verwendet werden."),
  512. MB_ICONERROR);
  513. return;
  514. }
  515. res = device->QueryInterface(__uuidof(ID3D12InfoQueue), (void**)&infoQueue);
  516. if (SUCCEEDED(res))
  517. {
  518. if (debugDX)
  519. {
  520. infoQueue->SetBreakOnSeverity(
  521. D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
  522. infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
  523. infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
  524. }
  525. // Suppress individual messages by their ID
  526. D3D12_MESSAGE_ID DenyIds[] = {
  527. // D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE, //
  528. // I'm really not sure how to avoid this message.
  529. D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, // This warning occurs when
  530. // using capture frame while
  531. // graphics debugging.
  532. D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE, // This warning occurs
  533. // when using capture
  534. // frame while graphics
  535. // debugging.
  536. };
  537. D3D12_INFO_QUEUE_FILTER NewFilter = {};
  538. NewFilter.DenyList.NumSeverities = 0; //_countof( Severities );
  539. NewFilter.DenyList.pSeverityList = 0; // Severities;
  540. NewFilter.DenyList.NumIDs = _countof(DenyIds);
  541. NewFilter.DenyList.pIDList = DenyIds;
  542. infoQueue->PushStorageFilter(&NewFilter);
  543. }
  544. directCommandQueue = new DX12DirectCommandQueue(device);
  545. IDXGIFactory5* fac5 = 0;
  546. factory->QueryInterface(__uuidof(IDXGIFactory5), (void**)&fac5);
  547. if (fac5)
  548. {
  549. res = fac5->CheckFeatureSupport(
  550. DXGI_FEATURE_PRESENT_ALLOW_TEARING, &tearing, sizeof(tearing));
  551. if (FAILED(res)) tearing = 0;
  552. fac5->Release();
  553. }
  554. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
  555. swapChainDesc.Width = backBufferSize.x;
  556. swapChainDesc.Height = backBufferSize.y;
  557. swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
  558. swapChainDesc.Stereo = FALSE;
  559. swapChainDesc.SampleDesc = {1, 0};
  560. swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  561. swapChainDesc.BufferCount = 2;
  562. swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
  563. swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
  564. swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
  565. swapChainDesc.Flags = tearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
  566. IDXGISwapChain1* tmpSwapChain;
  567. res = factory->CreateSwapChainForHwnd(directCommandQueue->zQueue(),
  568. fenster->getWindowHandle(),
  569. &swapChainDesc,
  570. 0,
  571. 0,
  572. &tmpSwapChain);
  573. if (FAILED(res))
  574. {
  575. factory->Release();
  576. Logging::error() << "ERROR: CreateSwapChainForHwnd returned " << res
  577. << "\n";
  578. WMessageBox(fenster->getWindowHandle(),
  579. new Text("Fehler"),
  580. new Text("CreateSwapChainForHwnd ist Fehlgeschlagen."),
  581. MB_ICONERROR);
  582. return;
  583. }
  584. res = tmpSwapChain->QueryInterface(
  585. __uuidof(IDXGISwapChain4), (void**)&swapChain);
  586. tmpSwapChain->Release();
  587. if (FAILED(res))
  588. {
  589. factory->Release();
  590. Logging::error() << "ERROR: QueryInterface returned " << res << "\n";
  591. WMessageBox(fenster->getWindowHandle(),
  592. new Text("Fehler"),
  593. new Text("QueryInterface ist Fehlgeschlagen."),
  594. MB_ICONERROR);
  595. return;
  596. }
  597. factory->MakeWindowAssociation(
  598. fenster->getWindowHandle(), DXGI_MWA_NO_ALT_ENTER);
  599. for (int i = 0; i < 2; i++)
  600. {
  601. ID3D12Resource* backBuffer;
  602. res = swapChain->GetBuffer(
  603. i, __uuidof(ID3D12Resource), (void**)&backBuffer);
  604. if (FAILED(res))
  605. {
  606. factory->Release();
  607. Logging::error() << "ERROR: GetBuffer returned " << res << "\n";
  608. WMessageBox(fenster->getWindowHandle(),
  609. new Text("Fehler"),
  610. new Text("GetBuffer ist Fehlgeschlagen."),
  611. MB_ICONERROR);
  612. return;
  613. }
  614. this->backBuffer[i] = backBuffer;
  615. }
  616. Image* renderTargetImage = new Image();
  617. renderTargetImage->newImage(backBufferSize.x, backBufferSize.y, 0);
  618. defaultRenderTarget = dynamic_cast<DX12Texture*>(
  619. createOrGetTexture("_f_RenderTarget", renderTargetImage, GPU_TO_RAM));
  620. defaultRenderTarget->updateTextur();
  621. viewPort = new D3D12_VIEWPORT();
  622. viewPort->Width = (float)this->backBufferSize.x;
  623. viewPort->Height = (float)this->backBufferSize.y;
  624. viewPort->MinDepth = 0.0f;
  625. viewPort->MaxDepth = 1.0f;
  626. viewPort->TopLeftX = 0.0f;
  627. viewPort->TopLeftY = 0.0f;
  628. allowedRenderArea = new D3D12_RECT();
  629. allowedRenderArea->left = 0;
  630. allowedRenderArea->top = 0;
  631. allowedRenderArea->right = LONG_MAX;
  632. allowedRenderArea->bottom = LONG_MAX;
  633. Image* renderB = new Image(1);
  634. renderB->setAlpha3D(1);
  635. renderB->newImage(this->backBufferSize.x, this->backBufferSize.y, 0);
  636. uiTexture = createOrGetTexture("_f_Render_Image", renderB, RAM_TO_GPU);
  637. D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {};
  638. featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1;
  639. if (FAILED(device->CheckFeatureSupport(
  640. D3D12_FEATURE_ROOT_SIGNATURE, &featureData, sizeof(featureData))))
  641. featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
  642. D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags
  643. = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT
  644. | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS
  645. | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS
  646. | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
  647. D3D12_DESCRIPTOR_RANGE1 range[2];
  648. range[0].NumDescriptors = 5;
  649. range[0].BaseShaderRegister = 0;
  650. range[0].RegisterSpace = 0;
  651. range[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
  652. range[0].OffsetInDescriptorsFromTableStart
  653. = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
  654. range[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
  655. range[1].NumDescriptors = 1;
  656. range[1].BaseShaderRegister = 0;
  657. range[1].RegisterSpace = 0;
  658. range[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
  659. range[1].OffsetInDescriptorsFromTableStart
  660. = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
  661. range[1].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
  662. D3D12_ROOT_PARAMETER1 rootParameters[1];
  663. rootParameters[0].ParameterType
  664. = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
  665. rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  666. rootParameters[0].DescriptorTable.NumDescriptorRanges = 2;
  667. rootParameters[0].DescriptorTable.pDescriptorRanges = range;
  668. D3D12_STATIC_SAMPLER_DESC sampler = {};
  669. sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
  670. sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
  671. sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
  672. sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
  673. sampler.MipLODBias = 0;
  674. sampler.MaxAnisotropy = 0;
  675. sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
  676. sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
  677. sampler.MinLOD = 0.0f;
  678. sampler.MaxLOD = D3D12_FLOAT32_MAX;
  679. sampler.ShaderRegister = 0;
  680. sampler.RegisterSpace = 0;
  681. sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
  682. D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDescription;
  683. rootSignatureDescription.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;
  684. rootSignatureDescription.Desc_1_1.NumParameters = 1;
  685. rootSignatureDescription.Desc_1_1.pParameters = rootParameters;
  686. rootSignatureDescription.Desc_1_1.NumStaticSamplers = 1;
  687. rootSignatureDescription.Desc_1_1.pStaticSamplers = &sampler;
  688. rootSignatureDescription.Desc_1_1.Flags = rootSignatureFlags;
  689. ID3DBlob* rootSignature;
  690. ID3DBlob* error;
  691. res = D3DX12SerializeVersionedRootSignature(&rootSignatureDescription,
  692. featureData.HighestVersion,
  693. &rootSignature,
  694. &error,
  695. d3d12svrsf,
  696. d3d12srsf);
  697. if (FAILED(res))
  698. {
  699. factory->Release();
  700. Logging::error()
  701. << "ERROR: D3DX12SerializeVersionedRootSignature returned " << res
  702. << "\n";
  703. WMessageBox(fenster->getWindowHandle(),
  704. new Text("Fehler"),
  705. new Text(
  706. "D3DX12SerializeVersionedRootSignature ist Fehlgeschlagen."),
  707. MB_ICONERROR);
  708. if (error) error->Release();
  709. return;
  710. }
  711. res = device->CreateRootSignature(0,
  712. rootSignature->GetBufferPointer(),
  713. rootSignature->GetBufferSize(),
  714. __uuidof(ID3D12RootSignature),
  715. (void**)&signature);
  716. if (FAILED(res))
  717. {
  718. factory->Release();
  719. Logging::error() << "ERROR: CreateRootSignature returned " << res
  720. << "\n";
  721. WMessageBox(fenster->getWindowHandle(),
  722. new Text("Fehler"),
  723. new Text("CreateRootSignature ist Fehlgeschlagen."),
  724. MB_ICONERROR);
  725. return;
  726. }
  727. rootSignature->Release();
  728. D3D12_RASTERIZER_DESC rdesc;
  729. rdesc.FillMode = D3D12_FILL_MODE_SOLID;
  730. rdesc.CullMode = D3D12_CULL_MODE_BACK;
  731. rdesc.FrontCounterClockwise = 0;
  732. rdesc.DepthBias = 0;
  733. rdesc.DepthBiasClamp = 0.f;
  734. rdesc.SlopeScaledDepthBias = 0.f;
  735. rdesc.DepthClipEnable = 1;
  736. rdesc.MultisampleEnable = 0;
  737. rdesc.AntialiasedLineEnable = 0;
  738. rdesc.ForcedSampleCount = 0;
  739. rdesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
  740. uiTexture->updateTextur();
  741. directCommandQueue->execute();
  742. factory->Release();
  743. }
  744. void DirectX12::beginFrame(bool fill2D, bool fill3D, int fillColor)
  745. {
  746. cameraCount = 0;
  747. D3D12_RESOURCE_BARRIER barrier;
  748. ZeroMemory(&barrier, sizeof(barrier));
  749. barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
  750. barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
  751. barrier.Transition.pResource = this->backBuffer[backBufferIndex];
  752. barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
  753. barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
  754. barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
  755. directCommandQueue->zCommandList()->ResourceBarrier(1, &barrier);
  756. if (fill2D) uiTexture->zImage()->setColor(fillColor);
  757. CD3DX12_RESOURCE_BARRIER transition
  758. = CD3DX12_RESOURCE_BARRIER::Transition(defaultRenderTarget->zResource(),
  759. D3D12_RESOURCE_STATE_COPY_SOURCE,
  760. D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
  761. directCommandQueue->zCommandList()->ResourceBarrier(1, &transition);
  762. }
  763. void DirectX12::renderKamera(Cam3D* zKamera)
  764. {
  765. cameraCount++;
  766. renderKamera(zKamera, defaultRenderTarget, true);
  767. }
  768. void Framework::DirectX12::renderKamera(Cam3D* zKamera, Texture* zTarget)
  769. {
  770. cameraCount++;
  771. renderKamera(zKamera, dynamic_cast<DX12Texture*>(zTarget), false);
  772. }
  773. void DirectX12::presentFrame()
  774. {
  775. if (cameraCount == 0)
  776. {
  777. if (!defaultKamera)
  778. {
  779. defaultKamera = new Cam3D();
  780. defaultKamera->setWorld(new World3D());
  781. defaultKamera->setScreenSize(backBufferSize);
  782. }
  783. renderKamera(defaultKamera);
  784. }
  785. CD3DX12_RESOURCE_BARRIER transition
  786. = CD3DX12_RESOURCE_BARRIER::Transition(defaultRenderTarget->zResource(),
  787. D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
  788. D3D12_RESOURCE_STATE_COPY_SOURCE);
  789. directCommandQueue->zCommandList()->ResourceBarrier(1, &transition);
  790. transition
  791. = CD3DX12_RESOURCE_BARRIER::Transition(backBuffer[backBufferIndex],
  792. D3D12_RESOURCE_STATE_RENDER_TARGET,
  793. D3D12_RESOURCE_STATE_COPY_DEST);
  794. directCommandQueue->zCommandList()->ResourceBarrier(1, &transition);
  795. directCommandQueue->zCommandList()->CopyResource(
  796. backBuffer[backBufferIndex], defaultRenderTarget->zResource());
  797. transition
  798. = CD3DX12_RESOURCE_BARRIER::Transition(backBuffer[backBufferIndex],
  799. D3D12_RESOURCE_STATE_COPY_DEST,
  800. D3D12_RESOURCE_STATE_RENDER_TARGET);
  801. directCommandQueue->zCommandList()->ResourceBarrier(1, &transition);
  802. // Indicate that the back buffer will now be used to present.
  803. transition
  804. = CD3DX12_RESOURCE_BARRIER::Transition(backBuffer[backBufferIndex],
  805. D3D12_RESOURCE_STATE_RENDER_TARGET,
  806. D3D12_RESOURCE_STATE_PRESENT);
  807. directCommandQueue->zCommandList()->ResourceBarrier(1, &transition);
  808. directCommandQueue->execute();
  809. swapChain->Present(0, 0);
  810. backBufferIndex = swapChain->GetCurrentBackBufferIndex();
  811. }
  812. Texture* DirectX12::createOrGetTexture(
  813. const char* name, Image* b, TextureDirection dir)
  814. {
  815. if (!device)
  816. {
  817. if (b) b->release();
  818. return 0;
  819. }
  820. if (texturRegister->hasTexture(name))
  821. {
  822. Texture* ret = texturRegister->getTexture(name);
  823. if (b) ret->setImageZ(b);
  824. return ret;
  825. }
  826. Texture* ret = new DX12Texture(device, directCommandQueue, dir);
  827. if (b) ret->setImageZ(b);
  828. texturRegister->addTexture(dynamic_cast<Texture*>(ret->getThis()), name);
  829. ret->updateTextur();
  830. directCommandQueue->execute();
  831. return ret;
  832. }
  833. Image* DirectX12::zUIRenderImage() const
  834. {
  835. return uiTexture ? uiTexture->zImage() : 0;
  836. }
  837. DXBuffer* DirectX12::createStructuredBuffer(int eSize)
  838. {
  839. return new DX12Buffer(eSize,
  840. device,
  841. dynamic_cast<DX12CommandQueue*>(directCommandQueue->getThis()),
  842. D3D12_RESOURCE_FLAG_NONE);
  843. }
  844. void Framework::DirectX12::setPipeline(DX12Pipeline* pipeline)
  845. {
  846. if (this->pipeline)
  847. {
  848. this->pipeline->release();
  849. }
  850. this->pipeline = pipeline;
  851. if (pipeline)
  852. {
  853. initializePipeline();
  854. if (!globalDescriptorHeap
  855. || globalDescriptorHeap->zPipeline() != pipeline)
  856. {
  857. if (globalDescriptorHeap)
  858. {
  859. globalDescriptorHeap->release();
  860. }
  861. globalDescriptorHeap = pipeline->createGlobalDescriptorHeap();
  862. initializeGlobalDescriptorHeap();
  863. }
  864. }
  865. }
  866. bool DirectX12::isAvailable()
  867. {
  868. HINSTANCE dxgiDLL = getDLLRegister()->loadDLL("dxgi.dll", "dxgi.dll");
  869. if (!dxgiDLL) return 0;
  870. HINSTANCE d3d12DLL = getDLLRegister()->loadDLL("d3d12.dll", "d3d12.dll");
  871. if (!d3d12DLL)
  872. {
  873. getDLLRegister()->releaseDLL("dxgi.dll");
  874. return 0;
  875. }
  876. CreateDXGIFactory2Function createFactory
  877. = (CreateDXGIFactory2Function)GetProcAddress(
  878. dxgiDLL, "CreateDXGIFactory2");
  879. if (!createFactory)
  880. {
  881. getDLLRegister()->releaseDLL("dxgi.dll");
  882. getDLLRegister()->releaseDLL("d3d12.dll");
  883. return 0;
  884. }
  885. D3D12CreateDeviceFunction createDevice
  886. = (D3D12CreateDeviceFunction)GetProcAddress(
  887. d3d12DLL, "D3D12CreateDevice");
  888. if (!createDevice)
  889. {
  890. getDLLRegister()->releaseDLL("dxgi.dll");
  891. getDLLRegister()->releaseDLL("d3d12.dll");
  892. return 0;
  893. }
  894. #ifdef _DEBUG
  895. D3D12GetDebugInterfaceFunction getDebugInterface
  896. = (D3D12GetDebugInterfaceFunction)GetProcAddress(
  897. d3d12DLL, "D3D12GetDebugInterface");
  898. ID3D12Debug* debug = 0;
  899. getDebugInterface(__uuidof(ID3D12Debug), (void**)&debug);
  900. debug->EnableDebugLayer();
  901. #endif
  902. IDXGIFactory4* factory;
  903. UINT createFactoryFlags = 0;
  904. #ifdef _DEBUG
  905. createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG;
  906. #endif
  907. HRESULT res = createFactory(
  908. createFactoryFlags, __uuidof(IDXGIFactory4), (void**)&factory);
  909. if (FAILED(res))
  910. {
  911. getDLLRegister()->releaseDLL("dxgi.dll");
  912. getDLLRegister()->releaseDLL("d3d12.dll");
  913. return 0;
  914. }
  915. int index = 0;
  916. do
  917. {
  918. IDXGIAdapter1* current;
  919. res = factory->EnumAdapters1(index++, &current);
  920. if (res == S_OK)
  921. {
  922. DXGI_ADAPTER_DESC1 dxgiAdapterDesc1;
  923. current->GetDesc1(&dxgiAdapterDesc1);
  924. ID3D12Device5* device = 0;
  925. if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0
  926. && SUCCEEDED(createDevice(current,
  927. D3D_FEATURE_LEVEL_12_1,
  928. __uuidof(ID3D12Device5),
  929. (void**)&device)))
  930. {
  931. device->Release();
  932. current->Release();
  933. factory->Release();
  934. #ifdef _DEBUG
  935. debug->Release();
  936. #endif
  937. getDLLRegister()->releaseDLL("dxgi.dll");
  938. getDLLRegister()->releaseDLL("d3d12.dll");
  939. return 1;
  940. }
  941. current->Release();
  942. }
  943. } while (res != DXGI_ERROR_NOT_FOUND);
  944. factory->Release();
  945. getDLLRegister()->releaseDLL("dxgi.dll");
  946. getDLLRegister()->releaseDLL("d3d12.dll");
  947. return 0;
  948. }
  949. bool Framework::DirectX12::renderGuiBefore3D() const
  950. {
  951. return true;
  952. }