direct3d12_gpu.c 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888
  1. #define WIN32_LEAN_AND_MEAN
  2. #include <iron_global.h>
  3. #include <stdbool.h>
  4. #include <malloc.h>
  5. #include <math.h>
  6. #include <assert.h>
  7. #include <d3d12.h>
  8. #include <dxgi.h>
  9. #include <dxgi1_4.h>
  10. #include <iron_gpu.h>
  11. #include <iron_system.h>
  12. #include <iron_math.h>
  13. #include <backends/windows_system.h>
  14. bool gpu_transpose_mat = false;
  15. static ID3D12Device *device = NULL;
  16. static ID3D12CommandQueue *queue;
  17. static IDXGISwapChain *window_swapchain;
  18. static ID3D12RootSignature *root_signature = NULL;
  19. static ID3D12CommandAllocator *command_allocator;
  20. static ID3D12GraphicsCommandList *command_list;
  21. static gpu_pipeline_t *current_pipeline;
  22. static D3D12_VIEWPORT current_viewport;
  23. static D3D12_RECT current_scissor;
  24. static gpu_buffer_t *current_vb;
  25. static gpu_buffer_t *current_ib;
  26. static D3D12_CPU_DESCRIPTOR_HANDLE target_descriptors[GPU_MAX_TEXTURES];
  27. static D3D12_CPU_DESCRIPTOR_HANDLE depth_handle;
  28. static D3D12_CPU_DESCRIPTOR_HANDLE *current_depth_handle;
  29. static gpu_texture_t *current_textures[GPU_MAX_TEXTURES] = {
  30. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  31. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  32. };
  33. static bool window_vsync;
  34. static ID3D12DescriptorHeap *sampler_heap;
  35. static ID3D12DescriptorHeap *srv_heap;
  36. static int srv_heap_index = 0;
  37. static UINT64 fence_value;
  38. static ID3D12Fence *fence;
  39. static HANDLE fence_event;
  40. static UINT64 frame_fence_values[GPU_FRAMEBUFFER_COUNT] = {0, 0};
  41. static bool resized = false;
  42. static ID3D12Resource *readback_buffer = NULL;
  43. static int readback_buffer_size = 0;
  44. static ID3D12Resource *upload_buffer = NULL;
  45. static int upload_buffer_size = 0;
  46. static ID3D12Resource *resources_to_destroy[256];
  47. static int resources_to_destroy_count = 0;
  48. static char device_name[256];
  49. static D3D12_BLEND convert_blend_factor(gpu_blending_factor_t factor) {
  50. switch (factor) {
  51. case GPU_BLEND_ONE:
  52. return D3D12_BLEND_ONE;
  53. case GPU_BLEND_ZERO:
  54. return D3D12_BLEND_ZERO;
  55. case GPU_BLEND_SOURCE_ALPHA:
  56. return D3D12_BLEND_SRC_ALPHA;
  57. case GPU_BLEND_DEST_ALPHA:
  58. return D3D12_BLEND_DEST_ALPHA;
  59. case GPU_BLEND_INV_SOURCE_ALPHA:
  60. return D3D12_BLEND_INV_SRC_ALPHA;
  61. case GPU_BLEND_INV_DEST_ALPHA:
  62. return D3D12_BLEND_INV_DEST_ALPHA;
  63. }
  64. }
  65. static D3D12_CULL_MODE convert_cull_mode(gpu_cull_mode_t cull_mode) {
  66. switch (cull_mode) {
  67. case GPU_CULL_MODE_CLOCKWISE:
  68. return D3D12_CULL_MODE_FRONT;
  69. case GPU_CULL_MODE_COUNTERCLOCKWISE:
  70. return D3D12_CULL_MODE_BACK;
  71. default:
  72. return D3D12_CULL_MODE_NONE;
  73. }
  74. }
  75. static D3D12_COMPARISON_FUNC convert_compare_mode(gpu_compare_mode_t compare) {
  76. switch (compare) {
  77. default:
  78. case GPU_COMPARE_MODE_ALWAYS:
  79. return D3D12_COMPARISON_FUNC_ALWAYS;
  80. case GPU_COMPARE_MODE_NEVER:
  81. return D3D12_COMPARISON_FUNC_NEVER;
  82. case GPU_COMPARE_MODE_EQUAL:
  83. return D3D12_COMPARISON_FUNC_EQUAL;
  84. case GPU_COMPARE_MODE_LESS:
  85. return D3D12_COMPARISON_FUNC_LESS;
  86. }
  87. }
  88. static DXGI_FORMAT convert_format(gpu_texture_format_t format) {
  89. switch (format) {
  90. case GPU_TEXTURE_FORMAT_RGBA128:
  91. return DXGI_FORMAT_R32G32B32A32_FLOAT;
  92. case GPU_TEXTURE_FORMAT_RGBA64:
  93. return DXGI_FORMAT_R16G16B16A16_FLOAT;
  94. case GPU_TEXTURE_FORMAT_R32:
  95. return DXGI_FORMAT_R32_FLOAT;
  96. case GPU_TEXTURE_FORMAT_R16:
  97. return DXGI_FORMAT_R16_FLOAT;
  98. case GPU_TEXTURE_FORMAT_R8:
  99. return DXGI_FORMAT_R8_UNORM;
  100. case GPU_TEXTURE_FORMAT_D32:
  101. return DXGI_FORMAT_D32_FLOAT;
  102. case GPU_TEXTURE_FORMAT_RGBA32:
  103. default:
  104. return DXGI_FORMAT_R8G8B8A8_UNORM;
  105. }
  106. }
  107. static D3D12_RESOURCE_STATES convert_texture_state(gpu_texture_state_t state) {
  108. switch (state) {
  109. case GPU_TEXTURE_STATE_SHADER_RESOURCE:
  110. return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
  111. case GPU_TEXTURE_STATE_RENDER_TARGET:
  112. return D3D12_RESOURCE_STATE_RENDER_TARGET;
  113. case GPU_TEXTURE_STATE_RENDER_TARGET_DEPTH:
  114. return D3D12_RESOURCE_STATE_DEPTH_WRITE;
  115. case GPU_TEXTURE_STATE_PRESENT:
  116. return D3D12_RESOURCE_STATE_PRESENT;
  117. }
  118. }
  119. static void wait_for_fence(ID3D12Fence *fence, UINT64 completion_value, HANDLE wait_event) {
  120. if (fence->lpVtbl->GetCompletedValue(fence) < completion_value) {
  121. fence->lpVtbl->SetEventOnCompletion(fence, completion_value, wait_event);
  122. WaitForSingleObject(wait_event, INFINITE);
  123. }
  124. }
  125. static void _gpu_barrier(ID3D12Resource *r, D3D12_RESOURCE_STATES state_before, D3D12_RESOURCE_STATES state_after) {
  126. D3D12_RESOURCE_BARRIER barrier = {
  127. .Transition.pResource = r,
  128. .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
  129. .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
  130. .Transition.StateBefore = state_before,
  131. .Transition.StateAfter = state_after,
  132. .Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
  133. };
  134. command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier);
  135. }
  136. void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after) {
  137. if (render_target->state == state_after) {
  138. return;
  139. }
  140. _gpu_barrier(render_target->impl.image, convert_texture_state(render_target->state), convert_texture_state(state_after));
  141. render_target->state = state_after;
  142. }
  143. void gpu_destroy() {
  144. wait_for_fence(fence, fence_value, fence_event);
  145. for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) {
  146. gpu_texture_destroy_internal(&framebuffers[i]);
  147. }
  148. if (framebuffer_depth.width > 0) {
  149. gpu_texture_destroy_internal(&framebuffer_depth);
  150. }
  151. if (readback_buffer != NULL) {
  152. readback_buffer->lpVtbl->Release(readback_buffer);
  153. }
  154. if (upload_buffer != NULL) {
  155. upload_buffer->lpVtbl->Release(upload_buffer);
  156. }
  157. command_list->lpVtbl->Release(command_list);
  158. command_allocator->lpVtbl->Release(command_allocator);
  159. window_swapchain->lpVtbl->Release(window_swapchain);
  160. queue->lpVtbl->Release(queue);
  161. root_signature->lpVtbl->Release(root_signature);
  162. srv_heap->lpVtbl->Release(srv_heap);
  163. fence->lpVtbl->Release(fence);
  164. CloseHandle(fence_event);
  165. device->lpVtbl->Release(device);
  166. }
  167. void gpu_render_target_init2(gpu_texture_t *render_target, int width, int height, gpu_texture_format_t format, int framebuffer_index) {
  168. render_target->width = width;
  169. render_target->height = height;
  170. render_target->format = format;
  171. render_target->state = (framebuffer_index >= 0) ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE;
  172. render_target->buffer = NULL;
  173. DXGI_FORMAT dxgi_format = convert_format(format);
  174. D3D12_CLEAR_VALUE clear_value;
  175. clear_value.Format = dxgi_format;
  176. clear_value.Color[0] = 0.0f;
  177. clear_value.Color[1] = 0.0f;
  178. clear_value.Color[2] = 0.0f;
  179. clear_value.Color[3] = 0.0f;
  180. clear_value.DepthStencil.Depth = 1.0f;
  181. D3D12_HEAP_PROPERTIES heap_properties = {
  182. .Type = D3D12_HEAP_TYPE_DEFAULT,
  183. .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
  184. .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN,
  185. .CreationNodeMask = 1,
  186. .VisibleNodeMask = 1,
  187. };
  188. D3D12_RESOURCE_DESC resource_desc = {
  189. .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
  190. .Alignment = 0,
  191. .Width = width,
  192. .Height = height,
  193. .DepthOrArraySize = 1,
  194. .MipLevels = 1,
  195. .Format = dxgi_format,
  196. .SampleDesc.Count = 1,
  197. .SampleDesc.Quality = 0,
  198. .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
  199. .Flags = format == GPU_TEXTURE_FORMAT_D32 ? D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL : D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
  200. };
  201. D3D12_DESCRIPTOR_HEAP_DESC heap_desc = {
  202. .NumDescriptors = 1,
  203. .Type = format == GPU_TEXTURE_FORMAT_D32 ? D3D12_DESCRIPTOR_HEAP_TYPE_DSV : D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
  204. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
  205. };
  206. device->lpVtbl->CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, &render_target->impl.rtv_descriptor_heap);
  207. if (framebuffer_index >= 0) {
  208. window_swapchain->lpVtbl->GetBuffer(window_swapchain, framebuffer_index, &IID_ID3D12Resource, &render_target->impl.image);
  209. }
  210. else {
  211. device->lpVtbl->CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
  212. &clear_value, &IID_ID3D12Resource, &render_target->impl.image);
  213. }
  214. D3D12_RENDER_TARGET_VIEW_DESC view_desc = {
  215. .Format = dxgi_format,
  216. .ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D,
  217. .Texture2D.MipSlice = 0,
  218. .Texture2D.PlaneSlice = 0,
  219. };
  220. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  221. render_target->impl.rtv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(render_target->impl.rtv_descriptor_heap, &handle);
  222. if (format == GPU_TEXTURE_FORMAT_D32) {
  223. device->lpVtbl->CreateDepthStencilView(device, render_target->impl.image, NULL, handle);
  224. }
  225. else {
  226. device->lpVtbl->CreateRenderTargetView(device, render_target->impl.image, &view_desc, handle);
  227. }
  228. D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = {
  229. .NumDescriptors = 1,
  230. .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
  231. .NodeMask = 0,
  232. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
  233. };
  234. device->lpVtbl->CreateDescriptorHeap(device, &descriptor_heap_desc, &IID_ID3D12DescriptorHeap, &render_target->impl.srv_descriptor_heap);
  235. D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {
  236. .ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
  237. .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
  238. .Format = format == GPU_TEXTURE_FORMAT_D32 ? DXGI_FORMAT_R32_FLOAT : dxgi_format,
  239. .Texture2D.MipLevels = 1,
  240. .Texture2D.MostDetailedMip = 0,
  241. .Texture2D.ResourceMinLODClamp = 0.0f,
  242. };
  243. render_target->impl.srv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(render_target->impl.srv_descriptor_heap, &handle);
  244. device->lpVtbl->CreateShaderResourceView(device, render_target->impl.image, &srv_desc, handle);
  245. }
  246. void create_root_signature(bool linear_sampling) {
  247. ID3DBlob *root_blob;
  248. ID3DBlob *error_blob;
  249. D3D12_ROOT_PARAMETER parameters[3] = {0};
  250. D3D12_DESCRIPTOR_RANGE range = {
  251. .RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
  252. .NumDescriptors = (UINT)GPU_MAX_TEXTURES,
  253. .BaseShaderRegister = 0,
  254. .RegisterSpace = 0,
  255. .OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
  256. };
  257. parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
  258. parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  259. parameters[0].DescriptorTable.NumDescriptorRanges = 1;
  260. parameters[0].DescriptorTable.pDescriptorRanges = &range;
  261. parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
  262. parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  263. parameters[1].Descriptor.ShaderRegister = 0;
  264. parameters[1].Descriptor.RegisterSpace = 0;
  265. D3D12_DESCRIPTOR_RANGE sampler_range = {
  266. .RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
  267. .NumDescriptors = 1,
  268. .BaseShaderRegister = 0,
  269. .RegisterSpace = 0,
  270. .OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
  271. };
  272. parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
  273. parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
  274. parameters[2].DescriptorTable.NumDescriptorRanges = 1;
  275. parameters[2].DescriptorTable.pDescriptorRanges = &sampler_range;
  276. D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {
  277. .NumParameters = 3,
  278. .pParameters = parameters,
  279. .Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT,
  280. };
  281. D3D12SerializeRootSignature(&root_signature_desc, D3D_ROOT_SIGNATURE_VERSION_1, &root_blob, &error_blob);
  282. device->lpVtbl->CreateRootSignature(device, 0, root_blob->lpVtbl->GetBufferPointer(root_blob), root_blob->lpVtbl->GetBufferSize(root_blob), &IID_ID3D12RootSignature, &root_signature);
  283. }
  284. void gpu_init_internal(int depth_buffer_bits, bool vsync) {
  285. window_vsync = vsync;
  286. #ifdef _DEBUG
  287. ID3D12Debug *debug_controller = NULL;
  288. if (D3D12GetDebugInterface(&IID_ID3D12Debug, &debug_controller) == S_OK) {
  289. debug_controller->lpVtbl->EnableDebugLayer(debug_controller);
  290. }
  291. #endif
  292. D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, &device);
  293. create_root_signature(true);
  294. D3D12_COMMAND_QUEUE_DESC queue_desc = {
  295. .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
  296. .Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
  297. };
  298. device->lpVtbl->CreateCommandQueue(device, &queue_desc, &IID_ID3D12CommandQueue, &queue);
  299. HWND hwnd = iron_windows_window_handle();
  300. DXGI_SWAP_CHAIN_DESC swapchain_desc = {
  301. .BufferCount = GPU_FRAMEBUFFER_COUNT,
  302. .BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
  303. .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
  304. .BufferDesc.Width = iron_window_width(),
  305. .BufferDesc.Height = iron_window_height(),
  306. .OutputWindow = hwnd,
  307. .SampleDesc.Count = 1,
  308. .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
  309. .Windowed = true,
  310. };
  311. IDXGIFactory4 *dxgi_factory = NULL;
  312. CreateDXGIFactory1(&IID_IDXGIFactory4, &dxgi_factory);
  313. dxgi_factory->lpVtbl->CreateSwapChain(dxgi_factory, (IUnknown *)queue, &swapchain_desc, &window_swapchain);
  314. fence_value = 0;
  315. fence_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  316. device->lpVtbl->CreateFence(device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, &fence);
  317. gpu_create_framebuffers(depth_buffer_bits);
  318. D3D12_DESCRIPTOR_HEAP_DESC heap_desc = {
  319. .NumDescriptors = GPU_CONSTANT_BUFFER_MULTIPLE,
  320. .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
  321. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
  322. };
  323. device->lpVtbl->CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, &srv_heap);
  324. D3D12_DESCRIPTOR_HEAP_DESC sampler_heap_desc = {
  325. .NumDescriptors = 1,
  326. .Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
  327. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
  328. };
  329. device->lpVtbl->CreateDescriptorHeap(device, &sampler_heap_desc, &IID_ID3D12DescriptorHeap, &sampler_heap);
  330. gpu_use_linear_sampling(true);
  331. device->lpVtbl->CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, &command_allocator);
  332. device->lpVtbl->CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, command_allocator, NULL, &IID_ID3D12CommandList, &command_list);
  333. }
  334. void gpu_begin_internal(unsigned flags, unsigned color, float depth) {
  335. for (int i = 0; i < current_render_targets_count; ++i) {
  336. current_render_targets[i]->impl.rtv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(current_render_targets[i]->impl.rtv_descriptor_heap, &target_descriptors[i]);
  337. }
  338. if (current_depth_buffer != NULL) {
  339. current_depth_buffer->impl.rtv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(current_depth_buffer->impl.rtv_descriptor_heap, &depth_handle);
  340. current_depth_handle = &depth_handle;
  341. }
  342. else {
  343. current_depth_handle = NULL;
  344. }
  345. command_list->lpVtbl->OMSetRenderTargets(command_list, current_render_targets_count, &target_descriptors[0], false, current_depth_handle);
  346. gpu_texture_t *target = current_render_targets[0];
  347. gpu_viewport(0, 0, target->width, target->height);
  348. gpu_scissor(0, 0, target->width, target->height);
  349. if (flags & GPU_CLEAR_COLOR) {
  350. float clear_color[] = {((color & 0x00ff0000) >> 16) / 255.0f,
  351. ((color & 0x0000ff00) >> 8) / 255.0f,
  352. (color & 0x000000ff) / 255.0f,
  353. ((color & 0xff000000) >> 24) / 255.0f};
  354. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  355. target->impl.rtv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(target->impl.rtv_descriptor_heap, &handle);
  356. command_list->lpVtbl->ClearRenderTargetView(command_list, handle, clear_color, 0, NULL);
  357. }
  358. if (flags & GPU_CLEAR_DEPTH && current_depth_buffer != NULL) {
  359. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  360. current_depth_buffer->impl.rtv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(current_depth_buffer->impl.rtv_descriptor_heap, &handle);
  361. command_list->lpVtbl->ClearDepthStencilView(command_list, handle, D3D12_CLEAR_FLAG_DEPTH, depth, 0, 0, NULL);
  362. }
  363. }
  364. void gpu_end_internal() {
  365. for (int i = 0; i < current_render_targets_count; ++i) {
  366. gpu_barrier(current_render_targets[i],
  367. current_render_targets[i] == &framebuffers[framebuffer_index] ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE);
  368. }
  369. current_render_targets_count = 0;
  370. }
  371. void gpu_execute_and_wait() {
  372. command_list->lpVtbl->Close(command_list);
  373. ID3D12CommandList *command_lists[] = {(ID3D12CommandList *)command_list};
  374. queue->lpVtbl->ExecuteCommandLists(queue, 1, command_lists);
  375. queue->lpVtbl->Signal(queue, fence, ++fence_value);
  376. wait_for_fence(fence, fence_value, fence_event);
  377. command_allocator->lpVtbl->Reset(command_allocator);
  378. command_list->lpVtbl->Reset(command_list, command_allocator, NULL);
  379. if (gpu_in_use) {
  380. command_list->lpVtbl->OMSetRenderTargets(command_list, current_render_targets_count, &target_descriptors[0], false, current_depth_handle);
  381. command_list->lpVtbl->SetPipelineState(command_list, current_pipeline->impl.pso);
  382. command_list->lpVtbl->SetGraphicsRootSignature(command_list, root_signature);
  383. command_list->lpVtbl->IASetVertexBuffers(command_list, 0, 1, (D3D12_VERTEX_BUFFER_VIEW *)&current_vb->impl.vertex_buffer_view);
  384. command_list->lpVtbl->IASetIndexBuffer(command_list, (D3D12_INDEX_BUFFER_VIEW *)&current_ib->impl.index_buffer_view);
  385. command_list->lpVtbl->RSSetViewports(command_list, 1, &current_viewport);
  386. command_list->lpVtbl->RSSetScissorRects(command_list, 1, &current_scissor);
  387. }
  388. }
  389. void gpu_present_internal() {
  390. gpu_execute_and_wait();
  391. window_swapchain->lpVtbl->Present(window_swapchain, window_vsync, 0);
  392. queue->lpVtbl->Signal(queue, fence, ++fence_value);
  393. frame_fence_values[framebuffer_index] = fence_value;
  394. framebuffer_index = (framebuffer_index + 1) % GPU_FRAMEBUFFER_COUNT;
  395. wait_for_fence(fence, frame_fence_values[framebuffer_index], fence_event);
  396. if (resized) {
  397. framebuffer_index = 0;
  398. for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) {
  399. gpu_texture_destroy_internal(&framebuffers[i]);
  400. }
  401. if (framebuffer_depth.width > 0) {
  402. gpu_texture_destroy_internal(&framebuffer_depth);
  403. }
  404. window_swapchain->lpVtbl->ResizeBuffers(window_swapchain, GPU_FRAMEBUFFER_COUNT, iron_window_width(), iron_window_height(), DXGI_FORMAT_R8G8B8A8_UNORM, 0);
  405. for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) {
  406. gpu_render_target_init2(&framebuffers[i], iron_window_width(), iron_window_height(), GPU_TEXTURE_FORMAT_RGBA32, i);
  407. }
  408. if (framebuffer_depth.width > 0) {
  409. gpu_render_target_init2(&framebuffer_depth, iron_window_width(), iron_window_height(), GPU_TEXTURE_FORMAT_D32, -1);
  410. }
  411. resized = false;
  412. }
  413. while (resources_to_destroy_count > 0) {
  414. resources_to_destroy_count--;
  415. ID3D12Resource *r = resources_to_destroy[resources_to_destroy_count];
  416. r->lpVtbl->Release(r);
  417. }
  418. }
  419. void gpu_resize_internal(int width, int height) {
  420. if (fence_value == 0) {
  421. return;
  422. }
  423. resized = true;
  424. }
  425. bool gpu_raytrace_supported() {
  426. D3D12_FEATURE_DATA_D3D12_OPTIONS5 options;
  427. if (device->lpVtbl->CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS5, &options, sizeof(options)) == S_OK) {
  428. return options.RaytracingTier >= D3D12_RAYTRACING_TIER_1_0;
  429. }
  430. return false;
  431. }
  432. void gpu_set_constant_buffer(gpu_buffer_t *buffer, int offset, size_t size) {
  433. command_list->lpVtbl->SetGraphicsRootConstantBufferView(command_list, 1, buffer->impl.buffer->lpVtbl->GetGPUVirtualAddress(buffer->impl.buffer) + offset);
  434. }
  435. void gpu_internal_set_textures() {
  436. UINT srv_step = device->lpVtbl->GetDescriptorHandleIncrementSize(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  437. if (srv_heap_index + GPU_MAX_TEXTURES > GPU_CONSTANT_BUFFER_MULTIPLE) {
  438. srv_heap_index = 0;
  439. }
  440. D3D12_CPU_DESCRIPTOR_HANDLE cpu_base;
  441. D3D12_GPU_DESCRIPTOR_HANDLE gpu_base;
  442. srv_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(srv_heap, &cpu_base);
  443. srv_heap->lpVtbl->GetGPUDescriptorHandleForHeapStart(srv_heap, &gpu_base);
  444. cpu_base.ptr += srv_heap_index * srv_step;
  445. gpu_base.ptr += srv_heap_index * srv_step;
  446. for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
  447. if (current_textures[i] != NULL) {
  448. D3D12_CPU_DESCRIPTOR_HANDLE source_cpu;
  449. ID3D12DescriptorHeap *source_heap = current_textures[i]->impl.srv_descriptor_heap;
  450. source_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(source_heap, &source_cpu);
  451. device->lpVtbl->CopyDescriptorsSimple(device, 1, cpu_base, source_cpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  452. cpu_base.ptr += srv_step;
  453. srv_heap_index++;
  454. }
  455. }
  456. ID3D12DescriptorHeap *heaps[] = {srv_heap, sampler_heap};
  457. command_list->lpVtbl->SetDescriptorHeaps(command_list, 2, heaps);
  458. command_list->lpVtbl->SetGraphicsRootDescriptorTable(command_list, 0, gpu_base);
  459. D3D12_GPU_DESCRIPTOR_HANDLE sampler_gpu_base;
  460. sampler_heap->lpVtbl->GetGPUDescriptorHandleForHeapStart(sampler_heap, &sampler_gpu_base);
  461. command_list->lpVtbl->SetGraphicsRootDescriptorTable(command_list, 2, sampler_gpu_base);
  462. }
  463. void gpu_draw_internal() {
  464. gpu_internal_set_textures();
  465. command_list->lpVtbl->IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  466. command_list->lpVtbl->DrawIndexedInstanced(command_list, current_ib->count, 1, 0, 0, 0);
  467. }
  468. void gpu_viewport(int x, int y, int width, int height) {
  469. current_viewport = (D3D12_VIEWPORT){
  470. .TopLeftX = (float)x,
  471. .TopLeftY = (float)y,
  472. .Width = (float)width,
  473. .Height = (float)height,
  474. .MinDepth = 0.0f,
  475. .MaxDepth = 1.0f,
  476. };
  477. command_list->lpVtbl->RSSetViewports(command_list, 1, &current_viewport);
  478. }
  479. void gpu_scissor(int x, int y, int width, int height) {
  480. current_scissor = (D3D12_RECT){
  481. .left = x,
  482. .top = y,
  483. .right = x + width,
  484. .bottom = y + height,
  485. };
  486. command_list->lpVtbl->RSSetScissorRects(command_list, 1, &current_scissor);
  487. }
  488. void gpu_disable_scissor() {
  489. current_scissor = (D3D12_RECT){
  490. .left = 0,
  491. .top = 0,
  492. .right = current_render_targets[0]->width,
  493. .bottom = current_render_targets[0]->height,
  494. };
  495. command_list->lpVtbl->RSSetScissorRects(command_list, 1, &current_scissor);
  496. }
  497. void gpu_set_pipeline(gpu_pipeline_t *pipeline) {
  498. current_pipeline = pipeline;
  499. command_list->lpVtbl->SetPipelineState(command_list, pipeline->impl.pso);
  500. command_list->lpVtbl->SetGraphicsRootSignature(command_list, root_signature);
  501. for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
  502. current_textures[i] = NULL;
  503. }
  504. }
  505. void gpu_set_vertex_buffer(gpu_buffer_t *buffer) {
  506. current_vb = buffer;
  507. command_list->lpVtbl->IASetVertexBuffers(command_list, 0, 1, (D3D12_VERTEX_BUFFER_VIEW *)&buffer->impl.vertex_buffer_view);
  508. }
  509. void gpu_set_index_buffer(gpu_buffer_t *buffer) {
  510. current_ib = buffer;
  511. command_list->lpVtbl->IASetIndexBuffer(command_list, (D3D12_INDEX_BUFFER_VIEW *)&buffer->impl.index_buffer_view);
  512. }
  513. void gpu_get_render_target_pixels(gpu_texture_t *render_target, uint8_t *data) {
  514. D3D12_RESOURCE_DESC desc;
  515. render_target->impl.image->lpVtbl->GetDesc(render_target->impl.image, &desc);
  516. DXGI_FORMAT dxgi_format = desc.Format;
  517. int format_size = gpu_texture_format_size(render_target->format);
  518. int packed_row_size = render_target->width * format_size;
  519. int row_pitch = packed_row_size;
  520. int align = row_pitch % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
  521. if (align != 0) {
  522. row_pitch = row_pitch + (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - align);
  523. }
  524. int new_readback_buffer_size = row_pitch * render_target->height;
  525. if (new_readback_buffer_size < (2048 * 2048 * 4)) {
  526. new_readback_buffer_size = (2048 * 2048 * 4);
  527. }
  528. if (readback_buffer_size < new_readback_buffer_size) {
  529. readback_buffer_size = new_readback_buffer_size;
  530. if (readback_buffer != NULL) {
  531. readback_buffer->lpVtbl->Release(readback_buffer);
  532. }
  533. D3D12_HEAP_PROPERTIES heap_properties = {
  534. .Type = D3D12_HEAP_TYPE_READBACK,
  535. .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
  536. .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN,
  537. .CreationNodeMask = 1,
  538. .VisibleNodeMask = 1,
  539. };
  540. D3D12_RESOURCE_DESC resource_desc = {
  541. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  542. .Alignment = 0,
  543. .Width = readback_buffer_size,
  544. .Height = 1,
  545. .DepthOrArraySize = 1,
  546. .MipLevels = 1,
  547. .Format = DXGI_FORMAT_UNKNOWN,
  548. .SampleDesc.Count = 1,
  549. .SampleDesc.Quality = 0,
  550. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  551. .Flags = D3D12_RESOURCE_FLAG_NONE,
  552. };
  553. device->lpVtbl->CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_COMMON, NULL,
  554. &IID_ID3D12Resource, &readback_buffer);
  555. }
  556. // Copy render target to readback buffer
  557. D3D12_RESOURCE_BARRIER barrier = {
  558. .Transition.pResource = render_target->impl.image,
  559. .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
  560. .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
  561. .Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
  562. .Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE,
  563. .Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
  564. };
  565. command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier);
  566. D3D12_TEXTURE_COPY_LOCATION source = {
  567. .pResource = render_target->impl.image,
  568. .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
  569. .SubresourceIndex = 0,
  570. };
  571. D3D12_TEXTURE_COPY_LOCATION dest = {
  572. .pResource = readback_buffer,
  573. .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
  574. .PlacedFootprint.Offset = 0,
  575. .PlacedFootprint.Footprint.Format = dxgi_format,
  576. .PlacedFootprint.Footprint.Width = render_target->width,
  577. .PlacedFootprint.Footprint.Height = render_target->height,
  578. .PlacedFootprint.Footprint.Depth = 1,
  579. .PlacedFootprint.Footprint.RowPitch = row_pitch,
  580. };
  581. command_list->lpVtbl->CopyTextureRegion(command_list , &dest, 0, 0, 0, &source, NULL);
  582. barrier = (D3D12_RESOURCE_BARRIER){
  583. .Transition.pResource = render_target->impl.image,
  584. .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
  585. .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
  586. .Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE,
  587. .Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
  588. .Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
  589. };
  590. command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier);
  591. gpu_execute_and_wait();
  592. void *p;
  593. readback_buffer->lpVtbl->Map(readback_buffer, 0, NULL, &p);
  594. if (packed_row_size == row_pitch) {
  595. memcpy(data, p, render_target->width * render_target->height * format_size);
  596. }
  597. else {
  598. uint8_t *src = (uint8_t *)p;
  599. uint8_t *dst = data;
  600. for (int y = 0; y < render_target->height; y++) {
  601. memcpy(dst, src, packed_row_size);
  602. src += row_pitch;
  603. dst += packed_row_size;
  604. }
  605. }
  606. readback_buffer->lpVtbl->Unmap(readback_buffer, 0, NULL);
  607. }
  608. void gpu_set_texture(int unit, gpu_texture_t *texture) {
  609. current_textures[unit] = texture;
  610. }
  611. void gpu_use_linear_sampling(bool b) {
  612. D3D12_SAMPLER_DESC sampler_desc = {
  613. .Filter = b ? D3D12_FILTER_MIN_MAG_MIP_LINEAR : D3D12_FILTER_MIN_MAG_MIP_POINT,
  614. .AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
  615. .AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
  616. .AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
  617. .MipLODBias = 0,
  618. .MaxAnisotropy = 16,
  619. .ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER,
  620. .BorderColor = {0.0f, 0.0f, 0.0f, 0.0f},
  621. .MinLOD = 0.0f,
  622. .MaxLOD = D3D12_FLOAT32_MAX,
  623. };
  624. D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle;
  625. sampler_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(sampler_heap, &sampler_handle);
  626. device->lpVtbl->CreateSampler(device, &sampler_desc, sampler_handle);
  627. }
  628. void gpu_pipeline_destroy_internal(gpu_pipeline_t *pipe) {
  629. if (pipe->impl.pso != NULL) {
  630. pipe->impl.pso->lpVtbl->Release(pipe->impl.pso);
  631. pipe->impl.pso = NULL;
  632. }
  633. }
  634. void gpu_pipeline_compile(gpu_pipeline_t *pipe) {
  635. int vertex_attribute_count = pipe->input_layout->size;
  636. D3D12_INPUT_ELEMENT_DESC *vertex_desc = (D3D12_INPUT_ELEMENT_DESC *)alloca(sizeof(D3D12_INPUT_ELEMENT_DESC) * vertex_attribute_count);
  637. ZeroMemory(vertex_desc, sizeof(D3D12_INPUT_ELEMENT_DESC) * vertex_attribute_count);
  638. for (int i = 0; i < pipe->input_layout->size; ++i) {
  639. vertex_desc[i].SemanticName = "TEXCOORD";
  640. vertex_desc[i].SemanticIndex = i;
  641. vertex_desc[i].InputSlot = 0;
  642. vertex_desc[i].AlignedByteOffset = (i == 0) ? 0 : D3D12_APPEND_ALIGNED_ELEMENT;
  643. vertex_desc[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
  644. vertex_desc[i].InstanceDataStepRate = 0;
  645. switch (pipe->input_layout->elements[i].data) {
  646. case GPU_VERTEX_DATA_F32_1X:
  647. vertex_desc[i].Format = DXGI_FORMAT_R32_FLOAT;
  648. break;
  649. case GPU_VERTEX_DATA_F32_2X:
  650. vertex_desc[i].Format = DXGI_FORMAT_R32G32_FLOAT;
  651. break;
  652. case GPU_VERTEX_DATA_F32_3X:
  653. vertex_desc[i].Format = DXGI_FORMAT_R32G32B32_FLOAT;
  654. break;
  655. case GPU_VERTEX_DATA_F32_4X:
  656. vertex_desc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
  657. break;
  658. case GPU_VERTEX_DATA_I16_2X_NORM:
  659. vertex_desc[i].Format = DXGI_FORMAT_R16G16_SNORM;
  660. break;
  661. case GPU_VERTEX_DATA_I16_4X_NORM:
  662. vertex_desc[i].Format = DXGI_FORMAT_R16G16B16A16_SNORM;
  663. break;
  664. default:
  665. break;
  666. }
  667. }
  668. const D3D12_DEPTH_STENCILOP_DESC default_stencil_op = {
  669. D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_NEVER
  670. };
  671. D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {
  672. .VS.BytecodeLength = pipe->vertex_shader->impl.length,
  673. .VS.pShaderBytecode = pipe->vertex_shader->impl.data,
  674. .PS.BytecodeLength = pipe->fragment_shader->impl.length,
  675. .PS.pShaderBytecode = pipe->fragment_shader->impl.data,
  676. .pRootSignature = root_signature,
  677. .NumRenderTargets = pipe->color_attachment_count,
  678. .DSVFormat = DXGI_FORMAT_UNKNOWN,
  679. .InputLayout.NumElements = vertex_attribute_count,
  680. .InputLayout.pInputElementDescs = vertex_desc,
  681. .RasterizerState.FillMode = D3D12_FILL_MODE_SOLID,
  682. .RasterizerState.CullMode = convert_cull_mode(pipe->cull_mode),
  683. .RasterizerState.FrontCounterClockwise = FALSE,
  684. .RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS,
  685. .RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
  686. .RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
  687. .RasterizerState.DepthClipEnable = TRUE,
  688. .RasterizerState.MultisampleEnable = FALSE,
  689. .RasterizerState.AntialiasedLineEnable = FALSE,
  690. .RasterizerState.ForcedSampleCount = 0,
  691. .RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
  692. .BlendState.AlphaToCoverageEnable = FALSE,
  693. .BlendState.IndependentBlendEnable = FALSE,
  694. .DepthStencilState.DepthEnable = TRUE,
  695. .DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL,
  696. .DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS,
  697. .DepthStencilState.StencilEnable = FALSE,
  698. .DepthStencilState.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK,
  699. .DepthStencilState.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK,
  700. .DepthStencilState.DepthEnable = pipe->depth_mode != GPU_COMPARE_MODE_ALWAYS,
  701. .DepthStencilState.DepthWriteMask = pipe->depth_write ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO,
  702. .DepthStencilState.DepthFunc = convert_compare_mode(pipe->depth_mode),
  703. .DepthStencilState.StencilEnable = false,
  704. .DSVFormat = DXGI_FORMAT_D32_FLOAT,
  705. .SampleDesc.Count = 1,
  706. .SampleMask = 0xFFFFFFFF,
  707. .PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
  708. .DepthStencilState.FrontFace = default_stencil_op,
  709. .DepthStencilState.BackFace = default_stencil_op,
  710. };
  711. for (int i = 0; i < pipe->color_attachment_count; ++i) {
  712. psoDesc.RTVFormats[i] = convert_format(pipe->color_attachment[i]);
  713. }
  714. psoDesc.BlendState.IndependentBlendEnable = true;
  715. for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
  716. psoDesc.BlendState.RenderTarget[i].BlendEnable = pipe->blend_source != GPU_BLEND_ONE || pipe->blend_destination != GPU_BLEND_ZERO ||
  717. pipe->alpha_blend_source != GPU_BLEND_ONE || pipe->alpha_blend_destination != GPU_BLEND_ZERO;
  718. psoDesc.BlendState.RenderTarget[i].SrcBlend = convert_blend_factor(pipe->blend_source);
  719. psoDesc.BlendState.RenderTarget[i].DestBlend = convert_blend_factor(pipe->blend_destination);
  720. psoDesc.BlendState.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD;
  721. psoDesc.BlendState.RenderTarget[i].SrcBlendAlpha = convert_blend_factor(pipe->alpha_blend_source);
  722. psoDesc.BlendState.RenderTarget[i].DestBlendAlpha = convert_blend_factor(pipe->alpha_blend_destination);
  723. psoDesc.BlendState.RenderTarget[i].BlendOpAlpha = D3D12_BLEND_OP_ADD;
  724. psoDesc.BlendState.RenderTarget[i].RenderTargetWriteMask =
  725. (((pipe->color_write_mask_red[i] ? D3D12_COLOR_WRITE_ENABLE_RED : 0) |
  726. (pipe->color_write_mask_green[i] ? D3D12_COLOR_WRITE_ENABLE_GREEN : 0)) |
  727. (pipe->color_write_mask_blue[i] ? D3D12_COLOR_WRITE_ENABLE_BLUE : 0)) |
  728. (pipe->color_write_mask_alpha[i] ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0);
  729. }
  730. device->lpVtbl->CreateGraphicsPipelineState(device, &psoDesc, &IID_ID3D12PipelineState, &pipe->impl.pso);
  731. }
  732. void gpu_shader_init(gpu_shader_t *shader, const void *_data, size_t length, gpu_shader_type_t type) {
  733. uint8_t *data = (uint8_t *)_data;
  734. shader->impl.length = (int)length;
  735. shader->impl.data = (uint8_t *)malloc(shader->impl.length);
  736. memcpy(shader->impl.data, data, shader->impl.length);
  737. }
  738. void gpu_shader_destroy(gpu_shader_t *shader) {
  739. free(shader->impl.data);
  740. }
  741. void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) {
  742. texture->width = width;
  743. texture->height = height;
  744. texture->format = format;
  745. texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE;
  746. texture->buffer = NULL;
  747. texture->impl.rtv_descriptor_heap = NULL;
  748. DXGI_FORMAT dxgi_format = convert_format(format);
  749. int format_size = gpu_texture_format_size(format);
  750. D3D12_HEAP_PROPERTIES heap_properties = {
  751. .Type = D3D12_HEAP_TYPE_DEFAULT,
  752. .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
  753. .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN,
  754. .CreationNodeMask = 1,
  755. .VisibleNodeMask = 1,
  756. };
  757. D3D12_RESOURCE_DESC resource_desc = {
  758. .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
  759. .Alignment = 0,
  760. .Width = texture->width,
  761. .Height = texture->height,
  762. .DepthOrArraySize = 1,
  763. .MipLevels = 1,
  764. .Format = dxgi_format,
  765. .SampleDesc.Count = 1,
  766. .SampleDesc.Quality = 0,
  767. .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
  768. .Flags = D3D12_RESOURCE_FLAG_NONE,
  769. };
  770. device->lpVtbl->CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc,
  771. D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, NULL, &IID_ID3D12Resource, &texture->impl.image);
  772. D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
  773. UINT64 upload_size;
  774. device->lpVtbl->GetCopyableFootprints(device, &resource_desc, 0, 1, 0, &footprint, NULL, NULL, &upload_size);
  775. int new_upload_buffer_size = upload_size;
  776. if (new_upload_buffer_size < (1024 * 1024 * 4)) {
  777. new_upload_buffer_size = (1024 * 1024 * 4);
  778. }
  779. if (upload_buffer_size < new_upload_buffer_size) {
  780. upload_buffer_size = new_upload_buffer_size;
  781. if (upload_buffer != NULL) {
  782. upload_buffer->lpVtbl->Release(upload_buffer);
  783. }
  784. D3D12_HEAP_PROPERTIES heap_properties_upload = {
  785. .Type = D3D12_HEAP_TYPE_UPLOAD,
  786. .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
  787. .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN,
  788. .CreationNodeMask = 1,
  789. .VisibleNodeMask = 1,
  790. };
  791. D3D12_RESOURCE_DESC resource_desc_upload = {
  792. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  793. .Alignment = 0,
  794. .Width = upload_buffer_size,
  795. .Height = 1,
  796. .DepthOrArraySize = 1,
  797. .MipLevels = 1,
  798. .Format = DXGI_FORMAT_UNKNOWN,
  799. .SampleDesc.Count = 1,
  800. .SampleDesc.Quality = 0,
  801. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  802. .Flags = D3D12_RESOURCE_FLAG_NONE,
  803. };
  804. device->lpVtbl->CreateCommittedResource(device, &heap_properties_upload, D3D12_HEAP_FLAG_NONE, &resource_desc_upload,
  805. D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &IID_ID3D12Resource, &upload_buffer);
  806. }
  807. BYTE *pixel;
  808. upload_buffer->lpVtbl->Map(upload_buffer, 0, NULL, (void **)&pixel);
  809. UINT row_pitch = footprint.Footprint.RowPitch;
  810. for (int y = 0; y < texture->height; ++y) {
  811. memcpy(pixel + y * row_pitch, ((uint8_t *)data) + y * width * format_size, width * format_size);
  812. }
  813. upload_buffer->lpVtbl->Unmap(upload_buffer, 0, NULL);
  814. D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = {
  815. .NumDescriptors = 1,
  816. .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
  817. .NodeMask = 0,
  818. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
  819. };
  820. device->lpVtbl->CreateDescriptorHeap(device, &descriptor_heap_desc, &IID_ID3D12DescriptorHeap, &texture->impl.srv_descriptor_heap);
  821. D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {
  822. .ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
  823. .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
  824. .Format = dxgi_format,
  825. .Texture2D.MipLevels = 1,
  826. .Texture2D.MostDetailedMip = 0,
  827. .Texture2D.ResourceMinLODClamp = 0.0f,
  828. };
  829. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  830. texture->impl.srv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(texture->impl.srv_descriptor_heap, &handle);
  831. device->lpVtbl->CreateShaderResourceView(device, texture->impl.image, &srv_desc, handle);
  832. D3D12_RESOURCE_BARRIER barrier = {
  833. .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
  834. .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
  835. .Transition.pResource = texture->impl.image,
  836. .Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
  837. .Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST,
  838. .Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
  839. };
  840. command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier);
  841. D3D12_TEXTURE_COPY_LOCATION source = {
  842. .pResource = upload_buffer,
  843. .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
  844. .PlacedFootprint = footprint,
  845. };
  846. D3D12_TEXTURE_COPY_LOCATION destination = {
  847. .pResource = texture->impl.image,
  848. .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
  849. .SubresourceIndex = 0,
  850. };
  851. command_list->lpVtbl->CopyTextureRegion(command_list, &destination, 0, 0, 0, &source, NULL);
  852. barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST,
  853. barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
  854. command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier);
  855. gpu_execute_and_wait(); ////
  856. }
  857. void gpu_texture_destroy_internal(gpu_texture_t *render_target) {
  858. if (render_target->impl.image != NULL) {
  859. render_target->impl.image->lpVtbl->Release(render_target->impl.image);
  860. }
  861. if (render_target->impl.rtv_descriptor_heap != NULL) {
  862. render_target->impl.rtv_descriptor_heap->lpVtbl->Release(render_target->impl.rtv_descriptor_heap);
  863. }
  864. if (render_target->impl.srv_descriptor_heap != NULL) {
  865. render_target->impl.srv_descriptor_heap->lpVtbl->Release(render_target->impl.srv_descriptor_heap);
  866. }
  867. }
  868. void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format) {
  869. gpu_render_target_init2(target, width, height, format, -1);
  870. }
  871. void _gpu_buffer_init(ID3D12Resource **buffer, int size, D3D12_HEAP_TYPE heap_type) {
  872. if (*buffer != NULL) {
  873. assert(resources_to_destroy_count < 256);
  874. resources_to_destroy[resources_to_destroy_count] = *buffer;
  875. resources_to_destroy_count++;
  876. }
  877. D3D12_HEAP_PROPERTIES heap_properties = {
  878. .Type = heap_type,
  879. .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
  880. .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN,
  881. .CreationNodeMask = 1,
  882. .VisibleNodeMask = 1,
  883. };
  884. D3D12_RESOURCE_DESC resource_desc = {
  885. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  886. .Alignment = 0,
  887. .Width = size,
  888. .Height = 1,
  889. .DepthOrArraySize = 1,
  890. .MipLevels = 1,
  891. .Format = DXGI_FORMAT_UNKNOWN,
  892. .SampleDesc.Count = 1,
  893. .SampleDesc.Quality = 0,
  894. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  895. .Flags = D3D12_RESOURCE_FLAG_NONE,
  896. };
  897. device->lpVtbl->CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc,
  898. heap_type == D3D12_HEAP_TYPE_UPLOAD ? D3D12_RESOURCE_STATE_GENERIC_READ : D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, buffer);
  899. }
  900. void gpu_vertex_buffer_init(gpu_buffer_t *buffer, int count, gpu_vertex_structure_t *structure) {
  901. buffer->count = count;
  902. buffer->stride = 0;
  903. for (int i = 0; i < structure->size; ++i) {
  904. buffer->stride += gpu_vertex_data_size(structure->elements[i].data);
  905. }
  906. buffer->impl.vertex_buffer_view.SizeInBytes = buffer->stride * buffer->count;
  907. buffer->impl.vertex_buffer_view.StrideInBytes = buffer->stride;
  908. buffer->impl.buffer = NULL;
  909. }
  910. void *gpu_vertex_buffer_lock(gpu_buffer_t *buffer) {
  911. _gpu_buffer_init(&buffer->impl.buffer, buffer->stride * buffer->count, D3D12_HEAP_TYPE_UPLOAD);
  912. D3D12_RANGE range = {
  913. .Begin = 0,
  914. .End = buffer->count * buffer->stride,
  915. };
  916. void *p;
  917. buffer->impl.buffer->lpVtbl->Map(buffer->impl.buffer, 0, &range, &p);
  918. return p;
  919. }
  920. void gpu_vertex_buffer_unlock(gpu_buffer_t *buffer) {
  921. D3D12_RANGE range = {
  922. .Begin = 0,
  923. .End = buffer->count * buffer->stride,
  924. };
  925. buffer->impl.buffer->lpVtbl->Unmap(buffer->impl.buffer, 0, &range);
  926. ID3D12Resource *upload_buffer = buffer->impl.buffer;
  927. _gpu_buffer_init(&buffer->impl.buffer, buffer->stride * buffer->count, D3D12_HEAP_TYPE_DEFAULT);
  928. _gpu_barrier(buffer->impl.buffer, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST);
  929. command_list->lpVtbl->CopyBufferRegion(command_list, buffer->impl.buffer, 0, upload_buffer, 0, buffer->stride * buffer->count);
  930. _gpu_barrier(buffer->impl.buffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
  931. buffer->impl.vertex_buffer_view.BufferLocation = buffer->impl.buffer->lpVtbl->GetGPUVirtualAddress(buffer->impl.buffer);
  932. }
  933. void gpu_index_buffer_init(gpu_buffer_t *buffer, int count) {
  934. buffer->count = count;
  935. buffer->impl.index_buffer_view.SizeInBytes = count * 4;
  936. buffer->impl.index_buffer_view.Format = DXGI_FORMAT_R32_UINT;
  937. buffer->impl.buffer = NULL;
  938. }
  939. void *gpu_index_buffer_lock(gpu_buffer_t *buffer) {
  940. _gpu_buffer_init(&buffer->impl.buffer, buffer->count * 4, D3D12_HEAP_TYPE_UPLOAD);
  941. D3D12_RANGE range = {
  942. .Begin = 0,
  943. .End = buffer->count * 4,
  944. };
  945. void *p;
  946. buffer->impl.buffer->lpVtbl->Map(buffer->impl.buffer, 0, &range, &p);
  947. return p;
  948. }
  949. void gpu_index_buffer_unlock(gpu_buffer_t *buffer) {
  950. D3D12_RANGE range = {
  951. .Begin = 0,
  952. .End = buffer->count * 4,
  953. };
  954. buffer->impl.buffer->lpVtbl->Unmap(buffer->impl.buffer, 0, &range);
  955. ID3D12Resource *upload_buffer = buffer->impl.buffer;
  956. _gpu_buffer_init(&buffer->impl.buffer, buffer->count * 4, D3D12_HEAP_TYPE_DEFAULT);
  957. _gpu_barrier(buffer->impl.buffer, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST);
  958. command_list->lpVtbl->CopyBufferRegion(command_list, buffer->impl.buffer, 0, upload_buffer, 0, buffer->count * 4);
  959. _gpu_barrier(buffer->impl.buffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER);
  960. buffer->impl.index_buffer_view.BufferLocation = buffer->impl.buffer->lpVtbl->GetGPUVirtualAddress(buffer->impl.buffer);
  961. }
  962. void gpu_constant_buffer_init(gpu_buffer_t *buffer, int size) {
  963. buffer->count = size;
  964. buffer->data = NULL;
  965. buffer->impl.buffer = NULL;
  966. _gpu_buffer_init(&buffer->impl.buffer, size, D3D12_HEAP_TYPE_UPLOAD);
  967. }
  968. void gpu_constant_buffer_lock(gpu_buffer_t *buffer, int start, int count) {
  969. buffer->impl.last_start = start;
  970. buffer->impl.last_count = count;
  971. D3D12_RANGE range = {
  972. .Begin = start,
  973. .End = start + count,
  974. };
  975. uint8_t *p;
  976. buffer->impl.buffer->lpVtbl->Map(buffer->impl.buffer, 0, &range, (void **)&p);
  977. buffer->data = &p[start];
  978. }
  979. void gpu_constant_buffer_unlock(gpu_buffer_t *buffer) {
  980. D3D12_RANGE range = {
  981. .Begin = buffer->impl.last_start,
  982. .End = buffer->impl.last_start + buffer->impl.last_count,
  983. };
  984. buffer->impl.buffer->lpVtbl->Unmap(buffer->impl.buffer, 0, &range);
  985. buffer->data = NULL;
  986. }
  987. void gpu_buffer_destroy_internal(gpu_buffer_t *buffer) {
  988. buffer->impl.buffer->lpVtbl->Release(buffer->impl.buffer);
  989. buffer->impl.buffer = NULL;
  990. }
  991. char *gpu_device_name() {
  992. IDXGIFactory *factory;
  993. CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory);
  994. IDXGIAdapter *adapter;
  995. factory->lpVtbl->EnumAdapters(factory, 0, &adapter);
  996. DXGI_ADAPTER_DESC desc;
  997. adapter->lpVtbl->GetDesc(adapter, &desc);
  998. WideCharToMultiByte(CP_UTF8, 0, desc.Description, -1, device_name, sizeof(device_name), NULL, NULL);
  999. adapter->lpVtbl->Release(adapter);
  1000. factory->lpVtbl->Release(factory);
  1001. return device_name;
  1002. }
  1003. typedef struct inst {
  1004. iron_matrix4x4_t m;
  1005. int i;
  1006. } inst_t;
  1007. static ID3D12Device5 *dxr_device = NULL;
  1008. static ID3D12GraphicsCommandList4 *dxr_command_list = NULL;
  1009. static ID3D12RootSignature *dxr_root_signature = NULL;
  1010. static ID3D12DescriptorHeap *dxr_descriptor_heap = NULL;
  1011. static gpu_raytrace_acceleration_structure_t *dxr_accel;
  1012. static gpu_raytrace_pipeline_t *dxr_pipeline;
  1013. static gpu_texture_t *dxr_output = NULL;
  1014. static D3D12_CPU_DESCRIPTOR_HANDLE dxr_output_cpu_descriptor;
  1015. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_output_descriptor_handle;
  1016. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_vbgpu_descriptor_handle;
  1017. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_ibgpu_descriptor_handle;
  1018. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_tex0gpu_descriptor_handle;
  1019. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_tex1gpu_descriptor_handle;
  1020. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_tex2gpu_descriptor_handle;
  1021. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_texenvgpu_descriptor_handle;
  1022. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_texsobolgpu_descriptor_handle;
  1023. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_texscramblegpu_descriptor_handle;
  1024. static D3D12_GPU_DESCRIPTOR_HANDLE dxr_texrankgpu_descriptor_handle;
  1025. static int dxr_descriptors_allocated = 0;
  1026. static UINT dxr_descriptor_size;
  1027. static gpu_buffer_t *dxr_vb[16];
  1028. static gpu_buffer_t *dxr_vb_last[16];
  1029. static gpu_buffer_t *dxr_ib[16];
  1030. static int dxr_vb_count = 0;
  1031. static int dxr_vb_count_last = 0;
  1032. static inst_t dxr_instances[1024];
  1033. static int dxr_instances_count = 0;
  1034. void gpu_raytrace_pipeline_init(gpu_raytrace_pipeline_t *pipeline, void *ray_shader, int ray_shader_size, gpu_buffer_t *constant_buffer) {
  1035. dxr_output = NULL;
  1036. dxr_descriptors_allocated = 0;
  1037. pipeline->constant_buffer = constant_buffer;
  1038. D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = {
  1039. .NumDescriptors = 12,
  1040. .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
  1041. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
  1042. .NodeMask = 0,
  1043. };
  1044. if (dxr_descriptor_heap != NULL) {
  1045. dxr_descriptor_heap->lpVtbl->Release(dxr_descriptor_heap);
  1046. }
  1047. device->lpVtbl->CreateDescriptorHeap(device, &descriptor_heap_desc, &IID_ID3D12DescriptorHeap, &dxr_descriptor_heap);
  1048. dxr_descriptor_size = device->lpVtbl->GetDescriptorHandleIncrementSize(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  1049. if (dxr_device != NULL) {
  1050. dxr_device->lpVtbl->Release(dxr_device);
  1051. }
  1052. if (dxr_command_list != NULL) {
  1053. dxr_command_list->lpVtbl->Release(dxr_command_list);
  1054. }
  1055. device->lpVtbl->QueryInterface(device, &IID_ID3D12Device5, &dxr_device);
  1056. command_list->lpVtbl->QueryInterface(command_list , &IID_ID3D12GraphicsCommandList4, &dxr_command_list);
  1057. // Root signatures
  1058. D3D12_DESCRIPTOR_RANGE ranges[] = {
  1059. {D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1060. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1061. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1062. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 3, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1063. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 4, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1064. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 5, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1065. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 6, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1066. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 7, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1067. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 8, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND},
  1068. {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 9, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND}
  1069. };
  1070. D3D12_ROOT_PARAMETER root_parameters[12] = {
  1071. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[0]}, D3D12_SHADER_VISIBILITY_ALL},
  1072. {D3D12_ROOT_PARAMETER_TYPE_SRV, {0}, D3D12_SHADER_VISIBILITY_ALL},
  1073. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[1]}, D3D12_SHADER_VISIBILITY_ALL},
  1074. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[2]}, D3D12_SHADER_VISIBILITY_ALL},
  1075. {D3D12_ROOT_PARAMETER_TYPE_CBV, {0}, D3D12_SHADER_VISIBILITY_ALL},
  1076. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[3]}, D3D12_SHADER_VISIBILITY_ALL},
  1077. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[4]}, D3D12_SHADER_VISIBILITY_ALL},
  1078. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[5]}, D3D12_SHADER_VISIBILITY_ALL},
  1079. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[6]}, D3D12_SHADER_VISIBILITY_ALL},
  1080. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[7]}, D3D12_SHADER_VISIBILITY_ALL},
  1081. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[8]}, D3D12_SHADER_VISIBILITY_ALL},
  1082. {D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1, &ranges[9]}, D3D12_SHADER_VISIBILITY_ALL}
  1083. };
  1084. D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {
  1085. .NumParameters = ARRAYSIZE(root_parameters),
  1086. .pParameters = root_parameters,
  1087. };
  1088. ID3DBlob *blob = NULL;
  1089. ID3DBlob *error = NULL;
  1090. D3D12SerializeRootSignature(&root_signature_desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, &error);
  1091. if (dxr_root_signature != NULL) {
  1092. dxr_root_signature->lpVtbl->Release(dxr_root_signature);
  1093. }
  1094. device->lpVtbl->CreateRootSignature(device, 1, blob->lpVtbl->GetBufferPointer(blob), blob->lpVtbl->GetBufferSize(blob), &IID_ID3D12RootSignature, &dxr_root_signature);
  1095. // Pipeline
  1096. D3D12_STATE_OBJECT_DESC raytracingPipeline = {
  1097. .Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE,
  1098. };
  1099. D3D12_SHADER_BYTECODE shaderBytecode = {
  1100. .pShaderBytecode = ray_shader,
  1101. .BytecodeLength = ray_shader_size,
  1102. };
  1103. D3D12_DXIL_LIBRARY_DESC dxilLibrary = {
  1104. .DXILLibrary = shaderBytecode,
  1105. };
  1106. D3D12_EXPORT_DESC exports[3] = {0};
  1107. exports[0].Name = L"raygeneration";
  1108. exports[1].Name = L"closesthit";
  1109. exports[2].Name = L"miss";
  1110. dxilLibrary.pExports = exports;
  1111. dxilLibrary.NumExports = 3;
  1112. D3D12_HIT_GROUP_DESC hitGroup = {
  1113. .ClosestHitShaderImport = L"closesthit",
  1114. .HitGroupExport = L"hitgroup",
  1115. .Type = D3D12_HIT_GROUP_TYPE_TRIANGLES,
  1116. };
  1117. D3D12_RAYTRACING_SHADER_CONFIG shaderConfig = {
  1118. .MaxPayloadSizeInBytes = 10 * sizeof(float), // float4 color, float3 ray_origin, float3 ray_dir
  1119. .MaxAttributeSizeInBytes = 2 * sizeof(float), // float2 barycentrics
  1120. };
  1121. D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = {
  1122. .MaxTraceRecursionDepth = 1, // ~ primary rays only
  1123. };
  1124. D3D12_STATE_SUBOBJECT subobjects[5] = {
  1125. { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &dxilLibrary },
  1126. { D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &hitGroup },
  1127. { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &shaderConfig },
  1128. { D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &dxr_root_signature },
  1129. { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &pipelineConfig }
  1130. };
  1131. raytracingPipeline.NumSubobjects = 5;
  1132. raytracingPipeline.pSubobjects = subobjects;
  1133. dxr_device->lpVtbl->CreateStateObject(dxr_device, &raytracingPipeline, &IID_ID3D12StateObject, &pipeline->impl.state);
  1134. // Shader tables
  1135. ID3D12StateObjectProperties *stateObjectProps = NULL;
  1136. pipeline->impl.state->lpVtbl->QueryInterface(pipeline->impl.state , &IID_ID3D12StateObjectProperties, &stateObjectProps);
  1137. const void *rayGenShaderId = stateObjectProps->lpVtbl->GetShaderIdentifier(stateObjectProps, L"raygeneration");
  1138. const void *missShaderId = stateObjectProps->lpVtbl->GetShaderIdentifier(stateObjectProps, L"miss");
  1139. const void *hitGroupShaderId = stateObjectProps->lpVtbl->GetShaderIdentifier(stateObjectProps, L"hitgroup");
  1140. UINT shaderIdSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
  1141. int align = D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT;
  1142. // Ray gen shader table
  1143. {
  1144. UINT size = shaderIdSize + constant_buffer->count;
  1145. UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
  1146. D3D12_RESOURCE_DESC bufferDesc = {
  1147. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  1148. .Width = shaderRecordSize,
  1149. .Height = 1,
  1150. .DepthOrArraySize = 1,
  1151. .MipLevels = 1,
  1152. .Format = DXGI_FORMAT_UNKNOWN,
  1153. .SampleDesc.Count = 1,
  1154. .SampleDesc.Quality = 0,
  1155. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  1156. };
  1157. D3D12_HEAP_PROPERTIES uploadHeapProperties = {
  1158. .Type = D3D12_HEAP_TYPE_UPLOAD,
  1159. .CreationNodeMask = 1,
  1160. .VisibleNodeMask = 1,
  1161. };
  1162. device->lpVtbl->CreateCommittedResource(device, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
  1163. &IID_ID3D12Resource, &pipeline->impl.raygen_shader_table);
  1164. D3D12_RANGE rstRange = {
  1165. .Begin = 0,
  1166. .End = 0,
  1167. };
  1168. uint8_t *byteDest;
  1169. pipeline->impl.raygen_shader_table->lpVtbl->Map(pipeline->impl.raygen_shader_table, 0, &rstRange, (void **)(&byteDest));
  1170. D3D12_RANGE cbRange = {
  1171. .Begin = 0,
  1172. .End = constant_buffer->count,
  1173. };
  1174. void *constantBufferData;
  1175. constant_buffer->impl.buffer->lpVtbl->Map(constant_buffer->impl.buffer, 0, &cbRange, (void **)&constantBufferData);
  1176. memcpy(byteDest, rayGenShaderId, size);
  1177. memcpy(byteDest + size, constantBufferData, constant_buffer->count);
  1178. pipeline->impl.raygen_shader_table->lpVtbl->Unmap(pipeline->impl.raygen_shader_table, 0, NULL);
  1179. }
  1180. // Miss shader table
  1181. {
  1182. UINT size = shaderIdSize;
  1183. UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
  1184. D3D12_RESOURCE_DESC bufferDesc = {
  1185. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  1186. .Width = shaderRecordSize,
  1187. .Height = 1,
  1188. .DepthOrArraySize = 1,
  1189. .MipLevels = 1,
  1190. .Format = DXGI_FORMAT_UNKNOWN,
  1191. .SampleDesc.Count = 1,
  1192. .SampleDesc.Quality = 0,
  1193. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  1194. };
  1195. D3D12_HEAP_PROPERTIES uploadHeapProperties = {
  1196. .Type = D3D12_HEAP_TYPE_UPLOAD,
  1197. .CreationNodeMask = 1,
  1198. .VisibleNodeMask = 1,
  1199. };
  1200. device->lpVtbl->CreateCommittedResource(device, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
  1201. &IID_ID3D12Resource, &pipeline->impl.miss_shader_table);
  1202. D3D12_RANGE mstRange = {
  1203. .Begin = 0,
  1204. .End = 0,
  1205. };
  1206. uint8_t *byteDest;
  1207. pipeline->impl.miss_shader_table->lpVtbl->Map(pipeline->impl.miss_shader_table, 0, &mstRange, (void **)(&byteDest));
  1208. memcpy(byteDest, missShaderId, size);
  1209. pipeline->impl.miss_shader_table->lpVtbl->Unmap(pipeline->impl.miss_shader_table, 0, NULL);
  1210. }
  1211. // Hit group shader table
  1212. {
  1213. UINT size = shaderIdSize;
  1214. UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
  1215. D3D12_RESOURCE_DESC bufferDesc = {
  1216. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  1217. .Width = shaderRecordSize,
  1218. .Height = 1,
  1219. .DepthOrArraySize = 1,
  1220. .MipLevels = 1,
  1221. .Format = DXGI_FORMAT_UNKNOWN,
  1222. .SampleDesc.Count = 1,
  1223. .SampleDesc.Quality = 0,
  1224. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  1225. };
  1226. D3D12_HEAP_PROPERTIES uploadHeapProperties = {
  1227. .Type = D3D12_HEAP_TYPE_UPLOAD,
  1228. .CreationNodeMask = 1,
  1229. .VisibleNodeMask = 1,
  1230. };
  1231. device->lpVtbl->CreateCommittedResource(device, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
  1232. &IID_ID3D12Resource, &pipeline->impl.hitgroup_shader_table);
  1233. D3D12_RANGE hstRange = {
  1234. .Begin = 0,
  1235. .End = 0,
  1236. };
  1237. uint8_t *byteDest;
  1238. pipeline->impl.hitgroup_shader_table->lpVtbl->Map(pipeline->impl.hitgroup_shader_table, 0, &hstRange, (void **)(&byteDest));
  1239. memcpy(byteDest, hitGroupShaderId, size);
  1240. pipeline->impl.hitgroup_shader_table->lpVtbl->Unmap(pipeline->impl.hitgroup_shader_table, 0, NULL);
  1241. }
  1242. // Output descriptor
  1243. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  1244. dxr_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &handle);
  1245. dxr_output_cpu_descriptor.ptr = handle.ptr + (INT64)(dxr_descriptors_allocated) * (UINT64)(dxr_descriptor_size);
  1246. dxr_descriptor_heap->lpVtbl->GetGPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &handle);
  1247. int descriptorHeapIndex = dxr_descriptors_allocated++;
  1248. dxr_output_descriptor_handle.ptr = handle.ptr + (INT64)(descriptorHeapIndex) * (UINT64)(dxr_descriptor_size);
  1249. }
  1250. void gpu_raytrace_pipeline_destroy(gpu_raytrace_pipeline_t *pipeline) {
  1251. pipeline->impl.state->lpVtbl->Release(pipeline->impl.state);
  1252. pipeline->impl.raygen_shader_table->lpVtbl->Release(pipeline->impl.raygen_shader_table);
  1253. pipeline->impl.miss_shader_table->lpVtbl->Release(pipeline->impl.miss_shader_table);
  1254. pipeline->impl.hitgroup_shader_table->lpVtbl->Release(pipeline->impl.hitgroup_shader_table);
  1255. }
  1256. UINT create_srv_vb(gpu_buffer_t *vb, UINT numElements, UINT elementSize) {
  1257. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {
  1258. .ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
  1259. .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
  1260. .Buffer.NumElements = numElements,
  1261. };
  1262. if (elementSize == 0) {
  1263. srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
  1264. srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
  1265. srvDesc.Buffer.StructureByteStride = 0;
  1266. }
  1267. else {
  1268. srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  1269. srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
  1270. srvDesc.Buffer.StructureByteStride = elementSize;
  1271. }
  1272. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  1273. dxr_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &handle);
  1274. D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptor = {
  1275. .ptr = handle.ptr + (INT64)(dxr_descriptors_allocated) * (UINT64)(dxr_descriptor_size),
  1276. };
  1277. UINT descriptorIndex = dxr_descriptors_allocated++;
  1278. device->lpVtbl->CreateShaderResourceView(device, vb->impl.buffer, &srvDesc, cpuDescriptor);
  1279. dxr_descriptor_heap->lpVtbl->GetGPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &handle);
  1280. dxr_vbgpu_descriptor_handle.ptr = handle.ptr + (INT64)(descriptorIndex) * (UINT64)(dxr_descriptor_size);
  1281. return descriptorIndex;
  1282. }
  1283. UINT create_srv_ib(gpu_buffer_t *ib, UINT numElements, UINT elementSize) {
  1284. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {
  1285. .ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
  1286. .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
  1287. .Buffer.NumElements = numElements,
  1288. };
  1289. if (elementSize == 0) {
  1290. srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
  1291. srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
  1292. srvDesc.Buffer.StructureByteStride = 0;
  1293. }
  1294. else {
  1295. srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  1296. srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
  1297. srvDesc.Buffer.StructureByteStride = elementSize;
  1298. }
  1299. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  1300. dxr_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &handle);
  1301. D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptor = {
  1302. .ptr = handle.ptr + (INT64)(dxr_descriptors_allocated) * (UINT64)(dxr_descriptor_size),
  1303. };
  1304. UINT descriptorIndex = dxr_descriptors_allocated++;
  1305. dxr_descriptor_heap->lpVtbl->GetGPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &handle);
  1306. device->lpVtbl->CreateShaderResourceView(device, ib->impl.buffer, &srvDesc, cpuDescriptor);
  1307. dxr_ibgpu_descriptor_handle.ptr = handle.ptr + (INT64)(descriptorIndex) * (UINT64)(dxr_descriptor_size);
  1308. return descriptorIndex;
  1309. }
  1310. void gpu_raytrace_acceleration_structure_init(gpu_raytrace_acceleration_structure_t *accel) {
  1311. dxr_vb_count = 0;
  1312. dxr_instances_count = 0;
  1313. }
  1314. void gpu_raytrace_acceleration_structure_add(gpu_raytrace_acceleration_structure_t *accel, gpu_buffer_t *vb, gpu_buffer_t *ib, iron_matrix4x4_t transform) {
  1315. int vb_i = -1;
  1316. for (int i = 0; i < dxr_vb_count; ++i) {
  1317. if (vb == dxr_vb[i]) {
  1318. vb_i = i;
  1319. break;
  1320. }
  1321. }
  1322. if (vb_i == -1) {
  1323. vb_i = dxr_vb_count;
  1324. dxr_vb[dxr_vb_count] = vb;
  1325. dxr_ib[dxr_vb_count] = ib;
  1326. dxr_vb_count++;
  1327. }
  1328. inst_t inst = { .i = vb_i, .m = transform };
  1329. dxr_instances[dxr_instances_count] = inst;
  1330. dxr_instances_count++;
  1331. }
  1332. void _gpu_raytrace_acceleration_structure_destroy_bottom(gpu_raytrace_acceleration_structure_t *accel) {
  1333. for (int i = 0; i < dxr_vb_count_last; ++i) {
  1334. accel->impl.bottom_level_accel[i]->lpVtbl->Release(accel->impl.bottom_level_accel[i]);
  1335. }
  1336. }
  1337. void _gpu_raytrace_acceleration_structure_destroy_top(gpu_raytrace_acceleration_structure_t *accel) {
  1338. accel->impl.top_level_accel->lpVtbl->Release(accel->impl.top_level_accel);
  1339. }
  1340. void gpu_raytrace_acceleration_structure_build(gpu_raytrace_acceleration_structure_t *accel, gpu_buffer_t *vb_full, gpu_buffer_t *ib_full) {
  1341. bool build_bottom = false;
  1342. for (int i = 0; i < 16; ++i) {
  1343. if (dxr_vb_last[i] != dxr_vb[i]) {
  1344. build_bottom = true;
  1345. }
  1346. dxr_vb_last[i] = dxr_vb[i];
  1347. }
  1348. if (dxr_vb_count_last > 0) {
  1349. if (build_bottom) {
  1350. _gpu_raytrace_acceleration_structure_destroy_bottom(accel);
  1351. }
  1352. _gpu_raytrace_acceleration_structure_destroy_top(accel);
  1353. }
  1354. dxr_vb_count_last = dxr_vb_count;
  1355. if (dxr_vb_count == 0) {
  1356. return;
  1357. }
  1358. dxr_descriptors_allocated = 1; // 1 descriptor already allocated in gpu_raytrace_pipeline_init
  1359. #ifdef is_forge
  1360. create_srv_ib(ib_full, ib_full->count, 0);
  1361. create_srv_vb(vb_full, vb_full->count, dxr_vb[0]->stride);
  1362. #else
  1363. create_srv_ib(dxr_ib[0], dxr_ib[0]->count, 0);
  1364. create_srv_vb(dxr_vb[0], dxr_vb[0]->count, dxr_vb[0]->stride);
  1365. #endif
  1366. command_list->lpVtbl->Reset(command_list, command_allocator, NULL);
  1367. D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS topLevelInputs = {
  1368. .DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY,
  1369. .Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE,
  1370. .NumDescs = 1,
  1371. .Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL,
  1372. };
  1373. D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO topLevelPrebuildInfo = {0};
  1374. dxr_device->lpVtbl->GetRaytracingAccelerationStructurePrebuildInfo(dxr_device, &topLevelInputs, &topLevelPrebuildInfo);
  1375. UINT64 scratch_size = topLevelPrebuildInfo.ScratchDataSizeInBytes;
  1376. // Bottom AS
  1377. D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS bottomLevelInputs[16];
  1378. D3D12_RAYTRACING_GEOMETRY_DESC geometryDescs[16];
  1379. if (build_bottom) {
  1380. for (int i = 0; i < dxr_vb_count; ++i) {
  1381. D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc = {
  1382. .Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES,
  1383. .Triangles.IndexBuffer = dxr_ib[i]->impl.buffer->lpVtbl->GetGPUVirtualAddress(dxr_ib[i]->impl.buffer),
  1384. .Triangles.IndexCount = dxr_ib[i]->count,
  1385. .Triangles.IndexFormat = DXGI_FORMAT_R32_UINT,
  1386. .Triangles.Transform3x4 = 0,
  1387. .Triangles.VertexFormat = DXGI_FORMAT_R16G16B16A16_SNORM,
  1388. .Triangles.VertexCount = dxr_vb[i]->count,
  1389. };
  1390. D3D12_RESOURCE_DESC desc;
  1391. dxr_vb[i]->impl.buffer->lpVtbl->GetDesc(dxr_vb[i]->impl.buffer, &desc);
  1392. geometryDesc.Triangles.VertexBuffer.StartAddress = dxr_vb[i]->impl.buffer->lpVtbl->GetGPUVirtualAddress(dxr_vb[i]->impl.buffer);
  1393. geometryDesc.Triangles.VertexBuffer.StrideInBytes = desc.Width / dxr_vb[i]->count;
  1394. geometryDesc.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
  1395. geometryDescs[i] = geometryDesc;
  1396. D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO bottomLevelPrebuildInfo = {0};
  1397. D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS inputs = {
  1398. .DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY,
  1399. .NumDescs = 1,
  1400. .Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL,
  1401. .pGeometryDescs = &geometryDescs[i],
  1402. .Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE,
  1403. };
  1404. dxr_device->lpVtbl->GetRaytracingAccelerationStructurePrebuildInfo(dxr_device, &inputs, &bottomLevelPrebuildInfo);
  1405. bottomLevelInputs[i] = inputs;
  1406. UINT64 blSize = bottomLevelPrebuildInfo.ScratchDataSizeInBytes;
  1407. if (scratch_size < blSize) {
  1408. scratch_size = blSize;
  1409. }
  1410. {
  1411. D3D12_RESOURCE_DESC bufferDesc = {
  1412. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  1413. .Width = bottomLevelPrebuildInfo.ResultDataMaxSizeInBytes,
  1414. .Height = 1,
  1415. .DepthOrArraySize = 1,
  1416. .MipLevels = 1,
  1417. .Format = DXGI_FORMAT_UNKNOWN,
  1418. .SampleDesc.Count = 1,
  1419. .SampleDesc.Quality = 0,
  1420. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  1421. .Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
  1422. };
  1423. D3D12_HEAP_PROPERTIES uploadHeapProperties = {
  1424. .Type = D3D12_HEAP_TYPE_DEFAULT,
  1425. .CreationNodeMask = 1,
  1426. .VisibleNodeMask = 1,
  1427. };
  1428. device->lpVtbl->CreateCommittedResource(dxr_device, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, NULL,
  1429. &IID_ID3D12Resource, &accel->impl.bottom_level_accel[i]);
  1430. }
  1431. }
  1432. }
  1433. // Create scratch memory
  1434. ID3D12Resource *scratchResource;
  1435. {
  1436. D3D12_RESOURCE_DESC bufferDesc = {
  1437. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  1438. .Width = scratch_size,
  1439. .Height = 1,
  1440. .DepthOrArraySize = 1,
  1441. .MipLevels = 1,
  1442. .Format = DXGI_FORMAT_UNKNOWN,
  1443. .SampleDesc.Count = 1,
  1444. .SampleDesc.Quality = 0,
  1445. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  1446. .Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
  1447. };
  1448. D3D12_HEAP_PROPERTIES uploadHeapProperties = {
  1449. .Type = D3D12_HEAP_TYPE_DEFAULT,
  1450. .CreationNodeMask = 1,
  1451. .VisibleNodeMask = 1,
  1452. };
  1453. device->lpVtbl->CreateCommittedResource(dxr_device, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, NULL,
  1454. &IID_ID3D12Resource, &scratchResource);
  1455. }
  1456. // Bottom AS
  1457. if (build_bottom) {
  1458. for (int i = 0; i < dxr_vb_count; ++i) {
  1459. D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC bottomLevelBuildDesc = {
  1460. .Inputs = bottomLevelInputs[i],
  1461. .ScratchAccelerationStructureData = scratchResource->lpVtbl->GetGPUVirtualAddress(scratchResource),
  1462. .DestAccelerationStructureData = accel->impl.bottom_level_accel[i]->lpVtbl->GetGPUVirtualAddress(accel->impl.bottom_level_accel[i]),
  1463. };
  1464. dxr_command_list->lpVtbl->BuildRaytracingAccelerationStructure(dxr_command_list, &bottomLevelBuildDesc, 0, NULL);
  1465. }
  1466. }
  1467. // Top AS
  1468. {
  1469. D3D12_RESOURCE_DESC bufferDesc = {
  1470. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  1471. .Width = topLevelPrebuildInfo.ResultDataMaxSizeInBytes,
  1472. .Height = 1,
  1473. .DepthOrArraySize = 1,
  1474. .MipLevels = 1,
  1475. .Format = DXGI_FORMAT_UNKNOWN,
  1476. .SampleDesc.Count = 1,
  1477. .SampleDesc.Quality = 0,
  1478. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  1479. .Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
  1480. };
  1481. D3D12_HEAP_PROPERTIES uploadHeapProperties = {
  1482. .Type = D3D12_HEAP_TYPE_DEFAULT,
  1483. .CreationNodeMask = 1,
  1484. .VisibleNodeMask = 1,
  1485. };
  1486. device->lpVtbl->CreateCommittedResource(device, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, NULL,
  1487. &IID_ID3D12Resource, &accel->impl.top_level_accel);
  1488. }
  1489. D3D12_RESOURCE_DESC bufferDesc = {
  1490. .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
  1491. .Width = sizeof(D3D12_RAYTRACING_INSTANCE_DESC) * dxr_instances_count,
  1492. .Height = 1,
  1493. .DepthOrArraySize = 1,
  1494. .MipLevels = 1,
  1495. .Format = DXGI_FORMAT_UNKNOWN,
  1496. .SampleDesc.Count = 1,
  1497. .SampleDesc.Quality = 0,
  1498. .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
  1499. };
  1500. D3D12_HEAP_PROPERTIES uploadHeapProperties = {
  1501. .Type = D3D12_HEAP_TYPE_UPLOAD,
  1502. .CreationNodeMask = 1,
  1503. .VisibleNodeMask = 1,
  1504. };
  1505. ID3D12Resource *instanceDescs;
  1506. device->lpVtbl->CreateCommittedResource(device, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
  1507. &IID_ID3D12Resource, &instanceDescs);
  1508. void *mappedData;
  1509. instanceDescs->lpVtbl->Map(instanceDescs, 0, NULL, &mappedData);
  1510. for (int i = 0; i < dxr_instances_count; ++i) {
  1511. D3D12_RAYTRACING_INSTANCE_DESC instanceDesc = {0};
  1512. instanceDesc.Transform[0][0] = dxr_instances[i].m.m[0];
  1513. instanceDesc.Transform[0][1] = dxr_instances[i].m.m[1];
  1514. instanceDesc.Transform[0][2] = dxr_instances[i].m.m[2];
  1515. instanceDesc.Transform[0][3] = dxr_instances[i].m.m[3];
  1516. instanceDesc.Transform[1][0] = dxr_instances[i].m.m[4];
  1517. instanceDesc.Transform[1][1] = dxr_instances[i].m.m[5];
  1518. instanceDesc.Transform[1][2] = dxr_instances[i].m.m[6];
  1519. instanceDesc.Transform[1][3] = dxr_instances[i].m.m[7];
  1520. instanceDesc.Transform[2][0] = dxr_instances[i].m.m[8];
  1521. instanceDesc.Transform[2][1] = dxr_instances[i].m.m[9];
  1522. instanceDesc.Transform[2][2] = dxr_instances[i].m.m[10];
  1523. instanceDesc.Transform[2][3] = dxr_instances[i].m.m[11];
  1524. int ib_off = 0;
  1525. for (int j = 0; j < dxr_instances[i].i; ++j) {
  1526. ib_off += dxr_ib[j]->count * 4;
  1527. }
  1528. instanceDesc.InstanceID = ib_off;
  1529. instanceDesc.InstanceMask = 1;
  1530. instanceDesc.AccelerationStructure = accel->impl.bottom_level_accel[dxr_instances[i].i]->lpVtbl->GetGPUVirtualAddress(accel->impl.bottom_level_accel[dxr_instances[i].i]);
  1531. memcpy((uint8_t *)mappedData + i * sizeof(D3D12_RAYTRACING_INSTANCE_DESC), &instanceDesc, sizeof(D3D12_RAYTRACING_INSTANCE_DESC));
  1532. }
  1533. instanceDescs->lpVtbl->Unmap(instanceDescs, 0, NULL);
  1534. D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC topLevelBuildDesc = {0};
  1535. topLevelInputs.InstanceDescs = instanceDescs->lpVtbl->GetGPUVirtualAddress(instanceDescs);
  1536. topLevelBuildDesc.Inputs = topLevelInputs;
  1537. topLevelBuildDesc.DestAccelerationStructureData = accel->impl.top_level_accel->lpVtbl->GetGPUVirtualAddress(accel->impl.top_level_accel);
  1538. topLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->lpVtbl->GetGPUVirtualAddress(scratchResource);
  1539. D3D12_RESOURCE_BARRIER barrier = {
  1540. .Type = D3D12_RESOURCE_BARRIER_TYPE_UAV,
  1541. .UAV.pResource = accel->impl.bottom_level_accel[0],
  1542. };
  1543. command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier);
  1544. dxr_command_list->lpVtbl->BuildRaytracingAccelerationStructure(dxr_command_list, &topLevelBuildDesc, 0, NULL);
  1545. gpu_execute_and_wait();
  1546. scratchResource->lpVtbl->Release(scratchResource);
  1547. instanceDescs->lpVtbl->Release(instanceDescs);
  1548. }
  1549. void gpu_raytrace_acceleration_structure_destroy(gpu_raytrace_acceleration_structure_t *accel) {
  1550. // accel->impl.bottom_level_accel->Release();
  1551. // accel->impl.top_level_accel->Release();
  1552. }
  1553. void gpu_raytrace_set_textures(gpu_texture_t *texpaint0, gpu_texture_t *texpaint1, gpu_texture_t *texpaint2, gpu_texture_t *texenv, gpu_texture_t *texsobol, gpu_texture_t *texscramble, gpu_texture_t *texrank) {
  1554. D3D12_CPU_DESCRIPTOR_HANDLE handle, cpuDescriptor, sourceCpu;
  1555. D3D12_GPU_DESCRIPTOR_HANDLE ghandle;
  1556. gpu_texture_t *textures[] = {texpaint0, texpaint1, texpaint2, texenv, texsobol, texscramble, texrank};
  1557. D3D12_GPU_DESCRIPTOR_HANDLE *gpu_handles[] = {&dxr_tex0gpu_descriptor_handle, &dxr_tex1gpu_descriptor_handle, &dxr_tex2gpu_descriptor_handle, &dxr_texenvgpu_descriptor_handle, &dxr_texsobolgpu_descriptor_handle, &dxr_texscramblegpu_descriptor_handle, &dxr_texrankgpu_descriptor_handle};
  1558. dxr_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &handle);
  1559. for (int i = 0; i < 7; i++) {
  1560. cpuDescriptor.ptr = handle.ptr + (5 + i) * (UINT64)dxr_descriptor_size;
  1561. textures[i]->impl.srv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(textures[i]->impl.srv_descriptor_heap, &sourceCpu);
  1562. device->lpVtbl->CopyDescriptorsSimple(device, 1, cpuDescriptor, sourceCpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  1563. dxr_descriptor_heap->lpVtbl->GetGPUDescriptorHandleForHeapStart(dxr_descriptor_heap, &ghandle);
  1564. gpu_handles[i]->ptr = ghandle.ptr + (5 + i) * (UINT64)dxr_descriptor_size;
  1565. }
  1566. }
  1567. void gpu_raytrace_set_acceleration_structure(gpu_raytrace_acceleration_structure_t *accel) {
  1568. dxr_accel = accel;
  1569. }
  1570. void gpu_raytrace_set_pipeline(gpu_raytrace_pipeline_t *pipeline) {
  1571. dxr_pipeline = pipeline;
  1572. }
  1573. void gpu_raytrace_set_target(gpu_texture_t *output) {
  1574. if (output != dxr_output) {
  1575. output->impl.image->lpVtbl->Release(output->impl.image);
  1576. output->impl.rtv_descriptor_heap->lpVtbl->Release(output->impl.rtv_descriptor_heap);
  1577. output->impl.srv_descriptor_heap->lpVtbl->Release(output->impl.srv_descriptor_heap);
  1578. D3D12_HEAP_PROPERTIES heap_properties = {
  1579. .Type = D3D12_HEAP_TYPE_DEFAULT,
  1580. .CreationNodeMask = 1,
  1581. .VisibleNodeMask = 1,
  1582. };
  1583. D3D12_RESOURCE_DESC desc = {
  1584. .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
  1585. .Width = output->width,
  1586. .Height = output->height,
  1587. .DepthOrArraySize = 1,
  1588. .MipLevels = 1,
  1589. .Format = DXGI_FORMAT_R16G16B16A16_FLOAT,
  1590. .SampleDesc.Count = 1,
  1591. .SampleDesc.Quality = 0,
  1592. .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
  1593. .Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
  1594. };
  1595. D3D12_CLEAR_VALUE clear_value;
  1596. clear_value.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
  1597. clear_value.Color[0] = 0.0f;
  1598. clear_value.Color[1] = 0.0f;
  1599. clear_value.Color[2] = 0.0f;
  1600. clear_value.Color[3] = 0.0f;
  1601. device->lpVtbl->CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &desc,
  1602. D3D12_RESOURCE_STATE_COMMON, &clear_value, &IID_ID3D12Resource, &output->impl.image);
  1603. D3D12_RENDER_TARGET_VIEW_DESC view = {
  1604. .Format = DXGI_FORMAT_R16G16B16A16_FLOAT,
  1605. .ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D,
  1606. .Texture2D.MipSlice = 0,
  1607. .Texture2D.PlaneSlice = 0,
  1608. };
  1609. D3D12_DESCRIPTOR_HEAP_DESC heap_desc = {
  1610. .NumDescriptors = 1,
  1611. .Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
  1612. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
  1613. };
  1614. device->lpVtbl->CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, &output->impl.rtv_descriptor_heap);
  1615. D3D12_CPU_DESCRIPTOR_HANDLE handle;
  1616. output->impl.rtv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(output->impl.rtv_descriptor_heap, &handle);
  1617. device->lpVtbl->CreateRenderTargetView(device, output->impl.image, &view, handle);
  1618. D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = {
  1619. .NumDescriptors = 1,
  1620. .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
  1621. .NodeMask = 0,
  1622. .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
  1623. };
  1624. device->lpVtbl->CreateDescriptorHeap(device, &descriptor_heap_desc, &IID_ID3D12DescriptorHeap, &output->impl.srv_descriptor_heap);
  1625. D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {
  1626. .ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
  1627. .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
  1628. .Format = DXGI_FORMAT_R16G16B16A16_FLOAT,
  1629. .Texture2D.MipLevels = 1,
  1630. .Texture2D.MostDetailedMip = 0,
  1631. .Texture2D.ResourceMinLODClamp = 0.0f,
  1632. };
  1633. output->impl.srv_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(output->impl.srv_descriptor_heap, &handle);
  1634. device->lpVtbl->CreateShaderResourceView(device, output->impl.image, &srv_desc,
  1635. handle);
  1636. D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {
  1637. .ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D,
  1638. };
  1639. device->lpVtbl->CreateUnorderedAccessView(device, output->impl.image, NULL, &UAVDesc, dxr_output_cpu_descriptor);
  1640. }
  1641. dxr_output = output;
  1642. }
  1643. void gpu_raytrace_dispatch_rays() {
  1644. command_list->lpVtbl->SetComputeRootSignature(command_list, dxr_root_signature);
  1645. command_list->lpVtbl->SetDescriptorHeaps(command_list, 1, &dxr_descriptor_heap);
  1646. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 0, dxr_output_descriptor_handle);
  1647. command_list->lpVtbl->SetComputeRootShaderResourceView(command_list, 1, dxr_accel->impl.top_level_accel->lpVtbl->GetGPUVirtualAddress(dxr_accel->impl.top_level_accel));
  1648. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 2, dxr_ibgpu_descriptor_handle);
  1649. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 3, dxr_vbgpu_descriptor_handle);
  1650. command_list->lpVtbl->SetComputeRootConstantBufferView(command_list, 4, dxr_pipeline->constant_buffer->impl.buffer->lpVtbl->GetGPUVirtualAddress(dxr_pipeline->constant_buffer->impl.buffer));
  1651. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 5, dxr_tex0gpu_descriptor_handle);
  1652. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 6, dxr_tex1gpu_descriptor_handle);
  1653. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 7, dxr_tex2gpu_descriptor_handle);
  1654. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 8, dxr_texenvgpu_descriptor_handle);
  1655. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 9, dxr_texsobolgpu_descriptor_handle);
  1656. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 10, dxr_texscramblegpu_descriptor_handle);
  1657. command_list->lpVtbl->SetComputeRootDescriptorTable(command_list, 11, dxr_texrankgpu_descriptor_handle);
  1658. D3D12_DISPATCH_RAYS_DESC dispatchDesc = {0};
  1659. D3D12_RESOURCE_DESC desc;
  1660. dxr_pipeline->impl.hitgroup_shader_table->lpVtbl->GetDesc(dxr_pipeline->impl.hitgroup_shader_table, &desc);
  1661. dispatchDesc.HitGroupTable.StartAddress = dxr_pipeline->impl.hitgroup_shader_table->lpVtbl->GetGPUVirtualAddress(dxr_pipeline->impl.hitgroup_shader_table);
  1662. dispatchDesc.HitGroupTable.SizeInBytes = desc.Width;
  1663. dispatchDesc.HitGroupTable.StrideInBytes = dispatchDesc.HitGroupTable.SizeInBytes;
  1664. dispatchDesc.MissShaderTable.StartAddress = dxr_pipeline->impl.miss_shader_table->lpVtbl->GetGPUVirtualAddress(dxr_pipeline->impl.miss_shader_table);
  1665. dxr_pipeline->impl.miss_shader_table->lpVtbl->GetDesc(dxr_pipeline->impl.miss_shader_table, &desc);
  1666. dispatchDesc.MissShaderTable.SizeInBytes = desc.Width;
  1667. dispatchDesc.MissShaderTable.StrideInBytes = dispatchDesc.MissShaderTable.SizeInBytes;
  1668. dispatchDesc.RayGenerationShaderRecord.StartAddress = dxr_pipeline->impl.raygen_shader_table->lpVtbl->GetGPUVirtualAddress(dxr_pipeline->impl.raygen_shader_table);
  1669. dxr_pipeline->impl.raygen_shader_table->lpVtbl->GetDesc(dxr_pipeline->impl.raygen_shader_table, &desc);
  1670. dispatchDesc.RayGenerationShaderRecord.SizeInBytes = desc.Width;
  1671. dispatchDesc.Width = dxr_output->width;
  1672. dispatchDesc.Height = dxr_output->height;
  1673. dispatchDesc.Depth = 1;
  1674. dxr_command_list->lpVtbl->SetPipelineState1(dxr_command_list, dxr_pipeline->impl.state);
  1675. dxr_command_list->lpVtbl->DispatchRays(dxr_command_list, &dispatchDesc);
  1676. }