started d3d12 renderer. device + swap chain + associate to window
This commit is contained in:
1 parent
d79cf42a3d
commit
2881b2c9d5
13 files changed
+259
-5
No files matched your search
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
@@ -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))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
RWMutex device_rw_mutex;
|
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
|
// 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);
|
||||||
Whitespace-only changes.
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Shell operations
|
||||||
|
|
||||||
|
internal void sh_message(bool32 error, String8 title, String8 message);
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#pragma once
|
||||||
Reference in new issue
Block a user