diff --git a/Juliet/render/d3d12/render_d3d12.c b/Juliet/render/d3d12/render_d3d12.c index 65bbf99..e37034a 100644 --- a/Juliet/render/d3d12/render_d3d12.c +++ b/Juliet/render/d3d12/render_d3d12.c @@ -26,11 +26,16 @@ internal R_Handle r_d3d12_handle_from_window(R_D3D12_Window* window) internal void r_d3d12_wait() { - r_d3d12_state->fence_value += 1; - ID3D12CommandQueue_Signal(r_d3d12_state->direct_command_queue, r_d3d12_state->fence, r_d3d12_state->fence_value); - if (ID3D12Fence_GetCompletedValue(r_d3d12_state->fence) < r_d3d12_state->fence_value) + r_d3d12_state->global_fence_value += 1; + ID3D12CommandQueue_Signal(r_d3d12_state->direct_command_queue, r_d3d12_state->fence, r_d3d12_state->global_fence_value); + r_d3d12_wait_for_fence_value(r_d3d12_state->global_fence_value); +} + +internal void r_d3d12_wait_for_fence_value(uint64 fence_value) +{ + if (ID3D12Fence_GetCompletedValue(r_d3d12_state->fence) < fence_value) { - ID3D12Fence_SetEventOnCompletion(r_d3d12_state->fence, r_d3d12_state->fence_value, r_d3d12_state->fence_event); + ID3D12Fence_SetEventOnCompletion(r_d3d12_state->fence, fence_value, r_d3d12_state->fence_event); WaitForSingleObject(r_d3d12_state->fence_event, INFINITE); } } @@ -292,12 +297,28 @@ void r_window_unequip(WM_Window handle, R_Handle handle_equip) void r_begin_frame() { - // No-op + MutexScopeW(r_d3d12_state->device_rw_mutex) + { + uint64 frame_slot = r_d3d12_state->frame_idx % 2; + r_d3d12_wait_for_fence_value(r_d3d12_state->frame_fence_value[frame_slot]); + ID3D12CommandAllocator_Reset(r_d3d12_state->command_allocators[frame_slot]); + r_d3d12_state->frame_has_presented = 0; + } } void r_end_frame() { - // pouet + MutexScopeW(r_d3d12_state->device_rw_mutex) + { + uint64 frame_slot = r_d3d12_state->frame_idx % 2; + + // Setup the frame fence + r_d3d12_state->global_fence_value += 1; + ID3D12CommandQueue_Signal(r_d3d12_state->direct_command_queue, r_d3d12_state->fence, r_d3d12_state->global_fence_value); + r_d3d12_state->frame_fence_value[frame_slot] = r_d3d12_state->global_fence_value; + + r_d3d12_state->frame_idx += 1; + } } void r_window_begin_frame(WM_Window window, R_Handle window_equip) @@ -338,12 +359,11 @@ void r_window_begin_frame(WM_Window window, R_Handle window_equip) } // Open the command list for that window that frame - // TODO : multiple command list as we have multiple windows + uint64 frame_slot = r_d3d12_state->frame_idx % 2; r_window->framebuffer_idx = IDXGISwapChain3_GetCurrentBackBufferIndex(r_window->swapchain); - ID3D12CommandAllocator* allocator = r_d3d12_state->command_allocators[r_window->framebuffer_idx]; + ID3D12CommandAllocator* allocator = r_d3d12_state->command_allocators[frame_slot]; ID3D12GraphicsCommandList* cmd_list = r_d3d12_state->command_list; - ID3D12CommandAllocator_Reset(allocator); ID3D12GraphicsCommandList1_Reset(cmd_list, allocator, 0); // Barrier to transition from Present (end of frame) to render target @@ -384,9 +404,8 @@ void r_window_end_frame(WM_Window window, R_Handle window_equip) ID3D12GraphicsCommandList_Close(cmd_list); ID3D12CommandQueue_ExecuteCommandLists(r_d3d12_state->direct_command_queue, 1, (ID3D12CommandList**)&cmd_list); - IDXGISwapChain3_Present(r_window->swapchain, 1, 0); - - // Fence until gpu finishes work - r_d3d12_wait(); + UINT sync_interval = r_d3d12_state->frame_has_presented ? 0 : 1; + IDXGISwapChain3_Present(r_window->swapchain, sync_interval, 0); + r_d3d12_state->frame_has_presented = 1; } } diff --git a/Juliet/render/d3d12/render_d3d12.h b/Juliet/render/d3d12/render_d3d12.h index 1c58c0f..37a4e33 100644 --- a/Juliet/render/d3d12/render_d3d12.h +++ b/Juliet/render/d3d12/render_d3d12.h @@ -37,6 +37,8 @@ struct R_D3D12_State Arena* arena; R_D3D12_Window* first_free_window; RWMutex device_rw_mutex; + uint8 frame_idx; + bool8 frame_has_presented; // base d3d12 object ID3D12Device4* device; @@ -50,7 +52,8 @@ struct R_D3D12_State // Fence ID3D12Fence* fence; - uint64 fence_value; + uint64 global_fence_value; + uint64 frame_fence_value[2]; HANDLE fence_event; }; @@ -70,3 +73,4 @@ internal R_Handle r_d3d12_handle_from_window(R_D3D12_Window* window); // Wait Function internal void r_d3d12_wait(); +internal void r_d3d12_wait_for_fence_value(uint64 fence_value);