started d3d12 renderer. device + swap chain + associate to window

This commit is contained in:
Patedam committed 2026-10-26 22:52:08 -04:00
1 parent d79cf42a3d
commit 2881b2c9d5
13 files changed
+256 -2

No files matched your search

+2
View File
@@ -73,6 +73,8 @@
// =============================================================================
// For loop helpers
#define DeferLoop(begin, end) for (int _i_ = ((begin), 0); !_i_; ++_i_, (end))
#define EachIndex(it, count) (uint64 it = 0; it < (count); ++it)
#define EachNode(it, Type, first) (Type* it = first; it != 0; it = it->next)
+6
View File
@@ -21,6 +21,8 @@ internal uint32 tid();
internal void set_platform_thread_name(String8 name);
// =============================================================================
// Synchronization primitive functions
// Read Write Mutexes functions
internal RWMutex rw_mutex_alloc();
@@ -31,3 +33,7 @@ internal void rw_mutex_drop(RWMutex mutex, bool32 write_mode);
#define rw_mutex_take_w(m) rw_mutex_take((m), (1))
#define rw_mutex_drop_r(m) rw_mutex_drop((m), (0))
#define rw_mutex_drop_w(m) rw_mutex_drop((m), (1))
// Scope macros
#define MutexScopeR(mutex) DeferLoop(rw_mutex_take_r(mutex), rw_mutex_drop_r(mutex))
#define MutexScopeW(mutex) DeferLoop(rw_mutex_take_w(mutex), rw_mutex_drop_w(mutex))
+2
View File
@@ -91,6 +91,7 @@ internal void ja_frame()
JA_WindowRequest* request = ja_window_request_from_id(ws->id);
if (request == 0 || ja_state->quit)
{
r_window_unequip(ws->plat_handle, ws->render_handle);
wm_window_close(ws->plat_handle);
arena_release(ws->arena);
DLL_remove_next_prev_zero(&ja_nil_window_state, ja_state->first_window_state,
@@ -220,6 +221,7 @@ internal JA_WindowState* ja_window_state_from_id(JA_ID id)
// TODO : put those in config, hardcoded for now
String8 title = str8_literal("Juliet");
ws->plat_handle = wm_window_open(rect2fp(50.f, 240.f, 1280.f, 720.f), WM_WindowFlag_UseDefaultPosition, title);
ws->render_handle = r_window_equip(ws->plat_handle);
WM_Monitor zero_monitor = { 0 };
if (!wm_monitor_match(zero_monitor, fav_monitor))
{
+1
View File
@@ -44,6 +44,7 @@ struct JA_WindowState
// Info and handle
Arena* arena;
WM_Window plat_handle;
R_Handle render_handle;
};
typedef struct JA_WindowStateSlot JA_WindowStateSlot;
+2
View File
@@ -4,12 +4,14 @@
// Headers
#include "core/core_inc.h"
#include "shell/shell_inc.h"
#include "window_manager/window_manager_inc.h"
#include "render/render_inc.h"
#include "julietapp/julietapp_inc.h"
// C
#include "core/core_inc.c"
#include "shell/shell_inc.c"
#include "window_manager/window_manager_inc.c"
#include "render/render_inc.c"
#include "julietapp/julietapp_inc.c"
+175 -2
View File
@@ -1,6 +1,29 @@
// TODO : Adapt stuff from D3D12GraphicsDevice.c specially all the shenanigans with dxgi factory and stuff
// TODO : Support more kind of format (HDR)
// =============================================================================
// Helpers
internal R_D3D12_Window* r_d3d12_window_from_handle(R_Handle handle)
{
R_D3D12_Window* window = (R_D3D12_Window*)handle.u64[0];
if (window == 0)
{
window = &r_d3d12_nil_window;
}
return window;
}
internal R_Handle r_d3d12_handle_from_window(R_D3D12_Window* window)
{
R_Handle handle = { 0 };
handle.u64[0] = (uint64)window;
return handle;
}
// =============================================================================
// top level layer initialization
void r_init()
{
HRESULT error = 0;
@@ -8,6 +31,85 @@ void r_init()
r_d3d12_state = push_array(arena, R_D3D12_State, 1);
r_d3d12_state->arena = arena;
r_d3d12_state->device_rw_mutex = rw_mutex_alloc();
// Create base device
D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_12_1;
UINT dxgi_flags = 0;
#if BUILD_DEBUG
dxgi_flags |= DXGI_CREATE_FACTORY_DEBUG;
#endif
error = CreateDXGIFactory2(dxgi_flags, &IID_IDXGIFactory4, (void**)&r_d3d12_state->dxgi_factory);
if (FAILED(error))
{
char buffer[256] = { 0 };
juliet_snprintf(buffer, sizeof(buffer), "D3D12 DXGI factory creation failure (%lx). Process is terminating", error);
sh_message(1, str8_literal("Fatal Error"), str8_cstring(buffer));
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);
if (SUCCEEDED(error))
{
// Prioritize discrete GPU
error = IDXGIFactory6_EnumAdapterByGpuPreference(factory6, 0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
&IID_IDXGIAdapter1, (void**)&r_d3d12_state->dxgi_adapter);
IDXGIFactory6_Release(factory6);
}
else
{
// Pray device 0 is the discrete gpu
error = IDXGIFactory4_EnumAdapters1(r_d3d12_state->dxgi_factory, 0, &r_d3d12_state->dxgi_adapter);
}
// Create basic graphics queue
D3D12_COMMAND_QUEUE_DESC queue_desc = { 0 };
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
error = ID3D12Device4_CreateCommandQueue(r_d3d12_state->device, &queue_desc, &IID_ID3D12CommandQueue,
(void**)&r_d3d12_state->direct_command_queue);
if (FAILED(error))
{
char buffer[256] = { 0 };
juliet_snprintf(buffer, sizeof(buffer), "D3D12 direct command queue creation failure (%lx). Process is terminating", error);
sh_message(1, str8_literal("Fatal Error"), str8_cstring(buffer));
abort_self(1);
}
}
void r_shutdown()
@@ -19,11 +121,82 @@ void r_shutdown()
// =============================================================================
// window setup/teardown
R_Handle r_window_equip(WM_Window window)
R_Handle r_window_equip(WM_Window handle)
{
R_Handle result = { 0 };
MutexScopeW(r_d3d12_state->device_rw_mutex)
{
R_D3D12_Window* window = r_d3d12_state->first_free_window;
if (window != 0)
{
SLL_stack_pop(r_d3d12_state->first_free_window);
MemoryZeroStruct(window);
}
else
{
window = push_array(r_d3d12_state->arena, R_D3D12_Window, 1);
}
HWND hwnd = { 0 };
{
W32_WM_Window* w32_layer_window = w32_wm_window_from_handle(handle);
hwnd = w32_wm_hwnd_from_window(w32_layer_window);
}
// 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_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;
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);
if (FAILED(error))
{
char buffer[256];
juliet_snprintf(buffer, sizeof(buffer), "DXGI swap chain creation failure (%lx). Process is terminating.", error);
sh_message(1, str8_literal("Fatal Error"), str8_cstring(buffer));
abort_self(1);
}
IDXGISwapChain1_QueryInterface(swap_chain1, &IID_IDXGISwapChain3, (void**)&window->swap_chain);
IDXGISwapChain1_Release(swap_chain1);
IDXGIFactory4_MakeWindowAssociation(r_d3d12_state->dxgi_factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
result = r_d3d12_handle_from_window(window);
}
return result;
}
void r_window_unequip(WM_Window window, R_Handle window_equip) {}
void r_window_unequip(WM_Window handle, R_Handle handle_equip)
{
MutexScopeW(r_d3d12_state->device_rw_mutex)
{
R_D3D12_Window* window = r_d3d12_window_from_handle(handle_equip);
if (window != 0)
{
IDXGISwapChain1_Release(window->swap_chain);
SLL_stack_push(r_d3d12_state->first_free_window, window);
}
}
}
+34
View File
@@ -1,17 +1,51 @@
#pragma once
#define COBJMACROS
#define CINTERFACE
#include <d3d12.h>
#include <dxgi1_6.h>
#undef COBJMACROS
#undef CINTERFACE
#pragma comment(lib, "d3d12")
#pragma comment(lib, "dxgi")
#pragma comment(lib, "dxguid")
// =============================================================================
// D3D12 States Types
typedef struct R_D3D12_Window R_D3D12_Window;
struct R_D3D12_Window
{
R_D3D12_Window* next;
IDXGISwapChain3* swap_chain;
};
typedef struct R_D3D12_State R_D3D12_State;
struct R_D3D12_State
{
// states
Arena* arena;
R_D3D12_Window* first_free_window;
RWMutex device_rw_mutex;
// base d3d12 object
ID3D12Device4* device;
IDXGIFactory4* dxgi_factory;
IDXGIAdapter1* dxgi_adapter;
// Commands
ID3D12CommandQueue* direct_command_queue;
};
// =============================================================================
// Globals
global R_D3D12_State* r_d3d12_state = 0;
global read_only R_D3D12_Window r_d3d12_nil_window = { &r_d3d12_nil_window };
// =============================================================================
// Helpers
internal R_D3D12_Window* r_d3d12_window_from_handle(R_Handle handle);
internal R_Handle r_d3d12_handle_from_window(R_D3D12_Window* window);
View File
Whitespace-only changes.
+6
View File
@@ -0,0 +1,6 @@
#pragma once
// =============================================================================
// Shell operations
internal void sh_message(bool32 error, String8 title, String8 message);
+7
View File
@@ -0,0 +1,7 @@
#include "shell.c"
#if OS_WINDOWS
# include "win32/shell/win32_shell.c"
#else
# error Shell functions not implemented for this operating system
#endif
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "shell.h"
#if OS_WINDOWS
# include "win32/shell/win32_shell.h"
#else
# error Shell functions not implemented for this operating system
#endif
+11
View File
@@ -0,0 +1,11 @@
// =============================================================================
// Shell operations
internal void sh_message(bool32 error, String8 title, String8 message)
{
TempArena scratch = scratch_begin(0, 0);
String16 title16 = str16_from_8(scratch.arena, title);
String16 message16 = str16_from_8(scratch.arena, message);
MessageBoxW(0, (WCHAR*)message16.str, (WCHAR*)title16.str, MB_OK | (!!error * MB_ICONERROR));
scratch_end(scratch);
}
+1
View File
@@ -0,0 +1 @@
#pragma once