blue window

This commit is contained in:
Patedam committed 2026-10-27 23:06:45 -04:00
1 parent 2881b2c9d5
commit 5fa75c116e
5 files changed
+300 -62

No files matched your search

+11
View File
@@ -14,6 +14,17 @@ union Vector2f
float32 v[2];
};
typedef union Vector2i Vector2i;
union Vector2i
{
struct
{
int32 x;
int32 y;
};
int32 v[2];
};
// =============================================================================
// Rect Types
+9
View File
@@ -104,6 +104,15 @@ internal void ja_frame()
}
}
// render frame
r_begin_frame();
for (JA_WindowState* w = ja_state->first_window_state; w != &ja_nil_window_state; w = w->order_next)
{
r_window_begin_frame(w->plat_handle, w->render_handle);
r_window_end_frame(w->plat_handle, w->render_handle);
}
r_end_frame();
// show window after first frame
if (ja_state->frame_depth == 1)
{
+249 -59
View File
@@ -21,6 +21,20 @@ internal R_Handle r_d3d12_handle_from_window(R_D3D12_Window* window)
return handle;
}
// =============================================================================
// Wait Function
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)
{
ID3D12Fence_SetEventOnCompletion(r_d3d12_state->fence, r_d3d12_state->fence_value, r_d3d12_state->fence_event);
WaitForSingleObject(r_d3d12_state->fence_event, INFINITE);
}
}
// =============================================================================
// top level layer initialization
@@ -37,6 +51,13 @@ void r_init()
UINT dxgi_flags = 0;
#if BUILD_DEBUG
ID3D12Debug1* debug_controller = 0;
if (SUCCEEDED(D3D12GetDebugInterface(&IID_ID3D12Debug1, (void**)&debug_controller)))
{
ID3D12Debug1_EnableDebugLayer(debug_controller);
ID3D12Debug1_SetEnableGPUBasedValidation(debug_controller, TRUE);
ID3D12Debug1_Release(debug_controller);
}
dxgi_flags |= DXGI_CREATE_FACTORY_DEBUG;
#endif
@@ -49,38 +70,6 @@ void r_init()
abort_self(1);
}
error = D3D12CreateDevice(0, feature_level, &IID_ID3D12Device4, (void**)&r_d3d12_state->device);
if (FAILED(error))
{
IDXGIAdapter1* warp_adapter = 0;
error = IDXGIFactory4_EnumWarpAdapter(r_d3d12_state->dxgi_factory, &IID_IDXGIFactory1, (void**)&warp_adapter);
if (SUCCEEDED(error))
{
error = D3D12CreateDevice((IUnknown*)warp_adapter, feature_level, &IID_ID3D12Device4, (void**)&r_d3d12_state->device);
}
IDXGIAdapter1_Release(warp_adapter);
}
if (FAILED(error))
{
char buffer[256] = { 0 };
juliet_snprintf(buffer, sizeof(buffer), "D3D12 device factory creation failure (%lx). Process is terminating", error);
sh_message(1, str8_literal("Fatal Error"), str8_cstring(buffer));
abort_self(1);
}
// break on error
#if BUILD_DEBUG
ID3D12InfoQueue* info = 0;
error = ID3D12Device4_QueryInterface(r_d3d12_state->device, &IID_ID3D12InfoQueue, (void**)info);
if (SUCCEEDED(error))
{
error = ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
error = ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
ID3D12InfoQueue_Release(info);
}
#endif
// dxgi setup (device and adapter)
IDXGIFactory6* factory6 = 0;
error = IDXGIFactory4_QueryInterface(r_d3d12_state->dxgi_factory, &IID_IDXGIFactory6, (void**)&factory6);
@@ -97,6 +86,41 @@ void r_init()
error = IDXGIFactory4_EnumAdapters1(r_d3d12_state->dxgi_factory, 0, &r_d3d12_state->dxgi_adapter);
}
error = D3D12CreateDevice((IUnknown*)r_d3d12_state->dxgi_adapter, feature_level, &IID_ID3D12Device4,
(void**)&r_d3d12_state->device);
// Try warp as hardware is no available
if (FAILED(error))
{
IDXGIAdapter1_Release(r_d3d12_state->dxgi_adapter);
error = IDXGIFactory4_EnumWarpAdapter(r_d3d12_state->dxgi_factory, &IID_IDXGIAdapter, (void**)&r_d3d12_state->dxgi_adapter);
if (SUCCEEDED(error))
{
error = D3D12CreateDevice((IUnknown*)r_d3d12_state->dxgi_adapter, feature_level, &IID_ID3D12Device4,
(void**)&r_d3d12_state->device);
}
}
if (FAILED(error))
{
char buffer[256] = { 0 };
juliet_snprintf(buffer, sizeof(buffer), "D3D12 device factory creation failure (%lx). Process is terminating", error);
sh_message(1, str8_literal("Fatal Error"), str8_cstring(buffer));
abort_self(1);
}
// break on error
#if BUILD_DEBUG
ID3D12InfoQueue* info = 0;
error = ID3D12Device4_QueryInterface(r_d3d12_state->device, &IID_ID3D12InfoQueue, (void**)&info);
if (SUCCEEDED(error))
{
error = ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
error = ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
ID3D12InfoQueue_Release(info);
}
#endif
// Create basic graphics queue
D3D12_COMMAND_QUEUE_DESC queue_desc = { 0 };
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
@@ -110,10 +134,39 @@ void r_init()
sh_message(1, str8_literal("Fatal Error"), str8_cstring(buffer));
abort_self(1);
}
// Create command allocator and command list
for EachIndex(i, 2)
{
ID3D12Device4_CreateCommandAllocator(r_d3d12_state->device, D3D12_COMMAND_LIST_TYPE_DIRECT,
&IID_ID3D12CommandAllocator, (void**)&r_d3d12_state->command_allocators[i]);
}
ID3D12Device4_CreateCommandList1(r_d3d12_state->device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_LIST_FLAG_NONE,
&IID_ID3D12GraphicsCommandList, (void**)&r_d3d12_state->command_list);
ID3D12Device4_CreateFence(r_d3d12_state->device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, (void**)&r_d3d12_state->fence);
r_d3d12_state->fence_event = CreateEventW(0, FALSE, FALSE, 0);
}
void r_shutdown()
{
MutexScopeW(r_d3d12_state->device_rw_mutex)
{
r_d3d12_wait();
CloseHandle(r_d3d12_state->fence_event);
ID3D12Fence_Release(r_d3d12_state->fence);
for EachIndex(i,2)
{
ID3D12CommandAllocator_Release(r_d3d12_state->command_allocators[i]);
}
ID3D12CommandList_Release(r_d3d12_state->command_list);
ID3D12CommandQueue_Release(r_d3d12_state->direct_command_queue);
ID3D12Device4_Release(r_d3d12_state->device);
IDXGIAdapter1_Release(r_d3d12_state->dxgi_adapter);
IDXGIFactory4_Release(r_d3d12_state->dxgi_factory);
}
rw_mutex_release(r_d3d12_state->device_rw_mutex);
arena_release(r_d3d12_state->arena);
}
@@ -145,31 +198,31 @@ R_Handle r_window_equip(WM_Window handle)
}
// Create swapchain
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = { 0 };
swap_chain_desc.Width = 0; // Use all window width
swap_chain_desc.Height = 0; // Use all window height
swap_chain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swap_chain_desc.Stereo = 0;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.BufferCount = 2; // Double buffering
swap_chain_desc.Scaling = DXGI_SCALING_NONE;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
swap_chain_desc.Flags = 0;
DXGI_SWAP_CHAIN_DESC1 swapchain_desc = { 0 };
swapchain_desc.Width = 0; // Use all window width
swapchain_desc.Height = 0; // Use all window height
swapchain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapchain_desc.Stereo = 0;
swapchain_desc.SampleDesc.Count = 1;
swapchain_desc.SampleDesc.Quality = 0;
swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapchain_desc.BufferCount = 2; // Double buffering
swapchain_desc.Scaling = DXGI_SCALING_NONE;
swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapchain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
swapchain_desc.Flags = 0;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swap_chain_fullscreen_desc = { 0 };
swap_chain_fullscreen_desc.RefreshRate.Numerator = 0;
swap_chain_fullscreen_desc.RefreshRate.Denominator = 0;
swap_chain_fullscreen_desc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swap_chain_fullscreen_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swap_chain_fullscreen_desc.Windowed = TRUE;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapchain_fullscreen_desc = { 0 };
swapchain_fullscreen_desc.RefreshRate.Numerator = 0;
swapchain_fullscreen_desc.RefreshRate.Denominator = 0;
swapchain_fullscreen_desc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapchain_fullscreen_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapchain_fullscreen_desc.Windowed = TRUE;
IDXGISwapChain1* swap_chain1 = 0;
HRESULT error =
IDXGIFactory4_CreateSwapChainForHwnd(r_d3d12_state->dxgi_factory, (IUnknown*)r_d3d12_state->direct_command_queue,
hwnd, &swap_chain_desc, &swap_chain_fullscreen_desc, 0, &swap_chain1);
IDXGISwapChain1* swapchain1 = 0;
HRESULT error = IDXGIFactory4_CreateSwapChainForHwnd(r_d3d12_state->dxgi_factory,
(IUnknown*)r_d3d12_state->direct_command_queue, hwnd,
&swapchain_desc, &swapchain_fullscreen_desc, 0, &swapchain1);
if (FAILED(error))
{
char buffer[256];
@@ -178,11 +231,38 @@ R_Handle r_window_equip(WM_Window handle)
abort_self(1);
}
IDXGISwapChain1_QueryInterface(swap_chain1, &IID_IDXGISwapChain3, (void**)&window->swap_chain);
IDXGISwapChain1_Release(swap_chain1);
IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void**)&window->swapchain);
IDXGISwapChain1_Release(swapchain1);
IDXGIFactory4_MakeWindowAssociation(r_d3d12_state->dxgi_factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
// Create framebuffer and rtv for swapchain
D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc = { 0 };
rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtv_heap_desc.NumDescriptors = 2;
rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
ID3D12Device4_CreateDescriptorHeap(r_d3d12_state->device, &rtv_heap_desc, &IID_ID3D12DescriptorHeap,
(void**)&window->rtv_heap);
UINT rtv_stride = ID3D12Device4_GetDescriptorHandleIncrementSize(r_d3d12_state->device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = { 0 };
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(window->rtv_heap, &rtv_handle);
for (UINT i = 0; i < 2; ++i)
{
window->rtv_handles[i] = rtv_handle;
IDXGISwapChain3_GetBuffer(window->swapchain, i, &IID_ID3D12Resource, (void**)&window->framebuffer[i]);
ID3D12Device4_CreateRenderTargetView(r_d3d12_state->device, window->framebuffer[i], 0, window->rtv_handles[i]);
rtv_handle.ptr += rtv_stride;
}
// Save resolution in case of resize
Rect2f client_rect = wm_client_rect_from_window(handle);
Vector2i resolution = { (int32)(client_rect.x1 - client_rect.x0), (int32)(client_rect.y1 - client_rect.y0) };
window->last_resolution = resolution;
result = r_d3d12_handle_from_window(window);
}
return result;
@@ -192,11 +272,121 @@ void r_window_unequip(WM_Window handle, R_Handle handle_equip)
{
MutexScopeW(r_d3d12_state->device_rw_mutex)
{
r_d3d12_wait();
R_D3D12_Window* window = r_d3d12_window_from_handle(handle_equip);
if (window != 0)
if (window != 0 && window != &r_d3d12_nil_window)
{
IDXGISwapChain1_Release(window->swap_chain);
for EachIndex(i, 2)
{
ID3D12Resource_Release(window->framebuffer[i]);
}
ID3D12DescriptorHeap_Release(window->rtv_heap);
IDXGISwapChain1_Release(window->swapchain);
SLL_stack_push(r_d3d12_state->first_free_window, window);
}
}
}
// frame markers
void r_begin_frame()
{
// No-op
}
void r_end_frame()
{
// pouet
}
void r_window_begin_frame(WM_Window window, R_Handle window_equip)
{
MutexScopeW(r_d3d12_state->device_rw_mutex)
{
R_D3D12_Window* r_window = r_d3d12_window_from_handle(window_equip);
// Get resolution
Rect2f client_rect = wm_client_rect_from_window(window);
Vector2i resolution = { (int32)(client_rect.x1 - client_rect.x0), (int32)(client_rect.y1 - client_rect.y0) };
// change resolution
if (resolution.x > 0 && resolution.y > 0 &&
(r_window->last_resolution.x != resolution.x || r_window->last_resolution.y != resolution.y))
{
r_window->last_resolution = resolution;
// resize swap chain
r_d3d12_wait();
for EachIndex(i,2)
{
if (r_window->framebuffer[i] != 0)
{
ID3D12Resource_Release(r_window->framebuffer[i]);
r_window->framebuffer[i] = 0;
}
}
IDXGISwapChain3_ResizeBuffers(r_window->swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
for EachIndex(i,2)
{
IDXGISwapChain3_GetBuffer(r_window->swapchain, i, &IID_ID3D12Resource, (void**)&r_window->framebuffer[i]);
ID3D12Device4_CreateRenderTargetView(r_d3d12_state->device, r_window->framebuffer[i], 0, r_window->rtv_handles[i]);
}
}
// Open the command list for that window that frame
// TODO : multiple command list as we have multiple windows
r_window->framebuffer_idx = IDXGISwapChain3_GetCurrentBackBufferIndex(r_window->swapchain);
ID3D12CommandAllocator* allocator = r_d3d12_state->command_allocators[r_window->framebuffer_idx];
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
D3D12_RESOURCE_BARRIER barrier = { 0 };
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = r_window->framebuffer[r_window->framebuffer_idx];
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
ID3D12GraphicsCommandList_ResourceBarrier(cmd_list, 1, &barrier);
// HARDCODED
// BLUE
float32 background[4] = { 0.1f, 0.2f, 0.8f, 1.0f };
ID3D12GraphicsCommandList_ClearRenderTargetView(cmd_list, r_window->rtv_handles[r_window->framebuffer_idx],
background, 0, 0);
}
}
void r_window_end_frame(WM_Window window, R_Handle window_equip)
{
MutexScopeW(r_d3d12_state->device_rw_mutex)
{
R_D3D12_Window* r_window = r_d3d12_window_from_handle(window_equip);
ID3D12GraphicsCommandList* cmd_list = r_d3d12_state->command_list;
// Transition from render target to present
D3D12_RESOURCE_BARRIER barrier = { 0 };
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = r_window->framebuffer[r_window->framebuffer_idx];
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
ID3D12GraphicsCommandList_ResourceBarrier(cmd_list, 1, &barrier);
// Close command list and push it onto the command queue
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();
}
}
+24 -3
View File
@@ -17,8 +17,17 @@
typedef struct R_D3D12_Window R_D3D12_Window;
struct R_D3D12_Window
{
R_D3D12_Window* next;
IDXGISwapChain3* swap_chain;
R_D3D12_Window* next;
// SwapChain and framebuffer
IDXGISwapChain3* swapchain;
ID3D12Resource* framebuffer[2];
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[2];
ID3D12DescriptorHeap* rtv_heap;
uint8 framebuffer_idx;
// last state
Vector2i last_resolution;
};
typedef struct R_D3D12_State R_D3D12_State;
@@ -35,7 +44,14 @@ struct R_D3D12_State
IDXGIAdapter1* dxgi_adapter;
// Commands
ID3D12CommandQueue* direct_command_queue;
ID3D12CommandQueue* direct_command_queue;
ID3D12CommandAllocator* command_allocators[2];
ID3D12GraphicsCommandList* command_list;
// Fence
ID3D12Fence* fence;
uint64 fence_value;
HANDLE fence_event;
};
// =============================================================================
@@ -49,3 +65,8 @@ global read_only R_D3D12_Window r_d3d12_nil_window = { &r_d3d12_nil_window };
internal R_D3D12_Window* r_d3d12_window_from_handle(R_Handle handle);
internal R_Handle r_d3d12_handle_from_window(R_D3D12_Window* window);
// =============================================================================
// Wait Function
internal void r_d3d12_wait();
+7
View File
@@ -21,3 +21,10 @@ void r_shutdown();
R_Handle r_window_equip(WM_Window window);
void r_window_unequip(WM_Window window, R_Handle window_equip);
// frame markers
void r_begin_frame();
void r_end_frame();
void r_window_begin_frame(WM_Window window, R_Handle window_equip);
void r_window_end_frame(WM_Window window, R_Handle window_equip);