From f1ac650471e8424c6301377c18f8b6031aace1e6 Mon Sep 17 00:00:00 2001 From: jacob Date: Fri, 6 Jun 2025 21:26:06 -0500 Subject: [PATCH] create separate dx12 direct & compute queues --- src/gpu_dx11.c | 4 +-- src/gpu_dx12.c | 69 +++++++++++++++++++++++++++++++++---------------- src/sys_win32.c | 4 +-- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/src/gpu_dx11.c b/src/gpu_dx11.c index 8fd0ff7a..9caccd3c 100644 --- a/src/gpu_dx11.c +++ b/src/gpu_dx11.c @@ -766,7 +766,7 @@ INTERNAL HRESULT dx11_include_open(ID3DInclude *d3d_handler, D3D_INCLUDE_TYPE in struct string name = string_from_cstr_no_limit((char *)name_cstr); if (handler->has_open_resource) { - sys_panic(LIT("D3d include handler somehow already has a resource open")); + sys_panic(LIT("Dx11 include handler somehow already has a resource open")); } struct resource res = resource_open(name); @@ -822,7 +822,7 @@ INTERNAL void dx11_include_handler_release(struct dx11_include_handler *handler) /* TODO: Multithread shader compilation */ -/* If shader compilation fails, then error string is returned allocated on `arena` */ +/* If shader compilation fails, then function returns error string allocated on `arena` */ INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *shader, struct dx11_shader_desc *shader_desc, struct resource *src_res) { __prof; diff --git a/src/gpu_dx12.c b/src/gpu_dx12.c index e9e04b67..2db9d481 100644 --- a/src/gpu_dx12.c +++ b/src/gpu_dx12.c @@ -75,9 +75,12 @@ GLOBAL struct { /* Desc sizes */ u32 desc_size_rtv; + /* Command queues */ + ID3D12CommandQueue *cq_direct; + ID3D12CommandQueue *cq_compute; + /* Swapchain */ u32 swapchain_frame_index; - ID3D12CommandQueue *swapchain_cq; ID3D12CommandAllocator *swapchain_ca; IDXGISwapChain3 *swapchain; ID3D12DescriptorHeap *swapchain_rtv_heap; @@ -91,6 +94,14 @@ GLOBAL struct { INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gpu_shutdown); +INTERNAL void dx12_init_error(struct string error) +{ + struct temp_arena scratch = scratch_begin_no_conflict(); + struct string msg = string_format(scratch.arena, LIT("Failed to initialize DirectX 12.\n\n%F"), FMT_STR(error)); + sys_panic(msg); + scratch_end(scratch); +} + INTERNAL void dx12_init(struct sys_window *window) { __prof; @@ -104,13 +115,13 @@ INTERNAL void dx12_init(struct sys_window *window) ID3D12Debug *debug_controller0 = NULL; hr = D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug_controller0); if (FAILED(hr)) { - sys_panic(LIT("Failed to create ID3D12Debug0")); + dx12_init_error(LIT("Failed to create ID3D12Debug0")); } ID3D12Debug1 *debug_controller1 = NULL; hr = ID3D12Debug_QueryInterface(debug_controller0, &IID_ID3D12Debug1, (void **)&debug_controller1); if (FAILED(hr)) { - sys_panic(LIT("Failed to create ID3D12Debug1")); + dx12_init_error(LIT("Failed to create ID3D12Debug1")); } ID3D12Debug_EnableDebugLayer(debug_controller0); @@ -128,7 +139,7 @@ INTERNAL void dx12_init(struct sys_window *window) IDXGIFactory6 *factory = NULL; hr = CreateDXGIFactory2(dxgi_factory_flags, &IID_IDXGIFactory6, (void **)&factory); if (FAILED(hr)) { - sys_panic(LIT("Failed to initialize DXGI factory")); + dx12_init_error(LIT("Failed to initialize DXGI factory")); } /* Create device */ @@ -163,12 +174,13 @@ INTERNAL void dx12_init(struct sys_window *window) break; } } + device = NULL; if (!device) { if (first_gpu_name.len > 0) { - struct string fmt = LIT("Could not initialize device '%F' with DirectX feature level 12_0. Ensure that the device is capable and drivers are up to date."); + struct string fmt = LIT("Could not initialize device '%F' with D3D_FEATURE_LEVEL_12_0. Ensure that the device is capable and drivers are up to date."); error = string_format(scratch.arena, fmt, FMT_STR(first_gpu_name)); } - sys_panic(error); + dx12_init_error(error); } } @@ -181,7 +193,7 @@ INTERNAL void dx12_init(struct sys_window *window) ID3D12InfoQueue *info = NULL; hr = ID3D12Device_QueryInterface(device, &IID_ID3D12InfoQueue, (void **)&info); if (FAILED(hr)) { - sys_panic(LIT("Failed to query ID3D12Device interface")); + dx12_init_error(LIT("Failed to query ID3D12Device interface")); } ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE); ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_ERROR, TRUE); @@ -193,7 +205,7 @@ INTERNAL void dx12_init(struct sys_window *window) IDXGIInfoQueue *dxgi_info = NULL; hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void **)&dxgi_info); if (FAILED(hr)) { - sys_panic(LIT("Failed to get DXGI debug interface")); + dx12_init_error(LIT("Failed to get DXGI debug interface")); } IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE); IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE); @@ -202,24 +214,37 @@ INTERNAL void dx12_init(struct sys_window *window) #endif /* Create direct command queue */ - ID3D12CommandQueue *swapchain_cq = NULL; + ID3D12CommandQueue *cq_direct = NULL; { D3D12_COMMAND_QUEUE_DESC desc = ZI; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&swapchain_cq); + hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_direct); if (FAILED(hr)) { - sys_panic(LIT("Failed to create swapchain command queue")); + dx12_init_error(LIT("Failed to create direct command queue")); } } - /* Create direct command allocator */ + /* Create compute command queue */ + ID3D12CommandQueue *cq_compute = NULL; + { + D3D12_COMMAND_QUEUE_DESC desc = ZI; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; + + hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_compute); + if (FAILED(hr)) { + dx12_init_error(LIT("Failed to create compute command queue")); + } + } + + /* Create swapchain command allocator */ ID3D12CommandAllocator *swapchain_ca = NULL; { hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, (void **)&swapchain_ca); if (FAILED(hr)) { - sys_panic(LIT("Failed to create swapchain command allocator")); + dx12_init_error(LIT("Failed to create swapchain command allocator")); } } @@ -241,15 +266,15 @@ INTERNAL void dx12_init(struct sys_window *window) /* Create swapchain1 */ IDXGISwapChain1 *swapchain1 = NULL; - hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)swapchain_cq, hwnd, &desc, NULL, NULL, &swapchain1); + hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)cq_direct, hwnd, &desc, NULL, NULL, &swapchain1); if (FAILED(hr)) { - sys_panic(LIT("Failed to create IDXGISwapChain1")); + dx12_init_error(LIT("Failed to create IDXGISwapChain1")); } /* Upgrade to swapchain3 */ hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain); if (FAILED(hr)) { - sys_panic(LIT("Failed to create IDXGISwapChain3")); + dx12_init_error(LIT("Failed to create IDXGISwapChain3")); } /* Disable Alt+Enter changing monitor resolution to match window size */ @@ -271,7 +296,7 @@ INTERNAL void dx12_init(struct sys_window *window) hr = ID3D12Device_CreateDescriptorHeap(device, &desc, &IID_ID3D12DescriptorHeap, (void **)&swapchain_rtv_heap); if (FAILED(hr)) { - sys_panic(LIT("Failed to create swapchain RTV heap")); + dx12_init_error(LIT("Failed to create swapchain RTV heap")); } } @@ -283,7 +308,7 @@ INTERNAL void dx12_init(struct sys_window *window) for (u32 i = 0; i < DX12_SWAPCHAIN_BUFFER_COUNT; ++i) { hr = IDXGISwapChain3_GetBuffer(swapchain, i, &IID_ID3D12Resource, (void **)&swapchain_rtvs[i]); if (FAILED(hr)) { - sys_panic(LIT("Failed to create swapchain RTV")); + dx12_init_error(LIT("Failed to create swapchain RTV")); } ID3D12Device_CreateRenderTargetView(device, swapchain_rtvs[i], NULL, rtv_handle); @@ -291,12 +316,11 @@ INTERNAL void dx12_init(struct sys_window *window) } } - /* Create command allocator */ - G.device = device; G.desc_size_rtv = desc_size_rtv; G.swapchain_frame_index = swapchain_frame_index; - G.swapchain_cq = swapchain_cq; + G.cq_direct = cq_direct; + G.cq_compute = cq_compute; G.swapchain_ca = swapchain_ca; G.swapchain = swapchain; G.swapchain_rtv_heap = swapchain_rtv_heap; @@ -331,7 +355,8 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gpu_shutdown) } ID3D12DescriptorHeap_Release(G.swapchain_rtv_heap); ID3D12CommandQueue_Release(G.swapchain_ca); - ID3D12CommandQueue_Release(G.swapchain_cq); + ID3D12CommandQueue_Release(G.cq_direct); + ID3D12CommandQueue_Release(G.cq_compute); IDXGISwapChain3_Release(G.swapchain); ID3D12Device_Release(G.device); #endif diff --git a/src/sys_win32.c b/src/sys_win32.c index b895a1ee..621d0909 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -2123,7 +2123,6 @@ void sys_panic(struct string msg) if (atomic_i32_eval_compare_exchange(&G.panicking, 0, 1) == 0) { log_panic(msg); - /* FIXME: Atomic panic str */ wchar_t *wstr = G.panic_wstr; u64 wstr_len = 0; @@ -2131,13 +2130,14 @@ void sys_panic(struct string msg) MEMCPY(wstr, prefix, min_u64(ARRAY_COUNT(G.panic_wstr), (ARRAY_COUNT(prefix) << 1))); wstr_len += ARRAY_COUNT(prefix) - 1; + /* Perform manual string encode to avoid any implicit memory + * allocation (in case allocation is unreliable) */ struct string str8 = msg; u64 pos8 = 0; while (pos8 < str8.len) { struct string str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 }; struct uni_decode_utf8_result decoded = uni_decode_utf8(str8_remaining); struct uni_encode_utf16_result encoded = uni_encode_utf16(decoded.codepoint); - u64 wstr_new_len = wstr_len + encoded.count16; if (wstr_new_len < (ARRAY_COUNT(G.panic_wstr) - 1)) { u16 *dest = wstr + wstr_len;