diff --git a/Juliet/core/core.h b/Juliet/core/core.h index 5a1c338..d2ae78e 100644 --- a/Juliet/core/core.h +++ b/Juliet/core/core.h @@ -178,6 +178,13 @@ #define ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0])) +#if ARCH_64BIT +# define IntFromPtr(ptr) ((uint64)(ptr)) +#else +# error Missing pointer to integer cast for this architecture +#endif +#define PtrFromInt(i) (void*)(i) + // ============================================================================= // Core Types diff --git a/Juliet/core/core_defines.h b/Juliet/core/core_defines.h index 67559b7..482769c 100644 --- a/Juliet/core/core_defines.h +++ b/Juliet/core/core_defines.h @@ -39,6 +39,13 @@ # error Compiler not supported. #endif +// ========================================================================== // +// Architecture + +#if defined(ARCH_X64) +# define ARCH_64BIT 1 +#endif + // ========================================================================== // // Language diff --git a/Juliet/core/core_threads.h b/Juliet/core/core_threads.h index 61ff3f2..5ed7aea 100644 --- a/Juliet/core/core_threads.h +++ b/Juliet/core/core_threads.h @@ -1,5 +1,14 @@ #pragma once +// ============================================================================= +// Synchronization primitives types + +typedef struct RWMutex RWMutex; +struct RWMutex +{ + uint64 handle[1]; +}; + // ============================================================================= // Thread Info Helpers internal void set_thread_name(String8 name); @@ -10,3 +19,15 @@ internal void set_thread_namef(char* fmt, ...); internal uint32 tid(); internal void set_platform_thread_name(String8 name); + +// ============================================================================= +// Read Write Mutexes functions + +internal RWMutex rw_mutex_alloc(); +internal void rw_mutex_release(RWMutex mutex); +internal void rw_mutex_take(RWMutex mutex, bool32 write_mode); +internal void rw_mutex_drop(RWMutex mutex, bool32 write_mode); +#define rw_mutex_take_r(m) rw_mutex_take((m), (0)) +#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)) diff --git a/Juliet/julietapp/julietapp_main.c b/Juliet/julietapp/julietapp_main.c index 646f876..2c6dc44 100644 --- a/Juliet/julietapp/julietapp_main.c +++ b/Juliet/julietapp/julietapp_main.c @@ -24,6 +24,7 @@ internal bool32 frame() internal void entry_point() { wm_init(); + r_init(); ja_init(); for (bool32 quit = 0; !quit;) @@ -31,4 +32,5 @@ internal void entry_point() quit = update(); } ja_shutdown(); + r_shutdown(); } diff --git a/Juliet/render/d3d12/render_d3d12.c b/Juliet/render/d3d12/render_d3d12.c index e69de29..3b948ce 100644 --- a/Juliet/render/d3d12/render_d3d12.c +++ b/Juliet/render/d3d12/render_d3d12.c @@ -0,0 +1,29 @@ + +// ============================================================================= +// top level layer initialization +void r_init() +{ + HRESULT error = 0; + Arena* arena = arena_alloc(); + r_d3d12_state = push_array(arena, R_D3D12_State, 1); + r_d3d12_state->arena = arena; + r_d3d12_state->device_rw_mutex = rw_mutex_alloc(); +} + +void r_shutdown() +{ + rw_mutex_release(r_d3d12_state->device_rw_mutex); + arena_release(r_d3d12_state->arena); +} + +// ============================================================================= +// window setup/teardown + +R_Handle r_window_equip(WM_Window window) +{ + R_Handle result = { 0 }; + + return result; +} + +void r_window_unequip(WM_Window window, R_Handle window_equip) {} diff --git a/Juliet/render/d3d12/render_d3d12.h b/Juliet/render/d3d12/render_d3d12.h index 6f70f09..a793450 100644 --- a/Juliet/render/d3d12/render_d3d12.h +++ b/Juliet/render/d3d12/render_d3d12.h @@ -1 +1,17 @@ #pragma once + +// ============================================================================= +// D3D12 States Types + +typedef struct R_D3D12_State R_D3D12_State; +struct R_D3D12_State +{ + // states + Arena* arena; + RWMutex device_rw_mutex; +}; + +// ============================================================================= +// Globals + +global R_D3D12_State* r_d3d12_state = 0; diff --git a/Juliet/render/render.h b/Juliet/render/render.h index 6f70f09..04cd74b 100644 --- a/Juliet/render/render.h +++ b/Juliet/render/render.h @@ -1 +1,23 @@ #pragma once + +// ============================================================================= +// Handle type + +typedef union R_Handle R_Handle; +union R_Handle +{ + uint64 u64[1]; + uint32 u32[2]; + uint16 u16[4]; +}; + +// ============================================================================= +// top level layer initialization +void r_init(); +void r_shutdown(); + +// ============================================================================= +// window setup/teardown + +R_Handle r_window_equip(WM_Window window); +void r_window_unequip(WM_Window window, R_Handle window_equip); diff --git a/Juliet/win32/core/win32_core.c b/Juliet/win32/core/win32_core.c index 826c067..627766b 100644 --- a/Juliet/win32/core/win32_core.c +++ b/Juliet/win32/core/win32_core.c @@ -6,6 +6,38 @@ typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDes W32_KERNEL32_EXT_X_LIST #undef X +// ============================================================================= +// Entity Functions + +internal W32_Entity* w32_entity_alloc(W32_EntityKind kind) +{ + W32_Entity* result = 0; + EnterCriticalSection(&w32_state.entity_mutex); + { + result = w32_state.entity_free; + if (result) + { + SLL_stack_pop(w32_state.entity_free); + } + else + { + result = push_array_no_zero(w32_state.entity_arena, W32_Entity, 1); + } + MemoryZeroStruct(result); + } + LeaveCriticalSection(&w32_state.entity_mutex); + result->kind = kind; + return result; +} + +internal void w32_entity_release(W32_Entity* entity) +{ + entity->kind = W32_EntityKind_Null; + EnterCriticalSection(&w32_state.entity_mutex); + SLL_stack_push(w32_state.entity_free, entity); + LeaveCriticalSection(&w32_state.entity_mutex); +} + // ============================================================================= // Time functions @@ -85,6 +117,51 @@ internal void set_platform_thread_name(String8 name) scratch_end(scratch); } +// ============================================================================= +// Synchronization primitive functions + +// read write mutexes + +internal RWMutex rw_mutex_alloc() +{ + W32_Entity* entity = w32_entity_alloc(W32_EntityKind_RWMutex); + InitializeSRWLock(&entity->rw_mutex); + RWMutex result = { IntFromPtr(entity) }; + return result; +} + +internal void rw_mutex_release(RWMutex rw_mutex) +{ + W32_Entity* entity = (W32_Entity*)PtrFromInt(rw_mutex.handle[0]); + w32_entity_release(entity); +} + +internal void rw_mutex_take(RWMutex rw_mutex, bool32 write_mode) +{ + W32_Entity* entity = (W32_Entity*)PtrFromInt(rw_mutex.handle[0]); + if (write_mode) + { + AcquireSRWLockExclusive(&entity->rw_mutex); + } + else + { + AcquireSRWLockShared(&entity->rw_mutex); + } +} + +internal void rw_mutex_drop(RWMutex rw_mutex, bool32 write_mode) +{ + W32_Entity* entity = (W32_Entity*)PtrFromInt(rw_mutex.handle[0]); + if (write_mode) + { + ReleaseSRWLockExclusive(&entity->rw_mutex); + } + else + { + ReleaseSRWLockShared(&entity->rw_mutex); + } +} + // ============================================================================= // Memory @@ -193,6 +270,10 @@ internal void w32_entry_point(int argc, WCHAR** wargv) } } + // setup entity storage + InitializeCriticalSection(&w32_state.entity_mutex); + w32_state.entity_arena = arena_alloc(); + main_thread_core_entry_point(argc, argv); tctx_release(tctx); diff --git a/Juliet/win32/core/win32_core.h b/Juliet/win32/core/win32_core.h index e50e6c7..be8fc8b 100644 --- a/Juliet/win32/core/win32_core.h +++ b/Juliet/win32/core/win32_core.h @@ -7,13 +7,51 @@ #pragma comment(lib, "shell32") // clang-format on +// ============================================================================= +// Entity Types + +typedef enum W32_EntityKind +{ + W32_EntityKind_Null, + W32_EntityKind_RWMutex, +} W32_EntityKind; + +typedef struct W32_Entity W32_Entity; +struct W32_Entity +{ + W32_Entity* next; + W32_EntityKind kind; + union + { + SRWLOCK rw_mutex; + }; +}; + +// ============================================================================= +// W32 state types + typedef struct W32_State W32_State; struct W32_State { - Arena* arena; - SystemInfo system_info; + Arena* arena; - uint64 microsecond_resolution; + // info + SystemInfo system_info; + uint64 microsecond_resolution; + + // entities + CRITICAL_SECTION entity_mutex; + Arena* entity_arena; + W32_Entity* entity_free; }; +// ============================================================================= +// W32 globals + global W32_State w32_state = { 0 }; + +// ============================================================================= +// Entity Functions + +internal W32_Entity* w32_entity_alloc(W32_EntityKind kind); +internal void w32_entity_release(W32_Entity* entity);