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 // 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 EachIndex(it, count) (uint64 it = 0; it < (count); ++it)
#define EachNode(it, Type, first) (Type* it = first; it != 0; it = it->next) #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); internal void set_platform_thread_name(String8 name);
// ============================================================================= // =============================================================================
// Synchronization primitive functions
// Read Write Mutexes functions // Read Write Mutexes functions
internal RWMutex rw_mutex_alloc(); 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_take_w(m) rw_mutex_take((m), (1))
#define rw_mutex_drop_r(m) rw_mutex_drop((m), (0)) #define rw_mutex_drop_r(m) rw_mutex_drop((m), (0))
#define rw_mutex_drop_w(m) rw_mutex_drop((m), (1)) #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); JA_WindowRequest* request = ja_window_request_from_id(ws->id);
if (request == 0 || ja_state->quit) if (request == 0 || ja_state->quit)
{ {
r_window_unequip(ws->plat_handle, ws->render_handle);
wm_window_close(ws->plat_handle); wm_window_close(ws->plat_handle);
arena_release(ws->arena); arena_release(ws->arena);
DLL_remove_next_prev_zero(&ja_nil_window_state, ja_state->first_window_state, 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 // TODO : put those in config, hardcoded for now
String8 title = str8_literal("Juliet"); 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->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 }; WM_Monitor zero_monitor = { 0 };
if (!wm_monitor_match(zero_monitor, fav_monitor)) if (!wm_monitor_match(zero_monitor, fav_monitor))
{ {
+1
View File
@@ -44,6 +44,7 @@ struct JA_WindowState
// Info and handle // Info and handle
Arena* arena; Arena* arena;
WM_Window plat_handle; WM_Window plat_handle;
R_Handle render_handle;
}; };
typedef struct JA_WindowStateSlot JA_WindowStateSlot; typedef struct JA_WindowStateSlot JA_WindowStateSlot;
+2
View File
@@ -4,12 +4,14 @@
// Headers // Headers
#include "core/core_inc.h" #include "core/core_inc.h"
#include "shell/shell_inc.h"
#include "window_manager/window_manager_inc.h" #include "window_manager/window_manager_inc.h"
#include "render/render_inc.h" #include "render/render_inc.h"
#include "julietapp/julietapp_inc.h" #include "julietapp/julietapp_inc.h"
// C // C
#include "core/core_inc.c" #include "core/core_inc.c"
#include "shell/shell_inc.c"
#include "window_manager/window_manager_inc.c" #include "window_manager/window_manager_inc.c"
#include "render/render_inc.c" #include "render/render_inc.c"
#include "julietapp/julietapp_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 // top level layer initialization
void r_init() void r_init()
{ {
HRESULT error = 0; HRESULT error = 0;
@@ -8,6 +31,85 @@ void r_init()
r_d3d12_state = push_array(arena, R_D3D12_State, 1); r_d3d12_state = push_array(arena, R_D3D12_State, 1);
r_d3d12_state->arena = arena; r_d3d12_state->arena = arena;
r_d3d12_state->device_rw_mutex = rw_mutex_alloc(); 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() void r_shutdown()
@@ -19,11 +121,82 @@ void r_shutdown()
// ============================================================================= // =============================================================================
// window setup/teardown // window setup/teardown
R_Handle r_window_equip(WM_Window window) R_Handle r_window_equip(WM_Window handle)
{ {
R_Handle result = { 0 }; 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; 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 #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 // 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; typedef struct R_D3D12_State R_D3D12_State;
struct R_D3D12_State struct R_D3D12_State
{ {
// states // states
Arena* arena; Arena* arena;
R_D3D12_Window* first_free_window;
RWMutex device_rw_mutex; RWMutex device_rw_mutex;
// base d3d12 object
ID3D12Device4* device;
IDXGIFactory4* dxgi_factory;
IDXGIAdapter1* dxgi_adapter;
// Commands
ID3D12CommandQueue* direct_command_queue;
}; };
// ============================================================================= // =============================================================================
// Globals // Globals
global R_D3D12_State* r_d3d12_state = 0; 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