begin job refactor

This commit is contained in:
jacob 2025-08-02 09:11:26 -05:00
parent 59e724f57a
commit 7906108994
47 changed files with 2194 additions and 2344 deletions

View File

@ -101,8 +101,8 @@ AppArgList ParseAppArgs(Arena *arena, String args_str)
value_end = i + 1; value_end = i + 1;
} }
if (key_start >= 0 && key_end > key_start && key_end <= (i64)args_str.len && value_start >= 0 && value_end > value_start && value_end <= (i64)args_str.len) { if (key_start >= 0 && key_end > key_start && key_end <= (i64)args_str.len && value_start >= 0 && value_end > value_start && value_end <= (i64)args_str.len) {
String key = CopyString(arena, STRING(key_end - key_start, args_str.text + key_start)); String key = PushString(arena, STRING(key_end - key_start, args_str.text + key_start));
String value = CopyString(arena, STRING(value_end - value_start, args_str.text + value_start)); String value = PushString(arena, STRING(value_end - value_start, args_str.text + value_start));
AppArg *arg = PushStruct(arena, AppArg); AppArg *arg = PushStruct(arena, AppArg);
arg->key = key; arg->key = key;
arg->value = value; arg->value = value;
@ -223,7 +223,7 @@ void P_AppStartup(String args_str)
P_LogInfoF("Settings file not found, loading default"); P_LogInfoF("Settings file not found, loading default");
window_settings = GetDefaultAppWindowSettings(window); window_settings = GetDefaultAppWindowSettings(window);
} }
CopyStringToBuffer(StringFromArray(window_settings.title), Lit(WINDOW_TITLE)); PushStringToBuffer(StringFromArray(window_settings.title), Lit(WINDOW_TITLE));
P_UpdateWindowSettings(window, &window_settings); P_UpdateWindowSettings(window, &window_settings);
EndTempArena(temp); EndTempArena(temp);
@ -237,17 +237,15 @@ void P_AppStartup(String args_str)
/* Subsystems */ /* Subsystems */
AC_StartupReceipt asset_cache_sr = AC_Startup(); AC_StartupReceipt asset_cache_sr = AC_Startup();
TTF_StartupReceipt ttf_sr = TTF_Startup(); TTF_Startup();
F_StartupReceipt font_sr = F_Startup(&asset_cache_sr, &ttf_sr);
S_StartupReceipt sprite_sr = S_Startup(); S_StartupReceipt sprite_sr = S_Startup();
MIX_StartupReceipt mixer_sr = MIX_Startup(); MIX_StartupReceipt mixer_sr = MIX_Startup();
SND_StartupReceipt sound_sr = SND_Startup(&asset_cache_sr); D_StartupReceipt draw_sr = D_Startup();
D_StartupReceipt draw_sr = D_Startup(&font_sr);
/* Interface systems */ /* Interface systems */
SimStartupReceipt sim_sr = SimStartup(); SimStartupReceipt sim_sr = SimStartup();
PB_StartupReceipt playback_sr = PB_Startup(&mixer_sr); PB_StartupReceipt playback_sr = PB_Startup(&mixer_sr);
UserStartupReceipt user_sr = StartupUser(&font_sr, &sprite_sr, &draw_sr, &asset_cache_sr, &sound_sr, &mixer_sr, &sim_sr, connect_address); UserStartupReceipt user_sr = StartupUser(&sprite_sr, &draw_sr, &asset_cache_sr, &mixer_sr, &sim_sr, connect_address);
LAX user_sr; LAX user_sr;
LAX playback_sr; LAX playback_sr;

View File

@ -407,7 +407,7 @@ void ASE_Inflate(u8 *dst, u8 *encoded)
void ASE_PushError(Arena *arena, ASE_ErrorList *list, String msg_src) void ASE_PushError(Arena *arena, ASE_ErrorList *list, String msg_src)
{ {
ASE_Error *e = PushStruct(arena, ASE_Error); ASE_Error *e = PushStruct(arena, ASE_Error);
e->msg = CopyString(arena, msg_src); e->msg = PushString(arena, msg_src);
if (!list->first) if (!list->first)
{ {
list->first = e; list->first = e;

View File

@ -126,7 +126,7 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
{ {
/* Copy key to store */ /* Copy key to store */
AC_Store store = AC_OpenStore(); AC_Store store = AC_OpenStore();
key_stored = CopyString(store.arena, key); key_stored = PushString(store.arena, key);
AC_CloseStore(&store); AC_CloseStore(&store);
} }
/* Initialize asset data */ /* Initialize asset data */

View File

@ -17,7 +17,7 @@ Struct(AC_Asset)
u64 hash; u64 hash;
String key; String key;
P_Counter counter; Counter counter;
/* Managed via asset_cache_mark_x functions */ /* Managed via asset_cache_mark_x functions */
AC_Status status; AC_Status status;

View File

@ -1,6 +1,5 @@
#include "base.h" #include "base.h"
#include "base_fiber.c"
#include "base_arena.c" #include "base_arena.c"
#include "base_gstat.c" #include "base_gstat.c"
#include "base_memory.c" #include "base_memory.c"
@ -11,3 +10,9 @@
#include "base_uid.c" #include "base_uid.c"
#include "base_uni.c" #include "base_uni.c"
#include "base_incbin.c" #include "base_incbin.c"
#if PlatformIsWindows
# include "win32/base_win32.c"
#else
# error Base layer platform backend not implemented
#enidf

View File

@ -7,9 +7,8 @@
//- Base cpu includes //- Base cpu includes
#include "../prof/prof.h" #include "../prof/prof.h"
# include "base_intrinsics.h" # include "base_intrinsics.h"
# include "base_atomic.h"
# include "base_fiber.h"
# include "base_memory.h" # include "base_memory.h"
# include "base_job.h"
# include "base_arena.h" # include "base_arena.h"
# include "base_uid.h" # include "base_uid.h"
# include "base_string.h" # include "base_string.h"
@ -20,6 +19,11 @@
# include "base_rand.h" # include "base_rand.h"
# include "base_util.h" # include "base_util.h"
# include "base_incbin.h" # include "base_incbin.h"
#if PlatformIsWindows
# include "win32/base_win32.h"
#endif
#elif LanguageIsGpu #elif LanguageIsGpu
//- Base gpu includes //- Base gpu includes
# include "base_math_gpu.h" # include "base_math_gpu.h"

View File

@ -1,88 +0,0 @@
////////////////////////////////
//~ Atomic types
/* NOTE: Must be aligned to 32 bit boundary by user */
Struct(Atomic8)
{
volatile i8 _v;
};
/* NOTE: Must be aligned to 32 bit boundary by user */
Struct(Atomic16)
{
volatile i16 _v;
};
Struct(Atomic32)
{
volatile i32 _v;
};
Struct(Atomic64)
{
volatile i64 _v;
};
////////////////////////////////
//~ Cache-line isolated atomic types
AlignedStruct(Atomic8Padded, 64)
{
Atomic8 v;
u8 _pad[60];
};
StaticAssert(sizeof(Atomic8Padded) == 64 && alignof(Atomic8Padded) == 64);
AlignedStruct(Atomic16Padded, 64)
{
Atomic16 v;
u8 _pad[60];
};
StaticAssert(sizeof(Atomic16Padded) == 64 && alignof(Atomic16Padded) == 64);
AlignedStruct(Atomic32Padded, 64)
{
Atomic32 v;
u8 _pad[60];
};
StaticAssert(sizeof(Atomic32Padded) == 64 && alignof(Atomic32Padded) == 64);
AlignedStruct(Atomic64Padded, 64)
{
Atomic64 v;
u8 _pad[56];
};
StaticAssert(sizeof(Atomic64Padded) == 64 && alignof(Atomic64Padded) == 64);
////////////////////////////////
//~ Atomic operations
#if PlatformIsWindows
ForceInline i8 Atomic8Fetch(Atomic8 *x) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, 0, 0); }
ForceInline i8 Atomic8FetchSet(Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((char *)&x->_v, e); }
ForceInline i8 Atomic8FetchTestSet(Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, e, c); }
ForceInline i8 Atomic8FetchXor(Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((char *)&x->_v, c); }
ForceInline i8 Atomic8FetchAdd(Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((char *)&x->_v, a); }
ForceInline i16 Atomic16Fetch(Atomic16 *x) { return (i16)_InterlockedCompareExchange16(&x->_v, 0, 0); }
ForceInline i16 Atomic16FetchSet(Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&x->_v, e); }
ForceInline i16 Atomic16FetchTestSet(Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&x->_v, e, c); }
ForceInline i16 Atomic16FetchTestXor(Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&x->_v, c); }
ForceInline i16 Atomic16FetchTestAdd(Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&x->_v, a); }
ForceInline i32 Atomic32Fetch(Atomic32 *x) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, 0, 0); }
ForceInline i32 Atomic32FetchSet(Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&x->_v, e); }
ForceInline i32 Atomic32FetchTestSet(Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, e, c); }
ForceInline i32 Atomic32FetchXor(Atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&x->_v, c); }
ForceInline i32 Atomic32FetchAdd(Atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&x->_v, a); }
ForceInline i64 Atomic64Fetch(Atomic64 *x) { return (i64)_InterlockedCompareExchange64(&x->_v, 0, 0); }
ForceInline i64 Atomic64FetchSet(Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&x->_v, e); }
ForceInline i64 Atomic64FetchTestSet(Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&x->_v, e, c); }
ForceInline i64 Atomic64FetchXor(Atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&x->_v, c); }
ForceInline i64 Atomic64FetchAdd(Atomic64 *x, i64 a) { return (i64)_InterlockedExchangeAdd64(&x->_v, a); }
#else
# error Atomics not implemented
#endif

View File

@ -470,6 +470,84 @@ Global const f64 *_f64_nan = (f64 *)&_f64_nan_u64;
#define IsF64Nan(x) (x != x) #define IsF64Nan(x) (x != x)
#endif #endif
////////////////////////////////
//~ Atomics
#if !LanguageIsGpu
//- Atomic types
Struct(Atomic8) { volatile i8 _v; };
Struct(Atomic16) { volatile i16 _v; };
Struct(Atomic32) { volatile i32 _v; };
Struct(Atomic64) { volatile i64 _v; };
//- Cache-line isolated aligned atomic types
AlignedStruct(Atomic8Padded, 64) { Atomic8 v; u8 _pad[60]; };
AlignedStruct(Atomic16Padded, 64) { Atomic16 v; u8 _pad[60]; };
AlignedStruct(Atomic32Padded, 64) { Atomic32 v; u8 _pad[60]; };
AlignedStruct(Atomic64Padded, 64) { Atomic64 v; u8 _pad[56]; };
StaticAssert(sizeof(Atomic8Padded) == 64 && alignof(Atomic8Padded) == 64);
StaticAssert(sizeof(Atomic16Padded) == 64 && alignof(Atomic16Padded) == 64);
StaticAssert(sizeof(Atomic32Padded) == 64 && alignof(Atomic32Padded) == 64);
StaticAssert(sizeof(Atomic64Padded) == 64 && alignof(Atomic64Padded) == 64);
#if PlatformIsWindows
//- 8 bit atomics operations
ForceInline i8 Atomic8Fetch(Atomic8 *x) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, 0, 0); }
ForceInline i8 Atomic8FetchSet(Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((char *)&x->_v, e); }
ForceInline i8 Atomic8FetchTestSet(Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, e, c); }
ForceInline i8 Atomic8FetchXor(Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((char *)&x->_v, c); }
ForceInline i8 Atomic8FetchAdd(Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((char *)&x->_v, a); }
//- 16 bit atomic operations
ForceInline i16 Atomic16Fetch(Atomic16 *x) { return (i16)_InterlockedCompareExchange16(&x->_v, 0, 0); }
ForceInline i16 Atomic16FetchSet(Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&x->_v, e); }
ForceInline i16 Atomic16FetchTestSet(Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&x->_v, e, c); }
ForceInline i16 Atomic16FetchTestXor(Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&x->_v, c); }
ForceInline i16 Atomic16FetchTestAdd(Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&x->_v, a); }
//- 32 bit atomic operations
ForceInline i32 Atomic32Fetch(Atomic32 *x) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, 0, 0); }
ForceInline i32 Atomic32FetchSet(Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&x->_v, e); }
ForceInline i32 Atomic32FetchTestSet(Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, e, c); }
ForceInline i32 Atomic32FetchXor(Atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&x->_v, c); }
ForceInline i32 Atomic32FetchAdd(Atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&x->_v, a); }
//- 64 bit atomic operations
ForceInline i64 Atomic64Fetch(Atomic64 *x) { return (i64)_InterlockedCompareExchange64(&x->_v, 0, 0); }
ForceInline i64 Atomic64FetchSet(Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&x->_v, e); }
ForceInline i64 Atomic64FetchTestSet(Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&x->_v, e, c); }
ForceInline i64 Atomic64FetchXor(Atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&x->_v, c); }
ForceInline i64 Atomic64FetchAdd(Atomic64 *x, i64 a) { return (i64)_InterlockedExchangeAdd64(&x->_v, a); }
#else
# error Atomics not implemented
#endif
#endif
////////////////////////////////
//~ Ticket mutex
#if !LanguageIsGpu
Struct(TicketMutex)
{
Atomic64Padded ticket;
Atomic64Padded serving;
};
ForceInline void LockTicketMutex(TicketMutex *tm)
{
i64 ticket = Atomic64FetchAdd(&tm->ticket.v, 1);
while (Atomic64Fetch(&tm->serving.v) != ticket)
{
_mm_pause();
}
}
ForceInline void UnlockTicketMutex(TicketMutex *tm)
{
Atomic64FetchAdd(&tm->serving.v, 1);
}
#endif
//////////////////////////////// ////////////////////////////////
//~ Config //~ Config

View File

@ -1,19 +0,0 @@
#if PlatformIsWindows
////////////////////////////////
//~ Windows headers
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#include <Windows.h>
////////////////////////////////
//~ FiberId
i16 FiberId(void)
{
return (i16)(i64)GetFiberData();
}
#else
# error FiberId not implemented for this platform
#endif

View File

@ -1,4 +0,0 @@
#define MaxFibers 4096
StaticAssert(MaxFibers < I16Max); /* Fiber id should fit max fibers */
i16 FiberId(void);

View File

@ -73,7 +73,7 @@ String StringFromIncbinRcResource(IncbinRcResource *inc)
/* Spin while another thread searches */ /* Spin while another thread searches */
while (state != IncbinStatus_Searched) while (state != IncbinStatus_Searched)
{ {
IxPause(); _mm_pause();
state = Atomic32Fetch(&inc->state); state = Atomic32Fetch(&inc->state);
} }

View File

@ -103,16 +103,3 @@ Inline f64 IxTruncF64ToF64(f64 f)
{ {
return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)); return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC));
} }
////////////////////////////////
//~ Utility intrinsics
Inline void IxPause(void)
{
_mm_pause();
}
Inline u64 IxClock(void)
{
return __rdtsc();
}

62
src/base/base_job.h Normal file
View File

@ -0,0 +1,62 @@
////////////////////////////////
//~ Job queue types
/* Work pools contain their own worker threads with their own thread priority
* affinity based on the intended context of the pool. */
typedef i32 PoolKind; enum
{
PoolKind_Inherit = -1,
/* The floating pool contains a large number of lower priority worker
* threads that have affinity over the entire CPU. Other pools should push
* jobs that only block and do no work here so that they can yield on the
* blocking job rather than blocking themselves. */
PoolKind_Floating = 0,
PoolKind_Background = 1,
PoolKind_Audio = 2,
PoolKind_User = 3,
PoolKind_Sim = 4,
PoolKind_Count
};
/* Job execution order within a pool is based on priority. */
typedef i32 PriorityKind; enum
{
PriorityKind_Inherit = -1,
PriorityKind_High = 0,
PriorityKind_Normal = 1,
PriorityKind_Low = 2,
PriorityKind_Count
};
////////////////////////////////
//~ @hookdecl Fiber helpers
#define MaxFibers 4096
i16 FiberId(void);
StaticAssert(MaxFibers < I16Max); /* Fiber id type should fit max fibers */
////////////////////////////////
//~ @hookdecl Job helpers
#define EmptySig { i32 _; }
#define JobDecl(job, sigdef) \
typedef struct job##_Sig sigdef job##_Sig; \
Struct(job##_Desc) { Counter *counter; Arena *job_arena; job##_Sig *sig; }; \
void job(job##_Sig *)
#define JobDef(job, sig_arg) void job(job##_Sig *sig_arg)
#define RunJob(job, desc) job(&desc->sig)
////////////////////////////////
//~ @hookdecl Wait
/* Futex-like wait & wake */
void P_Wait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns);
void P_Wake(void *addr, i32 count);

View File

@ -81,7 +81,7 @@ String StringFromI64(Arena *arena, i64 n, u64 base, u64 zfill)
String StringFromPtr(Arena *arena, void *ptr) String StringFromPtr(Arena *arena, void *ptr)
{ {
String prepend = CopyString(arena, Lit("0x")); String prepend = PushString(arena, Lit("0x"));
String uint_str = StringFromU64(arena, (u64)ptr, 16, sizeof(ptr)); String uint_str = StringFromU64(arena, (u64)ptr, 16, sizeof(ptr));
return (String) return (String)
{ {
@ -100,15 +100,15 @@ String StringFromF64(Arena *arena, f64 f, u32 precision)
if (IsF32Nan(f)) if (IsF32Nan(f))
{ {
final_len += CopyString(arena, Lit("NaN")).len; final_len += PushString(arena, Lit("NaN")).len;
} }
else if (f == F64Infinity) else if (f == F64Infinity)
{ {
final_len += CopyString(arena, Lit("inf")).len; final_len += PushString(arena, Lit("inf")).len;
} }
else if (f == -F64Infinity) else if (f == -F64Infinity)
{ {
final_len += CopyString(arena, Lit("-inf")).len; final_len += PushString(arena, Lit("-inf")).len;
} }
else else
{ {
@ -176,9 +176,9 @@ String StringFromhandle(Arena *arena, u64 v0, u64 v1)
{ {
String result = ZI; String result = ZI;
result.text = PushDry(arena, u8); result.text = PushDry(arena, u8);
result.len += CopyString(arena, Lit("h")).len; result.len += PushString(arena, Lit("h")).len;
result.len += StringFromU64(arena, v0, 16, 0).len; result.len += StringFromU64(arena, v0, 16, 0).len;
result.len += CopyString(arena, Lit("x")).len; result.len += PushString(arena, Lit("x")).len;
result.len += StringFromU64(arena, v1, 16, 0).len; result.len += StringFromU64(arena, v1, 16, 0).len;
return result; return result;
} }
@ -198,7 +198,7 @@ String StringFromUid(Arena *arena, Uid uid)
//- Copy //- Copy
String CopyString(Arena *arena, String src) String PushString(Arena *arena, String src)
{ {
String str = { String str = {
.len = src.len, .len = src.len,
@ -208,7 +208,7 @@ String CopyString(Arena *arena, String src)
return str; return str;
} }
String CopyStringToBuffer(String dst, String src) String PushStringToBuffer(String dst, String src)
{ {
String result = ZI; String result = ZI;
result.len = MinU64(dst.len, src.len); result.len = MinU64(dst.len, src.len);
@ -306,7 +306,7 @@ String IndentString(Arena *arena, String str, u32 indent)
StringFromChar(arena, ' '); StringFromChar(arena, ' ');
++final_len; ++final_len;
} }
CopyString(arena, piece); PushString(arena, piece);
final_len += piece.len; final_len += piece.len;
if (i < split.count - 1) if (i < split.count - 1)
{ {
@ -462,11 +462,7 @@ b32 StringEndsWith(String str, String substring)
* included in the arguments (instead of w/ the specifier like in printf). * included in the arguments (instead of w/ the specifier like in printf).
* *
* Example: * Example:
* StringFormat(arena, * StringFormat(arena, Lit("Hello there %F"), FmtString(Lit("George")))
* Lit("Hello there %F. You are %F feet %F inches tall!"),
* FmtString(Lit("George")),
* FmtUint(6),
* FmtFloat(5.375));
* *
* NOTE: FmtEnd must be passed as the last arg in the va_list (This is * NOTE: FmtEnd must be passed as the last arg in the va_list (This is
* done automatically by the `StringFormat` macro). * done automatically by the `StringFormat` macro).
@ -524,7 +520,7 @@ String StringFormatV(Arena *arena, String fmt, va_list args)
case FmtKind_String: case FmtKind_String:
{ {
parsed_str = CopyString(arena, arg.value.string); parsed_str = PushString(arena, arg.value.string);
} break; } break;
case FmtKind_Uint: case FmtKind_Uint:
@ -566,7 +562,7 @@ String StringFormatV(Arena *arena, String fmt, va_list args)
{ {
/* Unexpected end. Not enough FMT args passed to function. */ /* Unexpected end. Not enough FMT args passed to function. */
Assert(0); Assert(0);
parsed_str = CopyString(arena, Lit("<?>")); parsed_str = PushString(arena, Lit("<?>"));
no_more_args = 1; no_more_args = 1;
} break; } break;
@ -574,7 +570,7 @@ String StringFormatV(Arena *arena, String fmt, va_list args)
{ {
/* Unknown format type */ /* Unknown format type */
Assert(0); Assert(0);
parsed_str = CopyString(arena, Lit("<?>")); parsed_str = PushString(arena, Lit("<?>"));
no_more_args = 1; no_more_args = 1;
} break; } break;
} }
@ -757,7 +753,9 @@ String32 String32FromString(Arena *arena, String str8)
} }
//////////////////////////////// ////////////////////////////////
//~ Legacy null-terminated narrow C strings //~ Legacy null-terminated C string operations
//- Narrow C strings
u64 CstrLenNoLimit(char *cstr) u64 CstrLenNoLimit(char *cstr)
{ {
@ -831,8 +829,7 @@ String StringFromCstr(char *cstr, u64 limit)
}; };
} }
//////////////////////////////// //- Wide C strings
//~ Legacy null-terminated wide C strings
u64 WstrLenNoLimit(wchar_t *wstr) u64 WstrLenNoLimit(wchar_t *wstr)
{ {

View File

@ -112,8 +112,8 @@ String StringFromhandle(Arena *arena, u64 v0, u64 v1);
String StringFromUid(Arena *arena, Uid uid); String StringFromUid(Arena *arena, Uid uid);
//- Modification //- Modification
String CopyString(Arena *arena, String src); String PushString(Arena *arena, String src);
String CopyStringToBuffer(String dst, String src); String PushStringToBuffer(String dst, String src);
String RepeatString(Arena *arena, String src, u64 count); String RepeatString(Arena *arena, String src, u64 count);
String CatString(Arena *arena, String str1, String str2); String CatString(Arena *arena, String str1, String str2);
StringArray SplitString(Arena *arena, String str, String delim); StringArray SplitString(Arena *arena, String str, String delim);
@ -161,7 +161,7 @@ String16 String16FromString(Arena *arena, String str8);
String32 String32FromString(Arena *arena, String str8); String32 String32FromString(Arena *arena, String str8);
//////////////////////////////// ////////////////////////////////
//~ Legacy C string operations //~ Legacy null-terminated C string operations
//- Narrow strings //- Narrow strings
u64 CstrLenNoLimit(char *cstr); u64 CstrLenNoLimit(char *cstr);

View File

@ -0,0 +1,3 @@
#include "base_win32.h"
#include "base_win32_job.c"

View File

@ -0,0 +1,8 @@
#ifndef BASE_WIN32_H
#define BASE_WIN32_H
#include "../base.h"
#include "base_win32_job.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,293 @@
////////////////////////////////
//~ Win32 headers
#pragma warning(push, 0)
# define UNICODE
# define WIN32_LEAN_AND_MEAN
# include <Windows.h>
#if 0
# include <WinSock2.h>
# include <TlHelp32.h>
# include <WS2tcpip.h>
# include <windowsx.h>
# include <ShlObj_core.h>
# include <fileapi.h>
# include <dwmapi.h>
# include <bcrypt.h>
# include <avrt.h>
# include <shellapi.h>
#endif
#pragma warning(pop)
////////////////////////////////
//~ Thread types
#define W32_ThreadStackSize Kibi(64)
#define W32_ThreadDef(name, arg_name) void name(void *arg_name)
typedef W32_ThreadDef(W32_ThreadFunc, data);
Struct(W32_Thread)
{
W32_ThreadFunc *entry_point;
void *thread_data;
char thread_name_cstr[256];
wchar_t thread_name_wstr[256];
i32 profiler_group;
W32_Thread *next;
W32_Thread *prev;
HANDLE handle;
};
////////////////////////////////
//~ Wait list types
AlignedStruct(W32_WaitList, 64)
{
u64 value;
i16 first_waiter;
i16 last_waiter;
i32 num_waiters;
W32_WaitList *next_in_bin;
W32_WaitList *prev_in_bin;
};
StaticAssert(alignof(W32_WaitList) == 64); /* Avoid false sharing */
AlignedStruct(W32_WaitBin, 64)
{
W32_WaitList *first_wait_list;
W32_WaitList *last_wait_list;
W32_WaitList *first_free_wait_list;
TicketMutex lock;
};
StaticAssert(alignof(W32_WaitBin) == 64); /* Avoid false sharing */
////////////////////////////////
//~ Fiber types
#define W32_FiberStackSize Mebi(4)
#define W32_FiberNamePrefixCstr "Fiber ["
#define W32_FiberNameSuffixCstr "]"
#define W32_FiberNameMaxSize 64
//- Yield param
typedef i32 W32_YieldKind; enum
{
W32_YieldKind_None,
W32_YieldKind_Done,
W32_YieldKind_Wait,
W32_YieldKind_Count
};
Struct(W32_YieldParam)
{
W32_YieldKind kind;
union
{
struct
{
volatile void *addr;
void *cmp;
u32 size;
i64 timeout_ns;
} wait;
};
};
//- Fiber
AlignedStruct(W32_Fiber, 64)
{
/* ---------------------------------------------------- */
void *addr; /* 08 bytes */
/* ---------------------------------------------------- */
char *name_cstr; /* 08 bytes */
/* ---------------------------------------------------- */
Atomic32 wake_lock; /* 04 bytes (4 byte alignment) */
i16 id; /* 02 bytes */
i16 parent_id; /* 02 bytes */
/* ---------------------------------------------------- */
u64 wait_addr; /* 08 bytes */
/* ---------------------------------------------------- */
u64 wait_time; /* 08 bytes */
/* ---------------------------------------------------- */
i16 next_addr_waiter; /* 02 bytes */
i16 prev_addr_waiter; /* 02 bytes */
i16 next_time_waiter; /* 02 bytes */
i16 prev_time_waiter; /* 02 bytes */
/* ---------------------------------------------------- */
u8 _pad1[8]; /* 08 bytes (padding) */
/* ---------------------------------------------------- */
u8 _pad2[8]; /* 08 bytes (padding) */
/* ---------------------------------------------------- */
/* -------------------- Cache line -------------------- */
/* ---------------------------------------------------- */
void *job_func; /* 08 bytes */
/* ---------------------------------------------------- */
void *job_sig; /* 08 bytes */
/* ---------------------------------------------------- */
i32 job_id; /* 04 bytes */
i16 job_pool; /* 02 bytes */
i16 job_priority; /* 02 bytes */
/* ---------------------------------------------------- */
struct Counter *job_counter; /* 08 bytes */
/* ---------------------------------------------------- */
W32_YieldParam *yield_param; /* 08 bytes */
/* ---------------------------------------------------- */
u8 _pad3[24]; /* 24 bytes (padding) */
};
StaticAssert(sizeof(W32_Fiber) == 128); /* Padding validation (increase if necessary) */
StaticAssert(alignof(W32_Fiber) == 64); /* Verify alignment to avoid false sharing */
StaticAssert(offsetof(W32_Fiber, wake_lock) % 4 == 0); /* Atomic must be aligned */
////////////////////////////////
//~ Job queue types
//- Worker ctx
AlignedStruct(W32_WorkerCtx, 64)
{
PoolKind pool_kind;
i32 id;
};
//- Job info
Struct(W32_JobInfo)
{
i32 num_dispatched;
i32 count;
void *func;
void *sig;
struct Counter *counter;
i16 fiber_id; /* If the job is being resumed from a yield */
W32_JobInfo *next;
};
//- Job queue
AlignedStruct(W32_JobQueue, 64)
{
TicketMutex lock;
Arena *arena;
W32_JobInfo *first;
W32_JobInfo *last;
W32_JobInfo *first_free;
};
//- Job pool
AlignedStruct(W32_JobPool, 64)
{
/* Jobs */
W32_JobQueue job_queues[PriorityKind_Count];
TicketMutex free_fibers_tm;
i16 first_free_fiber_id;
/* Workers */
Atomic32Padded workers_shutdown;
Atomic64Padded num_jobs_in_queue;
TicketMutex workers_wake_tm;
i32 num_worker_threads;
i32 thread_priority;
u64 thread_affinity_mask;
b32 thread_is_audio;
Arena *worker_threads_arena;
W32_Thread **worker_threads;
W32_WorkerCtx *worker_contexts;
};
////////////////////////////////
//~ Shared state
/* Assume scheduler cycle is 20hz at start to be conservative */
#define W32_DefaultSchedulerPeriodNs 50000000
#define W32_NumRollingSchedulerPeriods 1000
#define W32_NumWaitAddrBins 16384
#define W32_NumWaitTimeBins 1024
/* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */
#define W32_WakeAllThreshold 16
Struct(W32_SharedCtx)
{
Atomic32 shutdown;
//- Worker thread pool
TicketMutex threads_tm;
Arena *threads_arena;
W32_Thread *first_thread;
W32_Thread *last_thread;
W32_Thread *first_free_thread;
//- Scheduler
Atomic64Padded current_scheduler_cycle;
Atomic64Padded current_scheduler_cycle_period_ns;
//- Fibers
TicketMutex fibers_tm;
i16 num_fibers;
Arena *fiber_names_arena;
W32_Fiber fibers[MaxFibers];
//- Wait lists
Atomic64Padded waiter_wake_gen;
TicketMutex wait_lists_arena_tm;
Arena *wait_lists_arena;
//- Wait tables
W32_WaitBin wait_addr_bins[W32_NumWaitAddrBins];
W32_WaitBin wait_time_bins[W32_NumWaitTimeBins];
//- Job pools
W32_JobPool job_pools[PoolKind_Count];
};
extern W32_SharedCtx W32_shared_ctx;
////////////////////////////////
//~ Startup
void StartupJobs(void);
////////////////////////////////
//~ Shutdown
void ShutdownJobs(void);
////////////////////////////////
//~ Thread operations
DWORD WINAPI W32_Win32ThreadProc(LPVOID vt);
W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, String thread_name, i32 profiler_group);
b32 W32_TryReleaseThread(W32_Thread *thread, f32 timeout_seconds);
void W32_WaitReleaseThread(W32_Thread *thread);
////////////////////////////////
//~ Wait list operations
void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers);
void W32_WakeByAddress(void *addr, i32 count);
void W32_WakeByTime(u64 time);
////////////////////////////////
//~ Fiber operations
W32_Fiber *W32_AllocFiber(W32_JobPool *pool);
void W32_ReleaseFiber(W32_JobPool *pool, W32_Fiber *fiber);
ForceInline W32_Fiber *W32_FiberFromId(i16 id);
ForceNoInline void W32_FiberResume(W32_Fiber *fiber);
void W32_YieldFiber(W32_Fiber *fiber, W32_Fiber *parent_fiber);
void W32_FiberEntryPoint(void *id_ptr);
////////////////////////////////
//~ Workers
W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg);
W32_ThreadDef(W32_JobSchedulerEntryFunc, _);

View File

@ -3,11 +3,10 @@ D_SharedState D_shared_state = ZI;
//////////////////////////////// ////////////////////////////////
//~ Startup //~ Startup
D_StartupReceipt D_Startup(F_StartupReceipt *font_sr) D_StartupReceipt D_Startup(void)
{ {
__prof; __prof;
D_SharedState *g = &D_shared_state; D_SharedState *g = &D_shared_state;
LAX font_sr;
u32 pixel_white = 0xFFFFFFFF; u32 pixel_white = 0xFFFFFFFF;
g->solid_white_texture = GPU_AllocTexture(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(1, 1), &pixel_white); g->solid_white_texture = GPU_AllocTexture(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(1, 1), &pixel_white);
return (D_StartupReceipt) { 0 }; return (D_StartupReceipt) { 0 };

View File

@ -112,7 +112,7 @@ extern D_SharedState D_shared_state;
//~ Startup //~ Startup
Struct(D_StartupReceipt) { i32 _; }; Struct(D_StartupReceipt) { i32 _; };
D_StartupReceipt D_Startup(F_StartupReceipt *font_sr); D_StartupReceipt D_Startup(void);
//////////////////////////////// ////////////////////////////////
//~ Material operations //~ Material operations

View File

@ -70,7 +70,7 @@ DXC_Result DXC_Compile(Arena *arena, String shader_source, i32 num_args, String
String blob_str = ZI; String blob_str = ZI;
blob_str.len = dxc_errors->GetBufferSize(); blob_str.len = dxc_errors->GetBufferSize();
blob_str.text = (u8 *)dxc_errors->GetBufferPointer(); blob_str.text = (u8 *)dxc_errors->GetBufferPointer();
result.errors = CopyString(arena, blob_str); result.errors = PushString(arena, blob_str);
} }
//- Get status //- Get status
@ -86,7 +86,7 @@ DXC_Result DXC_Compile(Arena *arena, String shader_source, i32 num_args, String
String blob_str = ZI; String blob_str = ZI;
blob_str.len = dxc_shader->GetBufferSize(); blob_str.len = dxc_shader->GetBufferSize();
blob_str.text = (u8 *)dxc_shader->GetBufferPointer(); blob_str.text = (u8 *)dxc_shader->GetBufferPointer();
result.dxc = CopyString(arena, blob_str); result.dxc = PushString(arena, blob_str);
} }
} }

View File

@ -1,51 +1,7 @@
F_SharedState F_shared_state = ZI;
////////////////////////////////
//~ Startup
F_StartupReceipt F_Startup(AC_StartupReceipt *asset_cache_sr, TTF_StartupReceipt *ttf_sr)
{
__prof;
F_SharedState *g = &F_shared_state;
LAX asset_cache_sr;
LAX ttf_sr;
g->params.arena = AllocArena(Gibi(64));
return (F_StartupReceipt) { 0 };
}
//////////////////////////////// ////////////////////////////////
//~ Load job //~ Load job
F_LoadJobSig *F_AllocJobSig(void) JobDef(F_LoadAssetJob, job)
{
F_SharedState *g = &F_shared_state;
F_LoadJobSig *p = 0;
{
P_Lock lock = P_LockE(&g->params.mutex);
if (g->params.head_free)
{
p = g->params.head_free;
g->params.head_free = p->next_free;
}
else
{
p = PushStruct(g->params.arena, F_LoadJobSig);
}
P_Unlock(&lock);
}
return p;
}
void F_ReleaseJobSig(F_LoadJobSig *p)
{
F_SharedState *g = &F_shared_state;
P_Lock lock = P_LockE(&g->params.mutex);
p->next_free = g->params.head_free;
g->params.head_free = p;
P_Unlock(&lock);
}
P_JobDef(F_LoadAssetJob, job)
{ {
__prof; __prof;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
@ -120,7 +76,7 @@ P_JobDef(F_LoadAssetJob, job)
FmtString(path))); FmtString(path)));
} }
/* CopyStruct glyphs from decode result */ /* Copy glyphs from decode result */
StaticAssert(sizeof(*font->glyphs) == sizeof(*result.glyphs)); /* Font glyph size must match TTF glyph size for memcpy */ StaticAssert(sizeof(*font->glyphs) == sizeof(*result.glyphs)); /* Font glyph size must match TTF glyph size for memcpy */
CopyBytes(font->glyphs, result.glyphs, sizeof(*font->glyphs) * result.glyphs_count); CopyBytes(font->glyphs, result.glyphs, sizeof(*font->glyphs) * result.glyphs_count);
@ -131,8 +87,6 @@ P_JobDef(F_LoadAssetJob, job)
font->lookup[codepoint] = result.cache_indices[i]; font->lookup[codepoint] = result.cache_indices[i];
} }
F_ReleaseJobSig(params);
P_LogSuccessF("Loaded font \"%F\" (point size %F) in %F seconds", FmtString(path), FmtFloat((f64)point_size), FmtFloat(SecondsFromNs(P_TimeNs() - start_ns))); P_LogSuccessF("Loaded font \"%F\" (point size %F) in %F seconds", FmtString(path), FmtFloat((f64)point_size), FmtFloat(SecondsFromNs(P_TimeNs() - start_ns)));
AC_MarkReady(asset, font); AC_MarkReady(asset, font);
@ -174,7 +128,7 @@ AC_Asset *F_LoadAsset(String path, f32 point_size, b32 wait)
/* PushStruct task */ /* PushStruct task */
AC_MarkLoading(asset); AC_MarkLoading(asset);
P_Run(1, F_LoadAssetJob, params, P_Pool_Background, P_Priority_Low, 0); P_Run(1, F_LoadAssetJob, params, PoolKind_Background, PriorityKind_Low, 0);
if (wait) if (wait)
{ {
AC_WaitOnAssetReady(asset); AC_WaitOnAssetReady(asset);

View File

@ -1,6 +1,8 @@
//////////////////////////////// ////////////////////////////////
//~ Font types //~ Font types
#define F_LookupTableSize (256)
Struct(F_Glyph) Struct(F_Glyph)
{ {
f32 off_x; f32 off_x;
@ -22,50 +24,10 @@ Struct(F_Font)
u16 *lookup; u16 *lookup;
}; };
////////////////////////////////
//~ Font job types
Struct(F_LoadJobSig)
{
F_LoadJobSig *next_free;
AC_Asset *asset;
f32 point_size;
u64 path_len;
char path_cstr[1024];
};
Struct(F_LoadJobSigStore)
{
F_LoadJobSig *head_free;
Arena *arena;
P_Mutex mutex;
};
////////////////////////////////
//~ Shared state
#define F_LookupTableSize (256)
Struct(F_SharedState)
{
F_LoadJobSigStore params;
};
extern F_SharedState F_shared_state;
////////////////////////////////
//~ Startup
Struct(F_StartupReceipt) { i32 _; };
F_StartupReceipt F_Startup(AC_StartupReceipt *asset_cache_sr, TTF_StartupReceipt *ttf_sr);
//////////////////////////////// ////////////////////////////////
//~ Font load job //~ Font load job
F_LoadJobSig *F_AllocJobSig(void); JobDecl(F_LoadAssetJob, { AC_Asset *asset; f32 point_size; String path; });
void F_ReleaseJobSig(F_LoadJobSig *p);
P_JobDef(F_LoadAssetJob, job);
//////////////////////////////// ////////////////////////////////
//~ Font load operations //~ Font load operations

View File

@ -71,7 +71,7 @@ void GPU_Startup(void)
P_OnExit(GPU_D12_Shutdown); P_OnExit(GPU_D12_Shutdown);
/* Start evictor job */ /* Start evictor job */
P_Run(1, GPU_D12_EvictorJob, 0, P_Pool_Background, P_Priority_Low, &g->evictor_job_counter); P_Run(1, GPU_D12_EvictorJob, 0, PoolKind_Background, PriorityKind_Low, &g->evictor_job_counter);
} }
P_ExitFuncDef(GPU_D12_Shutdown) P_ExitFuncDef(GPU_D12_Shutdown)
@ -319,15 +319,15 @@ void GPU_D12_InitObjects(void)
GPU_D12_CommandQueueDesc params[] = { GPU_D12_CommandQueueDesc params[] = {
{.type = D3D12_COMMAND_LIST_TYPE_DIRECT, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = Lit("Direct queue") }, {.type = D3D12_COMMAND_LIST_TYPE_DIRECT, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = Lit("Direct queue") },
{.type = D3D12_COMMAND_LIST_TYPE_COMPUTE, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = Lit("Compute queue") }, {.type = D3D12_COMMAND_LIST_TYPE_COMPUTE, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = Lit("Compute queue") },
{.type = D3D12_COMMAND_LIST_TYPE_COPY, .priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH, .dbg_name = Lit("Copyqueue") }, {.type = D3D12_COMMAND_LIST_TYPE_COPY, .priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH, .dbg_name = Lit("Copy queue") },
{.type = D3D12_COMMAND_LIST_TYPE_COPY, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = Lit("Background copy queue") } {.type = D3D12_COMMAND_LIST_TYPE_COPY, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = Lit("Background copy queue") }
}; };
GPU_D12_AllocCommandQueueJobSig sig = ZI; GPU_D12_AllocCommandQueueJobSig sig = ZI;
sig.descs_in = params; sig.descs_in = params;
sig.cqs_out = g->command_queues; sig.cqs_out = g->command_queues;
{ {
P_Counter counter = ZI; Counter counter = ZI;
P_Run(DX12_NUM_QUEUES, GPU_D12_AllocCommandQueueJob, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter); P_Run(DX12_NUM_QUEUES, GPU_D12_AllocCommandQueueJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
#if ProfilingIsEnabled #if ProfilingIsEnabled
@ -421,8 +421,8 @@ void GPU_InitPipelines(void)
GPU_D12_AllocPipelineJobSig sig = ZI; GPU_D12_AllocPipelineJobSig sig = ZI;
sig.descs_in = descs; sig.descs_in = descs;
sig.pipelines_out = pipelines; sig.pipelines_out = pipelines;
P_Counter counter = ZI; Counter counter = ZI;
P_Run(num_pipelines, GPU_D12_AllocPipelineJob, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter); P_Run(num_pipelines, GPU_D12_AllocPipelineJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
for (u32 i = 0; i < num_pipelines; ++i) for (u32 i = 0; i < num_pipelines; ++i)
@ -501,11 +501,11 @@ void GPU_D12_InitNoise(void)
/* Upload texture */ /* Upload texture */
{ {
P_Counter counter = ZI; Counter counter = ZI;
GPU_D12_UploadJobSig sig = ZI; GPU_D12_UploadJobSig sig = ZI;
sig.resource = r; sig.resource = r;
sig.data = data.text; sig.data = data.text;
P_Run(1, GPU_D12_UploadJob, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter); P_Run(1, GPU_D12_UploadJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
} }
@ -526,7 +526,7 @@ void GPU_D12_InitNoise(void)
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
P_JobDef(GPU_D12_CompileShaderJob, job) JobDef(GPU_D12_CompileShaderJob, job)
{ {
__prof; __prof;
GPU_D12_CompileShaderJobSig *sig = job.sig; GPU_D12_CompileShaderJobSig *sig = job.sig;
@ -577,7 +577,7 @@ P_JobDef(GPU_D12_CompileShaderJob, job)
* Pipeline * Pipeline
* ========================== */ * ========================== */
P_JobDef(GPU_D12_AllocPipelineJob, job) JobDef(GPU_D12_AllocPipelineJob, job)
{ {
__prof; __prof;
GPU_D12_SharedState *g = &GPU_D12_shared_state; GPU_D12_SharedState *g = &GPU_D12_shared_state;
@ -1116,8 +1116,8 @@ W_CallbackFuncDef(GPU_D12_WatchPipelineCallback, name)
sig.descs[0].target = Lit("cs_6_6"); sig.descs[0].target = Lit("cs_6_6");
} }
{ {
P_Counter counter = ZI; Counter counter = ZI;
P_Run(num_shaders, GPU_D12_CompileShaderJob, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter); P_Run(num_shaders, GPU_D12_CompileShaderJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
} }
@ -1180,8 +1180,8 @@ W_CallbackFuncDef(GPU_D12_WatchPipelineCallback, name)
GPU_D12_AllocPipelineJobSig sig = ZI; GPU_D12_AllocPipelineJobSig sig = ZI;
sig.descs_in = pipeline_descs; sig.descs_in = pipeline_descs;
sig.pipelines_out = pipelines; sig.pipelines_out = pipelines;
P_Counter counter = ZI; Counter counter = ZI;
P_Run(num_pipelines, GPU_D12_AllocPipelineJob, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter); P_Run(num_pipelines, GPU_D12_AllocPipelineJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
{ {
@ -1515,7 +1515,7 @@ void GPU_D12_InsertBarrier(ID3D12GraphicsCommandList *cl, i32 num_descs, GPU_D12
GPU_D12_CommandListPool *GPU_D12_AllocCommandListPool(GPU_D12_CommandQueue *cq); GPU_D12_CommandListPool *GPU_D12_AllocCommandListPool(GPU_D12_CommandQueue *cq);
P_JobDef(GPU_D12_AllocCommandQueueJob, job) JobDef(GPU_D12_AllocCommandQueueJob, job)
{ {
__prof; __prof;
GPU_D12_SharedState *g = &GPU_D12_shared_state; GPU_D12_SharedState *g = &GPU_D12_shared_state;
@ -1853,7 +1853,7 @@ GPU_D12_CommandDescriptorHeap *GPU_D12_PushDescriptorHeap(GPU_D12_CommandList *c
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_gpu_handle); ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_gpu_handle);
} }
/* CopyCPU heap */ /* Copy CPU heap */
{ {
P_Lock lock = P_LockS(&dh_cpu->mutex); P_Lock lock = P_LockS(&dh_cpu->mutex);
ID3D12Device_CopyDescriptorsSimple(g->device, dh_cpu->num_descriptors_reserved, cdh->start_cpu_handle, dh_cpu->handle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); ID3D12Device_CopyDescriptorsSimple(g->device, dh_cpu->num_descriptors_reserved, cdh->start_cpu_handle, dh_cpu->handle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
@ -2017,7 +2017,7 @@ GPU_D12_CommandBuffer *GPU_D12__PushCommandBuffer(GPU_D12_CommandList *cl, u64 d
* Wait job * Wait job
* ========================== */ * ========================== */
P_JobDef(GPU_D12_WaitOnFenceJob, job) JobDef(GPU_D12_WaitOnFenceJob, job)
{ {
__prof; __prof;
GPU_D12_WaitOnFenceJobSig *sig = job.sig; GPU_D12_WaitOnFenceJobSig *sig = job.sig;
@ -2099,11 +2099,11 @@ GPU_Resource *GPU_AllocTexture(GPU_TextureFormat format, u32 flags, Vec2I32 size
if (initial_data) if (initial_data)
{ {
/* TODO: Make wait optional */ /* TODO: Make wait optional */
P_Counter counter = ZI; Counter counter = ZI;
GPU_D12_UploadJobSig sig = ZI; GPU_D12_UploadJobSig sig = ZI;
sig.resource = r; sig.resource = r;
sig.data = initial_data; sig.data = initial_data;
P_Run(1, GPU_D12_UploadJob, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter); P_Run(1, GPU_D12_UploadJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
@ -2120,7 +2120,7 @@ Vec2I32 GPU_GetTextureSize(GPU_Resource *resource)
* Upload * Upload
* ========================== */ * ========================== */
P_JobDef(GPU_D12_UploadJob, job) JobDef(GPU_D12_UploadJob, job)
{ {
GPU_D12_SharedState *g = &GPU_D12_shared_state; GPU_D12_SharedState *g = &GPU_D12_shared_state;
GPU_D12_UploadJobSig *sig = job.sig; GPU_D12_UploadJobSig *sig = job.sig;
@ -2168,7 +2168,7 @@ P_JobDef(GPU_D12_UploadJob, job)
GPU_D12_CommandQueue *cq = g->command_queues[DX12_QUEUE_COPY_BACKGROUND]; GPU_D12_CommandQueue *cq = g->command_queues[DX12_QUEUE_COPY_BACKGROUND];
GPU_D12_CommandList *cl = GPU_D12_BeginCommandList(cq->cl_pool); GPU_D12_CommandList *cl = GPU_D12_BeginCommandList(cq->cl_pool);
{ {
/* Copyto upload heap */ /* Copy to upload heap */
{ {
D3D12_RANGE read_range = ZI; D3D12_RANGE read_range = ZI;
void *mapped = 0; void *mapped = 0;
@ -2194,7 +2194,7 @@ P_JobDef(GPU_D12_UploadJob, job)
ID3D12Resource_Unmap(upload->resource, 0, 0); ID3D12Resource_Unmap(upload->resource, 0, 0);
} }
/* Copyfrom upload heap to texture */ /* Copy from upload heap to texture */
{ {
__profnc_dx12(cl->cq->prof, cl->cl, "Upload texture", Rgb32F(0.2, 0.5, 0.2)); __profnc_dx12(cl->cq->prof, cl->cl, "Upload texture", Rgb32F(0.2, 0.5, 0.2));
D3D12_TEXTURE_COPY_LOCATION dst_loc = { D3D12_TEXTURE_COPY_LOCATION dst_loc = {
@ -2219,8 +2219,8 @@ P_JobDef(GPU_D12_UploadJob, job)
GPU_D12_WaitOnFenceJobSig wait_sig = ZI; GPU_D12_WaitOnFenceJobSig wait_sig = ZI;
wait_sig.fence = cq->submit_fence; wait_sig.fence = cq->submit_fence;
wait_sig.target = fence_target; wait_sig.target = fence_target;
P_Counter counter = ZI; Counter counter = ZI;
P_Run(1, GPU_D12_WaitOnFenceJob, &wait_sig, P_Pool_Floating, P_Priority_Low, &counter); P_Run(1, GPU_D12_WaitOnFenceJob, &wait_sig, PoolKind_Floating, PriorityKind_Low, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
@ -2254,6 +2254,17 @@ void GPU_D12_SetSig(GPU_D12_CommandList *cl, void *src, u32 size)
Assert(size <= 256); /* Only 64 32-bit root constants allowed in signature */ Assert(size <= 256); /* Only 64 32-bit root constants allowed in signature */
u32 num32bit = size / 4; u32 num32bit = size / 4;
b32 is_gfx = cl->cur_pipeline->is_gfx; b32 is_gfx = cl->cur_pipeline->is_gfx;
/* FIXME: Enable this */
#if 0
if (is_gfx)
{
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(cl->cl, 0, num32bit, src, 0);
}
else
{
ID3D12GraphicsCommandList_SetComputeRoot32BitConstants(cl->cl, 0, num32bit, src, 0);
}
#else
for (u32 i = 0; i < num32bit; ++i) for (u32 i = 0; i < num32bit; ++i)
{ {
u32 val = 0; u32 val = 0;
@ -2267,6 +2278,8 @@ void GPU_D12_SetSig(GPU_D12_CommandList *cl, void *src, u32 size)
ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(cl->cl, 0, val, i); ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(cl->cl, 0, val, i);
} }
} }
#endif
} }
struct D3D12_VIEWPORT GPU_D12_ViewportFromRect(Rect r) struct D3D12_VIEWPORT GPU_D12_ViewportFromRect(Rect r)
@ -3321,7 +3334,7 @@ void GPU_PresentSwapchain(GPU_Swapchain *gp_swapchain, Vec2I32 backbuffer_resolu
* Evictor job * Evictor job
* ========================== */ * ========================== */
P_JobDef(GPU_D12_EvictorJob, _) JobDef(GPU_D12_EvictorJob, _)
{ {
GPU_D12_SharedState *g = &GPU_D12_shared_state; GPU_D12_SharedState *g = &GPU_D12_shared_state;
u64 completed_targets[DX12_NUM_QUEUES] = ZI; u64 completed_targets[DX12_NUM_QUEUES] = ZI;
@ -3334,11 +3347,11 @@ P_JobDef(GPU_D12_EvictorJob, _)
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
u64 targets[countof(completed_targets)] = ZI; u64 targets[countof(completed_targets)] = ZI;
/* Copyqueued data */ /* Copy queued data */
u32 num_fenced_releases = 0; u32 num_fenced_releases = 0;
GPU_D12_FencedReleaseData *fenced_releases = 0; GPU_D12_FencedReleaseData *fenced_releases = 0;
{ {
__profn("Copyqueued releases"); __profn("Copy queued releases");
P_Lock lock = P_LockE(&g->fenced_releases_mutex); P_Lock lock = P_LockE(&g->fenced_releases_mutex);
num_fenced_releases = g->fenced_releases_arena->pos / sizeof(GPU_D12_FencedReleaseData); num_fenced_releases = g->fenced_releases_arena->pos / sizeof(GPU_D12_FencedReleaseData);
fenced_releases = PushStructsNoZero(scratch.arena, GPU_D12_FencedReleaseData, num_fenced_releases); fenced_releases = PushStructsNoZero(scratch.arena, GPU_D12_FencedReleaseData, num_fenced_releases);
@ -3365,8 +3378,8 @@ P_JobDef(GPU_D12_EvictorJob, _)
sig.fence = cq->submit_fence; sig.fence = cq->submit_fence;
sig.target = targets[i]; sig.target = targets[i];
{ {
P_Counter counter = ZI; Counter counter = ZI;
P_Run(1, GPU_D12_WaitOnFenceJob, &sig, P_Pool_Floating, P_Priority_Low, &counter); P_Run(1, GPU_D12_WaitOnFenceJob, &sig, PoolKind_Floating, PriorityKind_Low, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
} }

View File

@ -257,14 +257,6 @@ Struct(GPU_D12_FencedReleaseData)
void *ptr; void *ptr;
}; };
Struct(GPU_D12_AllocCommandQueueJobSig) { GPU_D12_CommandQueueDesc *descs_in; GPU_D12_CommandQueue **cqs_out; };
Struct(GPU_D12_AllocPipelineJobSig) { GPU_D12_PipelineDesc *descs_in; GPU_D12_Pipeline **pipelines_out; };
Struct(GPU_D12_UploadJobSig) { GPU_D12_Resource *resource; void *data; };
Struct(GPU_D12_WaitOnFenceJobSig) { ID3D12Fence *fence; u64 target; };
Struct(GPU_D12_ShaderDesc) Struct(GPU_D12_ShaderDesc)
{ {
String src; String src;
@ -281,14 +273,6 @@ Struct(GPU_D12_CompiledShaderResult)
b32 success; b32 success;
}; };
Struct(GPU_D12_CompileShaderJobSig)
{
Arena *arena;
GPU_D12_ShaderDesc *descs;
GPU_D12_CompiledShaderResult *results;
};
Struct(GPU_D12_RenderSig) Struct(GPU_D12_RenderSig)
{ {
Arena *arena; Arena *arena;
@ -360,7 +344,7 @@ Struct(GPU_D12_ResourceBarrierDesc)
}; };
/* ========================== * /* ========================== *
* Global state * Shared state
* ========================== */ * ========================== */
Struct(GPU_D12_SharedState) Struct(GPU_D12_SharedState)
@ -428,7 +412,7 @@ Struct(GPU_D12_SharedState)
GPU_D12_CommandQueue *command_queues[DX12_NUM_QUEUES]; GPU_D12_CommandQueue *command_queues[DX12_NUM_QUEUES];
/* Evictor job */ /* Evictor job */
P_Counter evictor_job_counter; Counter evictor_job_counter;
P_Cv evictor_wake_cv; P_Cv evictor_wake_cv;
P_Mutex evictor_wake_mutex; P_Mutex evictor_wake_mutex;
i64 evictor_wake_gen; i64 evictor_wake_gen;
@ -473,13 +457,13 @@ void GPU_D12_InitNoise(void);
* Shader compilation * Shader compilation
* ========================== */ * ========================== */
P_JobDef(GPU_D12_CompileShaderJob, job); JobDecl(GPU_D12_CompileShaderJob, { Arena *arena; GPU_D12_ShaderDesc *decs; GPU_D12_CompiledShaderResult results; });
/* ========================== * /* ========================== *
* Pipeline * Pipeline
* ========================== */ * ========================== */
P_JobDef(GPU_D12_AllocPipelineJob, job); JobDecl(GPU_D12_AllocPipelineJob, { GPU_D12_PipelineDesc *descs_in; GPU_D12_Pipeline **pipelines_out; });
void GPU_D12_ReleasePipelineNow(GPU_D12_Pipeline *pipeline); void GPU_D12_ReleasePipelineNow(GPU_D12_Pipeline *pipeline);
@ -538,7 +522,7 @@ void GPU_D12_InsertBarrier(ID3D12GraphicsCommandList *cl, i32 num_descs, GPU_D12
* Command queue * Command queue
* ========================== */ * ========================== */
P_JobDef(GPU_D12_AllocCommandQueueJob, job); JobDecl(GPU_D12_AllocCommandQueueJob, { GPU_D12_CommandQueueDesc *descs_in; GPU_D12_CommandQueue **cqs_out; });
void GPU_D12_ReleaseCommandQueue(GPU_D12_CommandQueue *cq); void GPU_D12_ReleaseCommandQueue(GPU_D12_CommandQueue *cq);
@ -572,13 +556,13 @@ GPU_D12_CommandBuffer *GPU_D12__PushCommandBuffer(GPU_D12_CommandList *cl, u64 d
* Wait job * Wait job
* ========================== */ * ========================== */
P_JobDef(GPU_D12_WaitOnFenceJob, job); JobDecl(GPU_D12_WaitOnFenceJob, { ID3D12Fence *fence; u64 target; });
/* ========================== * /* ========================== *
* Upload * Upload
* ========================== */ * ========================== */
P_JobDef(GPU_D12_UploadJob, job); JobDecl(GPU_D12_UploadJob, { GPU_D12_Resource *resource; void *data; });
/* ========================== * /* ========================== *
* Run utils * Run utils
@ -625,9 +609,8 @@ GPU_D12_SwapchainBuffer *GPU_D12_UpdateSwapchain(GPU_D12_Swapchain *swapchain, V
void GPU_D12_BlitToSwapchain(GPU_D12_SwapchainBuffer *dst, GPU_D12_Resource *src, Xform src_xf); void GPU_D12_BlitToSwapchain(GPU_D12_SwapchainBuffer *dst, GPU_D12_Resource *src, Xform src_xf);
/* ========================== * /* ========================== *
* Evictor job * Evictor job
* ========================== */ * ========================== */
P_JobDef(GPU_D12_EvictorJob, _); JobDecl(GPU_D12_EvictorJob, EmptySig);

View File

@ -520,7 +520,7 @@ void N_Write(N_Host *host, N_ChannelId channel_id, String msg, N_WriteFlag flags
N_Cmd *cmd = N_PushCmd(host); N_Cmd *cmd = N_PushCmd(host);
cmd->kind = N_CmdKind_Write; cmd->kind = N_CmdKind_Write;
cmd->channel_id = channel_id; cmd->channel_id = channel_id;
cmd->write_msg = CopyString(host->cmd_arena, msg); cmd->write_msg = PushString(host->cmd_arena, msg);
cmd->write_reliable = flags & N_WriteFlag_Reliable; cmd->write_reliable = flags & N_WriteFlag_Reliable;
} }
@ -561,7 +561,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host)
{ {
N_RcvPacket *packet = PushStruct(scratch.arena, N_RcvPacket); N_RcvPacket *packet = PushStruct(scratch.arena, N_RcvPacket);
packet->address = address; packet->address = address;
packet->data = CopyString(scratch.arena, data); packet->data = PushString(scratch.arena, data);
if (last_packet) if (last_packet)
{ {
last_packet->next = packet; last_packet->next = packet;

View File

@ -5,47 +5,6 @@ Struct(P_Watch);
Struct(P_Window); Struct(P_Window);
Struct(P_Sock); Struct(P_Sock);
////////////////////////////////
//~ Job queue types
/* Work pools contain their own worker threads with their own thread priority/affinity based on the intended context of the pool. */
typedef i32 P_Pool; enum
{
P_Pool_Inherit = -1,
/* The floating pool contains a large number of lower priority threads that have affinity over the entire CPU.
* Other pools should push jobs that only block and do no work here so that they can yield on the blocking job
* rather than blocking themselves. */
P_Pool_Floating = 0,
P_Pool_Background = 1,
P_Pool_Audio = 2,
P_Pool_User = 3,
P_Pool_Sim = 4,
P_Pool_Count
};
/* Job execution order within a pool is based on priority. */
typedef i32 P_Priority; enum
{
P_Priority_Inherit = -1,
P_Priority_High = 0,
P_Priority_Normal = 1,
P_Priority_Low = 2,
P_Priority_Count
};
Struct(P_JobData)
{
i32 id;
void *sig;
};
#define P_JobDef(job_name, arg_name) void job_name(P_JobData arg_name)
typedef P_JobDef(P_JobFunc, job_data);
//////////////////////////////// ////////////////////////////////
//~ Time types //~ Time types
@ -349,25 +308,13 @@ typedef i32 P_MessageBoxKind; enum
typedef P_ExitFuncDef(P_ExitFunc); typedef P_ExitFuncDef(P_ExitFunc);
//////////////////////////////// ////////////////////////////////
//~ Wait //~ @hookdecl Time helper operations
/* Futex-like wait & wake */
void P_Wait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns);
void P_Wake(void *addr, i32 count);
////////////////////////////////
//~ Job helpers
void P_Run(i32 count, P_JobFunc *func, void *sig, P_Pool pool_kind, P_Priority priority, P_Counter *counter);
////////////////////////////////
//~ Time helpers
P_DateTime P_LocalTime(void); P_DateTime P_LocalTime(void);
i64 P_TimeNs(void); i64 P_TimeNs(void);
//////////////////////////////// ////////////////////////////////
//~ File system operations //~ @hookdecl File system operations
/* NOTE: File paths use forward slash '/' as delimiter */ /* NOTE: File paths use forward slash '/' as delimiter */
@ -384,7 +331,7 @@ P_File P_OpenFileWrite(String path);
P_File P_OpenFileAppend(String path); P_File P_OpenFileAppend(String path);
void P_CloseFIle(P_File file); void P_CloseFIle(P_File file);
//- File data operations //- File data manipulation
String P_ReadFile(Arena *arena, P_File file); String P_ReadFile(Arena *arena, P_File file);
void P_WriteFile(P_File file, String data); void P_WriteFile(P_File file, String data);
@ -393,16 +340,15 @@ u64 P_GetFileSize(P_File file);
P_FileTime P_GetFileTime(P_File file); P_FileTime P_GetFileTime(P_File file);
//////////////////////////////// ////////////////////////////////
//~ File map operations //~ @hookdecl File map operations
P_FileMap P_OpenFileMap(P_File file); P_FileMap P_OpenFileMap(P_File file);
void P_CloseFileMap(P_FileMap map); void P_CloseFileMap(P_FileMap map);
String P_GetFileMapData(P_FileMap map); String P_GetFileMapData(P_FileMap map);
//////////////////////////////// ////////////////////////////////
//~ Watch operations //~ @hookdecl Watch operations
// A watch object allows the caller to watch for changes in a directory
/* A watch object allows the caller to watch for changes in a directory */
P_Watch *P_AllocWatch(String path); P_Watch *P_AllocWatch(String path);
void P_ReleaseWatch(P_Watch *dw); void P_ReleaseWatch(P_Watch *dw);
@ -410,15 +356,15 @@ P_WatchInfoList P_ReadWatchWait(Arena *arena, P_Watch *dw);
void P_WakeWatch(P_Watch *dw); void P_WakeWatch(P_Watch *dw);
//////////////////////////////// ////////////////////////////////
//~ Window operations //~ @hookdecl Window operations
P_Window *P_AllocWindow(void); P_Window *P_AllocWindow(void);
void P_ReleaseWindow(P_Window *window); void P_ReleaseWindow(P_Window *window);
//- Window events //- Events
P_WindowEventArray P_PopWindowEvents(Arena *arena, P_Window *window); P_WindowEventArray P_PopWindowEvents(Arena *arena, P_Window *window);
//- Window settings //- Settings
void P_UpdateWindowSettings(P_Window *window, P_WindowSettings *settings); void P_UpdateWindowSettings(P_Window *window, P_WindowSettings *settings);
P_WindowSettings P_GetWindowSettings(P_Window *window); P_WindowSettings P_GetWindowSettings(P_Window *window);
void P_ShowWindow(P_Window *window); void P_ShowWindow(P_Window *window);
@ -429,13 +375,13 @@ void P_EnableWindoweCursorClip(P_Window *window, Rect bounds);
void P_DisableWindoweCursorClip(P_Window *window); void P_DisableWindoweCursorClip(P_Window *window);
void P_ToggleWindowTopmost(P_Window *window); void P_ToggleWindowTopmost(P_Window *window);
//- Window info //- Info
Vec2 P_GetWindowSize(P_Window *window); Vec2 P_GetWindowSize(P_Window *window);
Vec2 P_GetWindowMonitorSize(P_Window *window); Vec2 P_GetWindowMonitorSize(P_Window *window);
u64 P_GetInternalWindowHandle(P_Window *window); u64 P_GetInternalWindowHandle(P_Window *window);
//////////////////////////////// ////////////////////////////////
//~ Address helpers //~ @hookdecl Address helpers
P_Address P_AddressFromString(String str); P_Address P_AddressFromString(String str);
P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr); P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr);
@ -444,7 +390,7 @@ String P_StringFromAddress(Arena *arena, P_Address address);
b32 P_AddressIsEqual(P_Address a, P_Address b); b32 P_AddressIsEqual(P_Address a, P_Address b);
//////////////////////////////// ////////////////////////////////
//~ Sock operations //~ @hookdecl Sock operations
P_Sock *P_AllocSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size); P_Sock *P_AllocSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
void P_ReleaseSock(P_Sock *sock); void P_ReleaseSock(P_Sock *sock);
@ -452,7 +398,7 @@ P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock);
void P_WriteSock(P_Sock *sock, P_Address address, String data); void P_WriteSock(P_Sock *sock, P_Address address, String data);
//////////////////////////////// ////////////////////////////////
//~ Utils //~ @hookdecl Utils
void P_MessageBox(P_MessageBoxKind kind, String message); void P_MessageBox(P_MessageBoxKind kind, String message);
void P_SetClipboardText(String str); void P_SetClipboardText(String str);
@ -462,20 +408,19 @@ u32 P_GetThreadId(void);
i64 P_GetCurrentSchedulerPeriodNs(void); i64 P_GetCurrentSchedulerPeriodNs(void);
//////////////////////////////// ////////////////////////////////
//~ Sleep //~ @hookdecl Sleep
void P_SleepPrecise(i64 sleep_time_ns); void P_SleepPrecise(i64 sleep_time_ns);
void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns); void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns);
//////////////////////////////// ////////////////////////////////
//~ Program exit //~ @hookdecl Program exit
void P_OnExit(P_ExitFunc *func); /* Registers a function to be called during graceful shutdown (in reverse order) */ void P_OnExit(P_ExitFunc *func);
void P_Exit(void); /* Signals the program to shut down gracefully and run exit callbacks */ void P_Exit(void);
void P_Panic(String msg); /* Forcefully exits the program and displays `msg` to the user */ void P_Panic(String msg);
//////////////////////////////// ////////////////////////////////
//~ Entry point //~ @hookdecl Entry point (implemented per application)
/* Must be defined by app */
void P_AppStartup(String args_str); void P_AppStartup(String args_str);

View File

@ -1,7 +1,7 @@
//////////////////////////////// ////////////////////////////////
//~ Global state //~ Shared state
P_SharedLogCtx P_shared_log_ctx = ZI; P_SharedLogState P_shared_log_state = ZI;
//////////////////////////////// ////////////////////////////////
//~ Startup //~ Startup
@ -9,7 +9,7 @@ P_SharedLogCtx P_shared_log_ctx = ZI;
void P_LogStartup(String logfile_path) void P_LogStartup(String logfile_path)
{ {
__prof; __prof;
P_SharedLogCtx *ctx = &P_shared_log_ctx; P_SharedLogState *ctx = &P_shared_log_state;
ctx->callbacks_arena = AllocArena(Mebi(8)); ctx->callbacks_arena = AllocArena(Mebi(8));
if (logfile_path.len > 0) if (logfile_path.len > 0)
{ {
@ -30,7 +30,7 @@ void P_LogStartup(String logfile_path)
void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level) void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level)
{ {
P_SharedLogCtx *ctx = &P_shared_log_ctx; P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; } if (!Atomic32Fetch(&ctx->initialized)) { return; }
P_Lock lock = P_LockE(&ctx->callbacks_mutex); P_Lock lock = P_LockE(&ctx->callbacks_mutex);
{ {
@ -56,7 +56,7 @@ void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level)
void P_LogAppend_(String msg) void P_LogAppend_(String msg)
{ {
__prof; __prof;
P_SharedLogCtx *ctx = &P_shared_log_ctx; P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; } if (!Atomic32Fetch(&ctx->initialized)) { return; }
if (ctx->file_valid) if (ctx->file_valid)
@ -75,7 +75,7 @@ void P_LogAppend_(String msg)
* writing to log file. */ * writing to log file. */
void P_LogPanic_(String msg) void P_LogPanic_(String msg)
{ {
P_SharedLogCtx *ctx = &P_shared_log_ctx; P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; } if (!Atomic32Fetch(&ctx->initialized)) { return; }
if (ctx->file_valid) if (ctx->file_valid)
@ -95,7 +95,7 @@ void P_LogFV_(i32 level, String file, u32 line, String fmt, va_list args)
void P_LogFV_(i32 level, String fmt, va_list args) void P_LogFV_(i32 level, String fmt, va_list args)
#endif #endif
{ {
P_SharedLogCtx *ctx = &P_shared_log_ctx; P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; } if (!Atomic32Fetch(&ctx->initialized)) { return; }
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
String msg = StringFormatV(scratch.arena, fmt, args); String msg = StringFormatV(scratch.arena, fmt, args);
@ -116,7 +116,7 @@ void P_LogF_(i32 level, String file, u32 line, String fmt, ...)
void P_LogF_(i32 level, String fmt, ...) void P_LogF_(i32 level, String fmt, ...)
#endif #endif
{ {
P_SharedLogCtx *ctx = &P_shared_log_ctx; P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; } if (!Atomic32Fetch(&ctx->initialized)) { return; }
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -138,7 +138,7 @@ void P_Log_(i32 level, String msg)
#endif #endif
{ {
__prof; __prof;
P_SharedLogCtx *ctx = &P_shared_log_ctx; P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; } if (!Atomic32Fetch(&ctx->initialized)) { return; }
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();

View File

@ -59,7 +59,7 @@ Struct(LogEventCallback)
//~ Shared state //~ Shared state
//- Shared context //- Shared context
Struct(P_SharedLogCtx) Struct(P_SharedLogState)
{ {
Atomic32 initialized; Atomic32 initialized;
@ -72,7 +72,7 @@ Struct(P_SharedLogCtx)
b32 file_valid; b32 file_valid;
}; };
extern P_SharedLogCtx P_shared_log_ctx; extern P_SharedLogState P_shared_log_state;
//-- Log level settings //-- Log level settings
Struct(P_LogLevelSettings) Struct(P_LogLevelSettings)

View File

@ -45,7 +45,7 @@ P_Lock P_LockSpinE(P_Mutex *m, i32 spin)
{ {
if (spin_cnt < spin) if (spin_cnt < spin)
{ {
IxPause(); _mm_pause();
} }
else else
{ {
@ -92,7 +92,7 @@ P_Lock P_LockSpinS(P_Mutex *m, i32 spin)
{ {
if (spin_cnt < spin) if (spin_cnt < spin)
{ {
IxPause(); _mm_pause();
} }
else else
{ {
@ -173,7 +173,7 @@ void P_SignalCv(P_Cv *cv, i32 count)
//////////////////////////////// ////////////////////////////////
//~ Counter //~ Counter
void P_CounterAdd(P_Counter *counter, i64 x) void P_CounterAdd(Counter *counter, i64 x)
{ {
i64 old_v = Atomic64FetchAdd(&counter->v, x); i64 old_v = Atomic64FetchAdd(&counter->v, x);
i64 new_v = old_v + x; i64 new_v = old_v + x;
@ -183,7 +183,7 @@ void P_CounterAdd(P_Counter *counter, i64 x)
} }
} }
void P_WaitOnCounter(P_Counter *counter) void P_WaitOnCounter(Counter *counter)
{ {
i64 v = Atomic64Fetch(&counter->v); i64 v = Atomic64Fetch(&counter->v);
while (v > 0) while (v > 0)

View File

@ -41,13 +41,13 @@ StaticAssert(alignof(P_Cv) == 64); /* Prevent false sharing */
//////////////////////////////// ////////////////////////////////
//~ Counter types //~ Counter types
AlignedStruct(P_Counter, 64) AlignedStruct(Counter, 64)
{ {
Atomic64 v; Atomic64 v;
u8 _pad[56]; u8 _pad[56];
}; };
StaticAssert(sizeof(P_Counter) == 64); /* Padding validation */ StaticAssert(sizeof(Counter) == 64); /* Padding validation */
StaticAssert(alignof(P_Counter) == 64); /* Prevent false sharing */ StaticAssert(alignof(Counter) == 64); /* Prevent false sharing */
//////////////////////////////// ////////////////////////////////
//~ Mutex operations //~ Mutex operations
@ -79,5 +79,5 @@ void P_SignalCv(P_Cv *cv, i32 count);
//////////////////////////////// ////////////////////////////////
//~ Counter operations //~ Counter operations
void P_CounterAdd(P_Counter *counter, i64 x); void P_CounterAdd(Counter *counter, i64 x);
void P_WaitOnCounter(P_Counter *counter); void P_WaitOnCounter(Counter *counter);

File diff suppressed because it is too large Load Diff

View File

@ -17,198 +17,6 @@
# include <shellapi.h> # include <shellapi.h>
#pragma warning(pop) #pragma warning(pop)
////////////////////////////////
//~ Ticket mutex types
Struct(P_W32_TicketMutex)
{
Atomic64Padded ticket;
Atomic64Padded serving;
};
////////////////////////////////
//~ Thread types
#define P_W32_ThreadStackSize Kibi(64)
#define P_W32_ThreadDef(name, arg_name) void name(void *arg_name)
typedef P_W32_ThreadDef(P_W32_ThreadFunc, data);
Struct(P_W32_Thread)
{
P_W32_ThreadFunc *entry_point;
void *thread_data;
char thread_name_cstr[256];
wchar_t thread_name_wstr[256];
i32 profiler_group;
P_W32_Thread *next;
P_W32_Thread *prev;
HANDLE handle;
};
////////////////////////////////
//~ Wait list types
AlignedStruct(P_W32_WaitList, 64)
{
u64 value;
i16 first_waiter;
i16 last_waiter;
i32 num_waiters;
P_W32_WaitList *next_in_bin;
P_W32_WaitList *prev_in_bin;
};
StaticAssert(alignof(P_W32_WaitList) == 64); /* Avoid false sharing */
AlignedStruct(P_W32_WaitBin, 64)
{
P_W32_WaitList *first_wait_list;
P_W32_WaitList *last_wait_list;
P_W32_WaitList *first_free_wait_list;
P_W32_TicketMutex lock;
};
StaticAssert(alignof(P_W32_WaitBin) == 64); /* Avoid false sharing */
////////////////////////////////
//~ Fiber types
#define P_W32_FiberStackSize Mebi(4)
#define P_W32_FiberNamePrefixCstr "Fiber ["
#define P_W32_FiberNameSuffixCstr "]"
#define P_W32_FiberNameMaxSize 64
//- Yield param
typedef i32 P_W32_YieldKind; enum
{
P_W32_YieldKind_None,
P_W32_YieldKind_Done,
P_W32_YieldKind_Wait,
P_W32_YieldKind_Count
};
Struct(P_W32_YieldParam)
{
P_W32_YieldKind kind;
union
{
struct
{
volatile void *addr;
void *cmp;
u32 size;
i64 timeout_ns;
} wait;
};
};
//- Fiber
AlignedStruct(P_W32_Fiber, 64)
{
/* ---------------------------------------------------- */
void *addr; /* 08 bytes */
/* ---------------------------------------------------- */
char *name_cstr; /* 08 bytes */
/* ---------------------------------------------------- */
Atomic32 wake_lock; /* 04 bytes (4 byte alignment) */
i16 id; /* 02 bytes */
i16 parent_id; /* 02 bytes */
/* ---------------------------------------------------- */
u64 wait_addr; /* 08 bytes */
/* ---------------------------------------------------- */
u64 wait_time; /* 08 bytes */
/* ---------------------------------------------------- */
i16 next_addr_waiter; /* 02 bytes */
i16 prev_addr_waiter; /* 02 bytes */
i16 next_time_waiter; /* 02 bytes */
i16 prev_time_waiter; /* 02 bytes */
/* ---------------------------------------------------- */
u8 _pad1[8]; /* 08 bytes (padding) */
/* ---------------------------------------------------- */
u8 _pad2[8]; /* 08 bytes (padding) */
/* ---------------------------------------------------- */
/* -------------------- Cache line -------------------- */
/* ---------------------------------------------------- */
P_JobFunc *job_func; /* 08 bytes */
/* ---------------------------------------------------- */
void *job_sig; /* 08 bytes */
/* ---------------------------------------------------- */
i32 job_id; /* 04 bytes */
i16 job_pool; /* 02 bytes */
i16 job_priority; /* 02 bytes */
/* ---------------------------------------------------- */
P_Counter *job_counter; /* 08 bytes */
/* ---------------------------------------------------- */
P_W32_YieldParam *yield_param; /* 08 bytes */
/* ---------------------------------------------------- */
u8 _pad3[24]; /* 24 bytes (padding) */
};
StaticAssert(sizeof(P_W32_Fiber) == 128); /* Padding validation (increase if necessary) */
StaticAssert(alignof(P_W32_Fiber) == 64); /* Avoid false sharing */
StaticAssert(offsetof(P_W32_Fiber, wake_lock) % 4 == 0); /* Atomic must be aligned */
////////////////////////////////
//~ Job queue types
//- Worker ctx
AlignedStruct(P_W32_WorkerCtx, 64)
{
P_Pool pool_kind;
i32 id;
};
//- Job info
Struct(P_W32_JobInfo)
{
i32 num_dispatched;
i32 count;
P_JobFunc *func;
void *sig;
P_Counter *counter;
i16 fiber_id; /* If the job is being resumed from a yield */
P_W32_JobInfo *next;
};
//- Job queue
AlignedStruct(P_W32_JobQueue, 64)
{
P_W32_TicketMutex lock;
Arena *arena;
P_W32_JobInfo *first;
P_W32_JobInfo *last;
P_W32_JobInfo *first_free;
};
//- Job pool
AlignedStruct(P_W32_JobPool, 64)
{
/* Jobs */
P_W32_JobQueue job_queues[P_Priority_Count];
P_W32_TicketMutex free_fibers_lock;
i16 first_free_fiber_id;
/* Workers */
Atomic32Padded workers_shutdown;
Atomic64Padded num_jobs_in_queue;
P_W32_TicketMutex workers_wake_lock;
i32 num_worker_threads;
i32 thread_priority;
u64 thread_affinity_mask;
b32 thread_is_audio;
Arena *worker_threads_arena;
P_W32_Thread **worker_threads;
P_W32_WorkerCtx *worker_contexts;
};
//////////////////////////////// ////////////////////////////////
//~ Window types //~ Window types
@ -227,7 +35,7 @@ Struct(P_W32_Window)
u32 flags; u32 flags;
HWND hwnd; HWND hwnd;
P_Counter ready_fence; Counter ready_fence;
u16 utf16_high_surrogate_last_input; u16 utf16_high_surrogate_last_input;
@ -253,7 +61,7 @@ Struct(P_W32_Window)
i32 current_event_arena_index; i32 current_event_arena_index;
Arena *event_arenas[2]; Arena *event_arenas[2];
P_W32_Thread *window_thread; W32_Thread *window_thread;
Atomic32 shutdown; Atomic32 shutdown;
P_W32_Window *next_free; P_W32_Window *next_free;
@ -300,18 +108,8 @@ Struct(P_W32_Sock)
#define P_W32_WindowClassName L"power_play_window_class" #define P_W32_WindowClassName L"power_play_window_class"
/* Assume scheduler cycle is 20hz at start to be conservative */
#define P_W32_DefaultSchedulerPeriodNs 50000000
#define P_W32_NumRollingSchedulerPeriods 1000
#define P_W32_NumWaitAddrBins 16384
#define P_W32_NumWaitTimeBins 1024
#define P_W32_MaxOnExitFuncs 1024 #define P_W32_MaxOnExitFuncs 1024
/* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */
#define P_W32_WakeAllThreshold 16
Struct(P_W32_SharedCtx) Struct(P_W32_SharedCtx)
{ {
SYSTEM_INFO info; SYSTEM_INFO info;
@ -333,13 +131,6 @@ Struct(P_W32_SharedCtx)
//- Key lookup table //- Key lookup table
P_Btn vk_btn_table[256]; P_Btn vk_btn_table[256];
//- Worker thread pool
P_Mutex threads_mutex;
Arena *threads_arena;
P_W32_Thread *first_thread;
P_W32_Thread *last_thread;
P_W32_Thread *first_free_thread;
//- Watches pool //- Watches pool
P_Mutex watches_mutex; P_Mutex watches_mutex;
Arena *watches_arena; Arena *watches_arena;
@ -360,69 +151,10 @@ Struct(P_W32_SharedCtx)
//- Exit funcs //- Exit funcs
Atomic32 num_exit_funcs; Atomic32 num_exit_funcs;
P_ExitFunc *exit_funcs[P_W32_MaxOnExitFuncs]; P_ExitFunc *exit_funcs[P_W32_MaxOnExitFuncs];
//- Scheduler
Atomic64Padded current_scheduler_cycle;
Atomic64Padded current_scheduler_cycle_period_ns;
//- Fibers
P_W32_TicketMutex fibers_lock;
i16 num_fibers;
Arena *fiber_names_arena;
P_W32_Fiber fibers[MaxFibers];
//- Wait lists
Atomic64Padded waiter_wake_gen;
P_W32_TicketMutex wait_lists_arena_lock;
Arena *wait_lists_arena;
//- Wait tables
P_W32_WaitBin wait_addr_bins[P_W32_NumWaitAddrBins];
P_W32_WaitBin wait_time_bins[P_W32_NumWaitTimeBins];
//- Job pools
P_W32_JobPool job_pools[P_Pool_Count];
}; };
extern P_W32_SharedCtx P_W32_shared_ctx; extern P_W32_SharedCtx P_W32_shared_ctx;
////////////////////////////////
//~ Ticket mutex operations
void P_W32_LockTicketMutex(P_W32_TicketMutex *tm);
void P_W32_UnlockTicketMutex(P_W32_TicketMutex *tm);
////////////////////////////////
//~ Thread operations
DWORD WINAPI P_W32_Win32ThreadProc(LPVOID vt);
P_W32_Thread *P_W32_AllocThread(P_W32_ThreadFunc *entry_point, void *thread_data, String thread_name, i32 profiler_group);
b32 P_W32_TryReleaseThread(P_W32_Thread *thread, f32 timeout_seconds);
void P_W32_WaitReleaseThread(P_W32_Thread *thread);
////////////////////////////////
//~ Wait list operations
void P_W32_WakeLockedFibers(i32 num_fibers, P_W32_Fiber **fibers);
void P_W32_WakeByAddress(void *addr, i32 count);
void P_W32_WakeByTime(u64 time);
////////////////////////////////
//~ Fiber operations
P_W32_Fiber *P_W32_AllocFiber(P_W32_JobPool *pool);
void P_W32_ReleaseFiber(P_W32_JobPool *pool, P_W32_Fiber *fiber);
ForceInline P_W32_Fiber *P_W32_FiberFromId(i16 id);
ForceNoInline void P_W32_FiberResume(P_W32_Fiber *fiber);
void P_W32_YieldFiber(P_W32_Fiber *fiber, P_W32_Fiber *parent_fiber);
void P_W32_FiberEntryPoint(void *id_ptr);
////////////////////////////////
//~ Workers
P_W32_ThreadDef(P_W32_JobWorkerEntryFunc, worker_ctx_arg);
P_W32_ThreadDef(P_W32_JobSchedulerEntryFunc, _);
//////////////////////////////// ////////////////////////////////
//~ Time operations //~ Time operations
@ -445,7 +177,7 @@ void P_W32_UpdateWindowFromSystem(P_W32_Window *window);
void P_W32_UpdateWindowFromSettings(P_W32_Window *window, P_WindowSettings *settings); void P_W32_UpdateWindowFromSettings(P_W32_Window *window, P_WindowSettings *settings);
//- Window thread //- Window thread
P_W32_ThreadDef(P_W32_WindowThreadEntryFunc, arg); W32_ThreadDef(P_W32_WindowThreadEntryFunc, arg);
void P_W32_ProcessWindowEvent(P_W32_Window *window, P_WindowEvent event); void P_W32_ProcessWindowEvent(P_W32_Window *window, P_WindowEvent event);
void P_W32_WakeWindow(P_W32_Window *window); void P_W32_WakeWindow(P_W32_Window *window);
LRESULT CALLBACK P_W32_Win32WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); LRESULT CALLBACK P_W32_Win32WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
@ -461,5 +193,5 @@ P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr);
//~ Entry point //~ Entry point
void P_W32_InitBtnTable(void); void P_W32_InitBtnTable(void);
P_JobDef(P_W32_AppStartupJob, _); JobDecl(P_W32_AppStartupJob, EmptySig);
P_JobDef(P_W32_AppShutdownJob, _); JobDecl(P_W32_AppShutdownJob, EmptySig);

View File

@ -16,7 +16,7 @@ PB_StartupReceipt PB_Startup(MIX_StartupReceipt *mixer_sr)
LAX mixer_sr; LAX mixer_sr;
PB_WSP_InitializeWasapi(); PB_WSP_InitializeWasapi();
/* Start playback job */ /* Start playback job */
P_Run(1, PB_WSP_PlaybackJob, 0, P_Pool_Audio, P_Priority_High, &g->PB_WSP_PlaybackJob_counter); P_Run(1, PB_WSP_PlaybackJob, 0, PoolKind_Audio, PriorityKind_High, &g->PB_WSP_PlaybackJob_counter);
P_OnExit(&PB_WSP_Shutdown); P_OnExit(&PB_WSP_Shutdown);
return (PB_StartupReceipt) { 0 }; return (PB_StartupReceipt) { 0 };
@ -184,7 +184,7 @@ void PB_WSP_EndUpdate(PB_WSP_Buff *wspbuf, MIX_PcmF32 src)
//////////////////////////////// ////////////////////////////////
//~ Playback job //~ Playback job
P_JobDef(PB_WSP_PlaybackJob, _) JobDef(PB_WSP_PlaybackJob, _)
{ {
__prof; __prof;
PB_WSP_SharedState *g = &PB_WSP_shared_state; PB_WSP_SharedState *g = &PB_WSP_shared_state;

View File

@ -39,7 +39,7 @@ Struct(PB_WSP_SharedState)
IAudioRenderClient *playback; IAudioRenderClient *playback;
WAVEFORMATEX *buffer_format; WAVEFORMATEX *buffer_format;
u32 buffer_frames; u32 buffer_frames;
P_Counter PB_WSP_PlaybackJob_counter; Counter PB_WSP_PlaybackJob_counter;
}; };
extern PB_WSP_SharedState PB_WSP_shared_state; extern PB_WSP_SharedState PB_WSP_shared_state;
@ -49,8 +49,6 @@ extern PB_WSP_SharedState PB_WSP_shared_state;
void PB_WSP_InitializeWasapi(void); void PB_WSP_InitializeWasapi(void);
P_ExitFuncDef(PB_WSP_Shutdown); P_ExitFuncDef(PB_WSP_Shutdown);
P_JobDef(PB_WSP_PlaybackJob, _);
P_ExitFuncDef(PB_WSP_Shutdown);
//////////////////////////////// ////////////////////////////////
//~ Playback update //~ Playback update
@ -61,4 +59,4 @@ void PB_WSP_EndUpdate(PB_WSP_Buff *wspbuf, MIX_PcmF32 src);
//////////////////////////////// ////////////////////////////////
//~ Playback job //~ Playback job
P_JobDef(PB_WSP_PlaybackJob, _); JobDecl(PB_WSP_PlaybackJob, EmptySig);

View File

@ -3,11 +3,9 @@ SharedUserState shared_user_state = ZI;
//////////////////////////////// ////////////////////////////////
//~ Startup //~ Startup
UserStartupReceipt StartupUser(F_StartupReceipt *font_sr, UserStartupReceipt StartupUser(S_StartupReceipt *sprite_sr,
S_StartupReceipt *sprite_sr,
D_StartupReceipt *draw_sr, D_StartupReceipt *draw_sr,
AC_StartupReceipt *asset_cache_sr, AC_StartupReceipt *asset_cache_sr,
SND_StartupReceipt *sound_sr,
MIX_StartupReceipt *mixer_sr, MIX_StartupReceipt *mixer_sr,
SimStartupReceipt *sim_sr, SimStartupReceipt *sim_sr,
String connect_address_str) String connect_address_str)
@ -28,7 +26,7 @@ UserStartupReceipt StartupUser(F_StartupReceipt *font_sr,
g->real_time_ns = P_TimeNs(); g->real_time_ns = P_TimeNs();
/* TODO: Remove this */ /* TODO: Remove this */
g->connect_address_str = CopyString(g->arena, connect_address_str); g->connect_address_str = PushString(g->arena, connect_address_str);
/* Initialize average dt to a reasonable value */ /* Initialize average dt to a reasonable value */
g->average_local_to_user_snapshot_publish_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND; g->average_local_to_user_snapshot_publish_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND;
@ -57,8 +55,8 @@ UserStartupReceipt StartupUser(F_StartupReceipt *font_sr,
P_ShowWindow(g->window); P_ShowWindow(g->window);
/* Start jobs */ /* Start jobs */
P_Run(1, UpdateUserJob, 0, P_Pool_User, P_Priority_High, &g->shutdown_job_counters); P_Run(1, UpdateUserJob, 0, PoolKind_User, PriorityKind_High, &g->shutdown_job_counters);
P_Run(1, SimJob, 0, P_Pool_Sim, P_Priority_High, &g->shutdown_job_counters); P_Run(1, SimJob, 0, PoolKind_Sim, PriorityKind_High, &g->shutdown_job_counters);
P_OnExit(&ShutdownUser); P_OnExit(&ShutdownUser);
return (UserStartupReceipt) { 0 }; return (UserStartupReceipt) { 0 };
@ -124,7 +122,7 @@ void DrawDebugMovement(Entity *ent)
} }
} }
//- Debug string //- Entity debug string
String DebugStringFromEntity(Arena *arena, Entity *ent) String DebugStringFromEntity(Arena *arena, Entity *ent)
{ {
TempArena scratch = BeginScratch(arena); TempArena scratch = BeginScratch(arena);
@ -141,29 +139,29 @@ String DebugStringFromEntity(Arena *arena, Entity *ent)
b32 receiving = sim_ent_has_prop(ent, SEPROP_SYNC_DST); b32 receiving = sim_ent_has_prop(ent, SEPROP_SYNC_DST);
if (transmitting & receiving) if (transmitting & receiving)
{ {
result.len += CopyString(arena, Lit(" networked (sending & receiving)")).len; result.len += PushString(arena, Lit(" networked (sending & receiving)")).len;
} }
else if (transmitting) else if (transmitting)
{ {
result.len += CopyString(arena, Lit(" networked (sending)")).len; result.len += PushString(arena, Lit(" networked (sending)")).len;
} }
else if (receiving) else if (receiving)
{ {
result.len += CopyString(arena, Lit(" networked (receiving)")).len; result.len += PushString(arena, Lit(" networked (receiving)")).len;
} }
else else
{ {
result.len += CopyString(arena, Lit(" local")).len; result.len += PushString(arena, Lit(" local")).len;
} }
} }
result.len += CopyString(arena, Lit("\n")).len; result.len += PushString(arena, Lit("\n")).len;
result.len += StringFormat(arena, Lit("owner: [%F]\n"), FmtUid(ent->owner.uid)).len; result.len += StringFormat(arena, Lit("owner: [%F]\n"), FmtUid(ent->owner.uid)).len;
result.len += CopyString(arena, Lit("\n")).len; result.len += PushString(arena, Lit("\n")).len;
{ {
result.len += CopyString(arena, Lit("props: 0x")).len; result.len += PushString(arena, Lit("props: 0x")).len;
for (u64 chunk_index = countof(ent->props); chunk_index-- > 0;) for (u64 chunk_index = countof(ent->props); chunk_index-- > 0;)
{ {
u64 chunk = ent->props[chunk_index]; u64 chunk = ent->props[chunk_index];
@ -178,7 +176,7 @@ String DebugStringFromEntity(Arena *arena, Entity *ent)
} }
} }
} }
result.len += CopyString(arena, Lit("\n")).len; result.len += PushString(arena, Lit("\n")).len;
} }
if (!sim_ent_id_eq(ent->parent, SIM_ENT_ROOT_ID)) if (!sim_ent_id_eq(ent->parent, SIM_ENT_ROOT_ID))
@ -192,7 +190,7 @@ String DebugStringFromEntity(Arena *arena, Entity *ent)
result.len += StringFormat(arena, Lit("next: [%F]\n"), FmtUid(ent->next.uid)).len; result.len += StringFormat(arena, Lit("next: [%F]\n"), FmtUid(ent->next.uid)).len;
} }
result.len += CopyString(arena, Lit("\n")).len; result.len += PushString(arena, Lit("\n")).len;
/* Pos */ /* Pos */
Xform xf = sim_ent_get_xform(ent); Xform xf = sim_ent_get_xform(ent);
@ -216,8 +214,8 @@ String DebugStringFromEntity(Arena *arena, Entity *ent)
} }
while (child->valid) while (child->valid)
{ {
result.len += CopyString(arena, Lit("\n---------------------------------\n")).len; result.len += PushString(arena, Lit("\n---------------------------------\n")).len;
result.len += CopyString(arena, Lit("CHILD\n")).len; result.len += PushString(arena, Lit("CHILD\n")).len;
String child_text = DebugStringFromEntity(scratch.arena, child); String child_text = DebugStringFromEntity(scratch.arena, child);
result.len += IndentString(arena, child_text, 4).len; result.len += IndentString(arena, child_text, 4).len;
child = sim_ent_from_id(ss, child->next); child = sim_ent_from_id(ss, child->next);
@ -240,7 +238,7 @@ P_LogEventCallbackFuncDef(ConsoleLogCallback, log)
{ {
ConsoleLog *clog = PushStruct(g->console_logs_arena, ConsoleLog); ConsoleLog *clog = PushStruct(g->console_logs_arena, ConsoleLog);
clog->level = log.level; clog->level = log.level;
clog->msg = CopyString(g->console_logs_arena, log.msg); clog->msg = PushString(g->console_logs_arena, log.msg);
clog->datetime = log.datetime; clog->datetime = log.datetime;
clog->time_ns = log.time_ns; clog->time_ns = log.time_ns;
@ -1922,94 +1920,94 @@ void UpdateUser(P_Window *window)
text.text = PushDry(temp.arena, u8); text.text = PushDry(temp.arena, u8);
#if BITBUFF_DEBUG #if BITBUFF_DEBUG
text.len += CopyString(temp.arena, Lit("(bitbuff debug enabled)")).len; text.len += PushString(temp.arena, Lit("(bitbuff debug enabled)")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
#endif #endif
text.len += StringFormat(temp.arena, Lit("blended world entities: %F/%F"), FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved)).len; text.len += StringFormat(temp.arena, Lit("blended world entities: %F/%F"), FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("blended world tick: %F"), FmtUint(g->ss_blended->tick)).len; text.len += StringFormat(temp.arena, Lit("blended world tick: %F"), FmtUint(g->ss_blended->tick)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("blended world time: %F"), FmtFloat(SecondsFromNs(g->ss_blended->sim_time_ns))).len; text.len += StringFormat(temp.arena, Lit("blended world time: %F"), FmtFloat(SecondsFromNs(g->ss_blended->sim_time_ns))).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("average local sim publish dt: %F"), FmtFloat(SecondsFromNs(g->average_local_to_user_snapshot_publish_dt_ns))).len; text.len += StringFormat(temp.arena, Lit("average local sim publish dt: %F"), FmtFloat(SecondsFromNs(g->average_local_to_user_snapshot_publish_dt_ns))).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("local sim last known tick: %F"), FmtUint(g->local_sim_last_known_tick)).len; text.len += StringFormat(temp.arena, Lit("local sim last known tick: %F"), FmtUint(g->local_sim_last_known_tick)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("local sim last known time: %F"), FmtFloat(SecondsFromNs(g->local_sim_last_known_time_ns))).len; text.len += StringFormat(temp.arena, Lit("local sim last known time: %F"), FmtFloat(SecondsFromNs(g->local_sim_last_known_time_ns))).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("local sim predicted time: %F"), FmtFloat(SecondsFromNs(g->local_sim_predicted_time_ns))).len; text.len += StringFormat(temp.arena, Lit("local sim predicted time: %F"), FmtFloat(SecondsFromNs(g->local_sim_predicted_time_ns))).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("render time target: %F"), FmtFloat(SecondsFromNs(g->render_time_target_ns))).len; text.len += StringFormat(temp.arena, Lit("render time target: %F"), FmtFloat(SecondsFromNs(g->render_time_target_ns))).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("render time: %F"), FmtFloat(SecondsFromNs(g->render_time_ns))).len; text.len += StringFormat(temp.arena, Lit("render time: %F"), FmtFloat(SecondsFromNs(g->render_time_ns))).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("local player: [%F]"), FmtUid(local_player->id.uid)).len; text.len += StringFormat(temp.arena, Lit("local player: [%F]"), FmtUid(local_player->id.uid)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
Vec2 world_cursor = g->world_cursor; Vec2 world_cursor = g->world_cursor;
text.len += StringFormat(temp.arena, Lit("cursor world: %F, %F"), FmtFloat(world_cursor.x), FmtFloat(world_cursor.y)).len; text.len += StringFormat(temp.arena, Lit("cursor world: %F, %F"), FmtFloat(world_cursor.x), FmtFloat(world_cursor.y)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
Vec2I32 world_tile_cursor = sim_world_tile_index_from_pos(world_cursor); Vec2I32 world_tile_cursor = sim_world_tile_index_from_pos(world_cursor);
text.len += StringFormat(temp.arena, Lit("cursor world tile: %F, %F"), FmtSint(world_tile_cursor.x), FmtSint(world_tile_cursor.y)).len; text.len += StringFormat(temp.arena, Lit("cursor world tile: %F, %F"), FmtSint(world_tile_cursor.x), FmtSint(world_tile_cursor.y)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
Vec2I32 local_tile_cursor = sim_local_tile_index_from_world_tile_index(world_tile_cursor); Vec2I32 local_tile_cursor = sim_local_tile_index_from_world_tile_index(world_tile_cursor);
text.len += StringFormat(temp.arena, Lit("cursor local tile: %F, %F"), FmtSint(local_tile_cursor.x), FmtSint(local_tile_cursor.y)).len; text.len += StringFormat(temp.arena, Lit("cursor local tile: %F, %F"), FmtSint(local_tile_cursor.x), FmtSint(local_tile_cursor.y)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
Vec2I32 tile_chunk_cursor = sim_tile_chunk_index_from_world_tile_index(world_tile_cursor); Vec2I32 tile_chunk_cursor = sim_tile_chunk_index_from_world_tile_index(world_tile_cursor);
text.len += StringFormat(temp.arena, Lit("cursor tile chunk: %F, %F"), FmtSint(tile_chunk_cursor.x), FmtSint(tile_chunk_cursor.y)).len; text.len += StringFormat(temp.arena, Lit("cursor tile chunk: %F, %F"), FmtSint(tile_chunk_cursor.x), FmtSint(tile_chunk_cursor.y)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Network read: %F mbit/s"), FmtFloat((f64)g->net_bytes_read.last_second * 8 / 1000 / 1000)).len; text.len += StringFormat(temp.arena, Lit("Network read: %F mbit/s"), FmtFloat((f64)g->net_bytes_read.last_second * 8 / 1000 / 1000)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Network write: %F mbit/s"), FmtFloat((f64)g->net_bytes_sent.last_second * 8 / 1000 / 1000)).len; text.len += StringFormat(temp.arena, Lit("Network write: %F mbit/s"), FmtFloat((f64)g->net_bytes_sent.last_second * 8 / 1000 / 1000)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Ping (real): %F ms"), FmtFloat(SecondsFromNs(local_player->player_last_rtt_ns) * 1000)).len; text.len += StringFormat(temp.arena, Lit("Ping (real): %F ms"), FmtFloat(SecondsFromNs(local_player->player_last_rtt_ns) * 1000)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Ping (average): %F ms"), FmtFloat(local_player->player_average_rtt_seconds * 1000)).len; text.len += StringFormat(temp.arena, Lit("Ping (average): %F ms"), FmtFloat(local_player->player_average_rtt_seconds * 1000)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Memory committed: %F MiB"), FmtFloat((f64)GetGstat(GSTAT_MEMORY_COMMITTED) / 1024 / 1024)).len; text.len += StringFormat(temp.arena, Lit("Memory committed: %F MiB"), FmtFloat((f64)GetGstat(GSTAT_MEMORY_COMMITTED) / 1024 / 1024)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Virtual memory reserved: %F TiB"), FmtFloat((f64)GetGstat(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024)).len; text.len += StringFormat(temp.arena, Lit("Virtual memory reserved: %F TiB"), FmtFloat((f64)GetGstat(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Arenas allocated: %F"), FmtUint(GetGstat(GSTAT_NUM_ARENAS))).len; text.len += StringFormat(temp.arena, Lit("Arenas allocated: %F"), FmtUint(GetGstat(GSTAT_NUM_ARENAS))).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Video memory (GPU): %F MiB"), FmtFloat((f64)vram.local_used / 1024 / 1024)).len; text.len += StringFormat(temp.arena, Lit("Video memory (GPU): %F MiB"), FmtFloat((f64)vram.local_used / 1024 / 1024)).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Video memory (shared): %F MiB"), FmtFloat((f64)vram.non_local_used / 1024 / 1024)).len; text.len += StringFormat(temp.arena, Lit("Video memory (shared): %F MiB"), FmtFloat((f64)vram.non_local_used / 1024 / 1024)).len;
//text.len += CopyString(temp.arena, Lit("\n")).len; //text.len += PushString(temp.arena, Lit("\n")).len;
//text.len += CopyString(temp.arena, Lit("\n")).len; //text.len += PushString(temp.arena, Lit("\n")).len;
#if RtcIsEnabled #if RtcIsEnabled
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += CopyString(temp.arena, Lit("\n")).len; text.len += PushString(temp.arena, Lit("\n")).len;
text.len += StringFormat(temp.arena, Lit("Debug steps: %F"), FmtUint(GetGstat(GSTAT_DEBUG_STEPS))).len; text.len += StringFormat(temp.arena, Lit("Debug steps: %F"), FmtUint(GetGstat(GSTAT_DEBUG_STEPS))).len;
//text.len += CopyString(temp.arena, Lit("\n")).len; //text.len += PushString(temp.arena, Lit("\n")).len;
#endif #endif
//draw_text(g->render_sig, font, pos, StringFormat(temp.arena, Lit("blended world entities: %F/%F"), FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved))); //draw_text(g->render_sig, font, pos, StringFormat(temp.arena, Lit("blended world entities: %F/%F"), FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved)));
@ -2068,7 +2066,7 @@ void UpdateUser(P_Window *window)
//- User update job //- User update job
P_JobDef(UpdateUserJob, _) JobDef(UpdateUserJob, _)
{ {
SharedUserState *g = &shared_user_state; SharedUserState *g = &shared_user_state;
i64 time_ns = P_TimeNs(); i64 time_ns = P_TimeNs();
@ -2134,7 +2132,7 @@ void GenerateuserInputCmds(Client *user_input_client, u64 tick)
//////////////////////////////// ////////////////////////////////
//~ Sim update //~ Sim update
P_JobDef(SimJob, UNUSED job) JobDef(SimJob, UNUSED job)
{ {
SharedUserState *g = &shared_user_state; SharedUserState *g = &shared_user_state;
#if 0 #if 0

View File

@ -153,7 +153,7 @@ Struct(BindState)
Struct(SharedUserState) Struct(SharedUserState)
{ {
Atomic32 shutdown; Atomic32 shutdown;
P_Counter shutdown_job_counters; Counter shutdown_job_counters;
P_Window *window; P_Window *window;
GPU_Swapchain *swapchain; GPU_Swapchain *swapchain;
@ -253,11 +253,9 @@ extern SharedUserState shared_user_state;
//~ Startup //~ Startup
Struct(UserStartupReceipt) { i32 _; }; Struct(UserStartupReceipt) { i32 _; };
UserStartupReceipt StartupUser(F_StartupReceipt *font_sr, UserStartupReceipt StartupUser(S_StartupReceipt *sprite_sr,
S_StartupReceipt *sprite_sr,
D_StartupReceipt *draw_sr, D_StartupReceipt *draw_sr,
AC_StartupReceipt *asset_cache_sr, AC_StartupReceipt *asset_cache_sr,
SND_StartupReceipt *sound_sr,
MIX_StartupReceipt *mixer_sr, MIX_StartupReceipt *mixer_sr,
SimStartupReceipt *sim_sr, SimStartupReceipt *sim_sr,
String connect_address_str); String connect_address_str);
@ -289,7 +287,7 @@ MergesortCompareFuncDef(EntitySortCmp, arg_a, arg_b, _);
//~ User update //~ User update
void UpdateUser(P_Window *window); void UpdateUser(P_Window *window);
P_JobDef(UpdateUserJob, _); JobDecl(UpdateUserJob, EmptySig);
//////////////////////////////// ////////////////////////////////
//~ User input cmds //~ User input cmds
@ -299,4 +297,4 @@ void GenerateuserInputCmds(Client *user_input_client, u64 tick);
//////////////////////////////// ////////////////////////////////
//~ Sim update //~ Sim update
P_JobDef(SimJob, _); JobDecl(SimJob, EmptySig);

View File

@ -160,7 +160,7 @@ Struct(ControlData) {
Vec2 move; /* Movement direction vector (speed of 0 -> 1) */ Vec2 move; /* Movement direction vector (speed of 0 -> 1) */
Vec2 focus; /* Focus direction vector (where does the controller want to look) */ Vec2 focus; /* Focus direction vector (where does the controller want to look) */
Vec2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */ Vec2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
u32 flags; ControlFlag flags;
}; };
typedef i32 CmdKind; enum { typedef i32 CmdKind; enum {

View File

@ -993,7 +993,7 @@ void sim_step(SimStepCtx *ctx)
ControlData *control = &player->player_control; ControlData *control = &player->player_control;
*control = cmd_ent->cmd_control; *control = cmd_ent->cmd_control;
{ {
u32 flags = control->flags; ControlFlag flags = control->flags;
player->player_cursor_pos = control->dbg_cursor; player->player_cursor_pos = control->dbg_cursor;
player->player_hovered_ent = cmd_ent->cmd_control_hovered_ent; player->player_hovered_ent = cmd_ent->cmd_control_hovered_ent;
@ -1296,7 +1296,7 @@ void sim_step(SimStepCtx *ctx)
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) { if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
ControlData *control = &ent->control; ControlData *control = &ent->control;
u32 flags = control->flags; ControlFlag flags = control->flags;
if (flags & SIM_CONTROL_FLAG_FIRE) { if (flags & SIM_CONTROL_FLAG_FIRE) {
Entity *equipped = sim_ent_from_id(world, ent->equipped); Entity *equipped = sim_ent_from_id(world, ent->equipped);
if (equipped->valid) { if (equipped->valid) {

View File

@ -173,7 +173,7 @@ abort:
} }
else else
{ {
*error_out = CopyString(arena, error); *error_out = PushString(arena, error);
} }
} }

View File

@ -1,60 +1,14 @@
SND_SharedState SND_shared_state = ZI;
////////////////////////////////
//~ Startup
SND_StartupReceipt SND_Startup(AC_StartupReceipt *asset_cache_sr)
{
__prof;
SND_SharedState *g = &SND_shared_state;
LAX asset_cache_sr;
g->params.arena = AllocArena(Gibi(64));
return (SND_StartupReceipt) { 0 };
}
////////////////////////////////
//~ Job sig store
SND_LoadAssetJobSig *SND_AllocJobSig(void)
{
SND_SharedState *g = &SND_shared_state;
SND_LoadAssetJobSig *p = 0;
{
P_Lock lock = P_LockE(&g->params.mutex);
if (g->params.head_free)
{
p = g->params.head_free;
g->params.head_free = p->next_free;
}
else
{
p = PushStruct(g->params.arena, SND_LoadAssetJobSig);
}
P_Unlock(&lock);
}
return p;
}
void SND_ReleaseJobSig(SND_LoadAssetJobSig *p)
{
SND_SharedState *g = &SND_shared_state;
P_Lock lock = P_LockE(&g->params.mutex);
p->next_free = g->params.head_free;
g->params.head_free = p;
P_Unlock(&lock);
}
//////////////////////////////// ////////////////////////////////
//~ Load job //~ Load job
P_JobDef(SND_LoadAssetJob, job) JobDef(SND_LoadAssetJob, job)
{ {
__prof; __prof;
SND_LoadAssetJobSig *params = job.sig; SND_LoadAssetJobSig *params = job.sig;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
String path = STRING(params->path_len, (u8 *)params->path_cstr); String path = STRING(params->path_len, (u8 *)params->path_cstr);
AC_Asset *asset = params->asset; AC_Asset *asset = params->asset;
u32 flags = params->flags; SND_SoundFlag flags = params->flags;
P_LogInfoF("Loading sound \"%F\"", FmtString(path)); P_LogInfoF("Loading sound \"%F\"", FmtString(path));
i64 start_ns = P_TimeNs(); i64 start_ns = P_TimeNs();
@ -125,15 +79,13 @@ P_JobDef(SND_LoadAssetJob, job)
AC_MarkReady(asset, sound); AC_MarkReady(asset, sound);
} }
SND_ReleaseJobSig(params);
EndScratch(scratch); EndScratch(scratch);
} }
//////////////////////////////// ////////////////////////////////
//~ Load sound //~ Load sound
AC_Asset *SND_LoadAsset(String path, u32 flags, b32 wait) AC_Asset *SND_LoadAsset(String path, SND_SoundFlag flags, b32 wait)
{ {
__prof; __prof;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
@ -164,7 +116,7 @@ AC_Asset *SND_LoadAsset(String path, u32 flags, b32 wait)
/* PushStruct task */ /* PushStruct task */
AC_MarkLoading(asset); AC_MarkLoading(asset);
P_Run(1, SND_LoadAssetJob, params, P_Pool_Background, P_Priority_Low, &asset->counter); P_Run(1, SND_LoadAssetJob, params, PoolKind_Background, PriorityKind_Low, &asset->counter);
if (wait) if (wait)
{ {
AC_WaitOnAssetReady(asset); AC_WaitOnAssetReady(asset);
@ -175,7 +127,7 @@ AC_Asset *SND_LoadAsset(String path, u32 flags, b32 wait)
return asset; return asset;
} }
SND_Sound *SND_LoadSoundAsync(String path, u32 flags) SND_Sound *SND_LoadSoundAsync(String path, SND_SoundFlag flags)
{ {
__prof; __prof;
AC_Asset *asset = SND_LoadAsset(path, flags, 0); AC_Asset *asset = SND_LoadAsset(path, flags, 0);
@ -183,7 +135,7 @@ SND_Sound *SND_LoadSoundAsync(String path, u32 flags)
return sound; return sound;
} }
SND_Sound *SND_LoadSoundWait(String path, u32 flags) SND_Sound *SND_LoadSoundWait(String path, SND_SoundFlag flags)
{ {
__prof; __prof;
AC_Asset *asset = SND_LoadAsset(path, flags, 1); AC_Asset *asset = SND_LoadAsset(path, flags, 1);

View File

@ -1,5 +1,5 @@
//////////////////////////////// ////////////////////////////////
//~ Sound structs //~ Sound types
#define SND_SampleRate 48000 #define SND_SampleRate 48000
@ -11,57 +11,15 @@ typedef u32 SND_SoundFlag; enum
Struct(SND_Sound) Struct(SND_Sound)
{ {
u32 flags; SND_SoundFlag flags;
u64 samples_count; u64 samples_count;
i16 *samples; i16 *samples;
}; };
////////////////////////////////
//~ Sound job types
Struct(SND_LoadAssetJobSig)
{
SND_LoadAssetJobSig *next_free;
u32 flags;
AC_Asset *asset;
u64 path_len;
char path_cstr[1024];
};
Struct(SND_LoadAssetJobSigStore)
{
SND_LoadAssetJobSig *head_free;
Arena *arena;
P_Mutex mutex;
};
////////////////////////////////
//~ Shared state
Struct(SND_SharedState)
{
SND_LoadAssetJobSigStore params;
};
extern SND_SharedState SND_shared_state;
////////////////////////////////
//~ Startup
Struct(SND_StartupReceipt) { i32 _; };
SND_StartupReceipt SND_Startup(AC_StartupReceipt *asset_cache_sr);
////////////////////////////////
//~ Sound load job
SND_LoadAssetJobSig *SND_AllocJobSig(void);
void SND_ReleaseJobSig(SND_LoadAssetJobSig *p);
//////////////////////////////// ////////////////////////////////
//~ Sound load operations //~ Sound load operations
P_JobDef(SND_LoadAssetJob, job); JobDecl(SND_LoadAssetJob, { SND_SoundFlag flags; AC_Asset *asset; String path; });
AC_Asset *SND_LoadAsset(String path, u32 flags, b32 wait); AC_Asset *SND_LoadAsset(String path, SND_SoundFlag flags, b32 wait);
SND_Sound *SND_LoadSoundAsync(String path, u32 flags); SND_Sound *SND_LoadSoundAsync(String path, SND_SoundFlag flags);
SND_Sound *SND_LoadSoundWait(String path, u32 flags); SND_Sound *SND_LoadSoundWait(String path, SND_SoundFlag flags);

View File

@ -44,7 +44,7 @@ S_StartupReceipt S_Startup(void)
g->scopes_arena = AllocArena(Gibi(64)); g->scopes_arena = AllocArena(Gibi(64));
P_Run(1, S_EvictorJob, 0, P_Pool_Background, P_Priority_Low, &g->shutdown_counter); P_Run(1, S_EvictorJob, 0, PoolKind_Background, PriorityKind_Low, &g->shutdown_counter);
P_OnExit(&S_Shutdown); P_OnExit(&S_Shutdown);
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
@ -188,7 +188,7 @@ S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase)
u64 index = 0; u64 index = 0;
for (ASE_Span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) for (ASE_Span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next)
{ {
String name = CopyString(arena, ase_span->name); String name = PushString(arena, ase_span->name);
S_Span *span = &sheet.spans[index]; S_Span *span = &sheet.spans[index];
span->name = name; span->name = name;
span->start = ase_span->start; span->start = ase_span->start;
@ -265,7 +265,7 @@ S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase)
for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next)
{ {
S_SheetSliceGroup *slice_group = &sheet.slice_groups[index]; S_SheetSliceGroup *slice_group = &sheet.slice_groups[index];
slice_group->name = CopyString(arena, temp_slice_group_node->name); slice_group->name = PushString(arena, temp_slice_group_node->name);
slice_group->per_frame_count = temp_slice_group_node->per_frame_count; slice_group->per_frame_count = temp_slice_group_node->per_frame_count;
slice_group->frame_slices = PushStructs(arena, S_Slice, ase.num_frames * slice_group->per_frame_count); slice_group->frame_slices = PushStructs(arena, S_Slice, ase.num_frames * slice_group->per_frame_count);
@ -422,7 +422,7 @@ S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase)
//~ Load job //~ Load job
//- Job def //- Job def
P_JobDef(S_LoadSpriteJob, job) JobDef(S_LoadSpriteJob, job)
{ {
__prof; __prof;
S_SharedState *g = &S_shared_state; S_SharedState *g = &S_shared_state;
@ -483,7 +483,7 @@ void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag)
} }
/* PushStruct work */ /* PushStruct work */
P_Run(1, S_LoadSpriteJob, cmd, P_Pool_Background, P_Priority_Inherit, 0); P_Run(1, S_LoadSpriteJob, cmd, PoolKind_Background, PriorityKind_Inherit, 0);
} }
//////////////////////////////// ////////////////////////////////
@ -998,7 +998,7 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
{ {
while (Atomic32Fetch(&ref.e->state) != S_CacheEntryState_Loaded) while (Atomic32Fetch(&ref.e->state) != S_CacheEntryState_Loaded)
{ {
IxPause(); _mm_pause();
} }
} }
@ -1189,7 +1189,7 @@ MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, _)
* - The cache is over its memory budget and the node's last reference is longer ago than the grace period * - The cache is over its memory budget and the node's last reference is longer ago than the grace period
* - Resource reloading is enabled and the node is out of date due to a change to its original resource file * - Resource reloading is enabled and the node is out of date due to a change to its original resource file
*/ */
P_JobDef(S_EvictorJob, _) JobDef(S_EvictorJob, _)
{ {
S_SharedState *g = &S_shared_state; S_SharedState *g = &S_shared_state;
b32 shutdown = 0; b32 shutdown = 0;

View File

@ -188,18 +188,6 @@ Struct(S_Scope)
S_Scope *next_free; S_Scope *next_free;
}; };
////////////////////////////////
//~ Cmd
Struct(S_Cmd)
{
S_Cmd *next_free;
S_Scope *scope;
S_CacheEntryRef ref;
S_Tag tag;
u8 tag_path_buff[512];
};
//////////////////////////////// ////////////////////////////////
//~ Evictor //~ Evictor
@ -249,11 +237,6 @@ Struct(S_SharedState)
/* Cache */ /* Cache */
S_Cache cache; S_Cache cache;
/* Cmds */
P_Mutex cmds_mutex;
Arena *cmds_arena;
S_Cmd *first_free_cmd;
/* Scopes */ /* Scopes */
P_Mutex scopes_mutex; P_Mutex scopes_mutex;
Arena *scopes_arena; Arena *scopes_arena;
@ -261,7 +244,7 @@ Struct(S_SharedState)
/* Evictor */ /* Evictor */
Atomic32Padded evictor_cycle; Atomic32Padded evictor_cycle;
P_Counter shutdown_counter; Counter shutdown_counter;
b32 evictor_scheduler_shutdown; b32 evictor_scheduler_shutdown;
P_Mutex evictor_scheduler_mutex; P_Mutex evictor_scheduler_mutex;
P_Cv evictor_scheduler_shutdown_cv; P_Cv evictor_scheduler_shutdown_cv;
@ -302,7 +285,7 @@ S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase);
//~ Load job //~ Load job
void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag); void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag);
P_JobDef(S_LoadSpriteJob, job); JobDecl(S_LoadSpriteJob, { S_Scope *scope; S_CacheEntryRef ref; S_Tag tag; });
//////////////////////////////// ////////////////////////////////
//~ Cache load operations //~ Cache load operations
@ -365,4 +348,4 @@ W_CallbackFuncDef(S_WatchSpriteCallback, name);
//~ Evictor job //~ Evictor job
MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, udata); MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, udata);
P_JobDef(S_EvictorJob, _); JobDecl(S_EvictorJob, EmptySig);

View File

@ -10,8 +10,8 @@ void W_Startup(void)
g->watch_events_arena = AllocArena(Gibi(64)); g->watch_events_arena = AllocArena(Gibi(64));
P_Run(1, W_MonitorJob, 0, P_Pool_Floating, P_Priority_Low, &g->watch_jobs_counter); P_Run(1, W_MonitorJob, 0, PoolKind_Floating, PriorityKind_Low, &g->watch_jobs_counter);
P_Run(1, W_DispatcherJob, 0, P_Pool_Background, P_Priority_Low, &g->watch_jobs_counter); P_Run(1, W_DispatcherJob, 0, PoolKind_Background, PriorityKind_Low, &g->watch_jobs_counter);
P_OnExit(&W_Shutdown); P_OnExit(&W_Shutdown);
} }
@ -49,7 +49,7 @@ void W_RegisterCallback(W_CallbackFunc *callback)
P_Unlock(&lock); P_Unlock(&lock);
} }
P_JobDef(W_RunCallbackJob, job) JobDef(W_RunCallbackJob, job)
{ {
__prof; __prof;
W_RunCallbackJobSig *sig = job.sig; W_RunCallbackJobSig *sig = job.sig;
@ -65,7 +65,7 @@ P_JobDef(W_RunCallbackJob, job)
* & dispatching watch callbacks into two separate jobs so that we can delay * & dispatching watch callbacks into two separate jobs so that we can delay
* the dispatch, allowing for deduplication of file modification notifications. */ * the dispatch, allowing for deduplication of file modification notifications. */
P_JobDef(W_MonitorJob, _) JobDef(W_MonitorJob, _)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
W_SharedState *g = &W_shared_state; W_SharedState *g = &W_shared_state;
@ -98,7 +98,7 @@ P_JobDef(W_MonitorJob, _)
if (!ignore) if (!ignore)
{ {
W_Event *e = PushStruct(g->watch_events_arena, W_Event); W_Event *e = PushStruct(g->watch_events_arena, W_Event);
e->name = CopyString(g->watch_events_arena, name_src); e->name = PushString(g->watch_events_arena, name_src);
if (g->last_watch_event) if (g->last_watch_event)
{ {
g->last_watch_event->next = e; g->last_watch_event->next = e;
@ -123,7 +123,7 @@ P_JobDef(W_MonitorJob, _)
//////////////////////////////// ////////////////////////////////
//~ Dispatcher job //~ Dispatcher job
P_JobDef(W_DispatcherJob, _) JobDef(W_DispatcherJob, _)
{ {
W_SharedState *g = &W_shared_state; W_SharedState *g = &W_shared_state;
@ -147,7 +147,7 @@ P_JobDef(W_DispatcherJob, _)
for (W_Event *src_event = g->first_watch_event; src_event; src_event = src_event->next) for (W_Event *src_event = g->first_watch_event; src_event; src_event = src_event->next)
{ {
W_Event *e = PushStruct(scratch.arena, W_Event); W_Event *e = PushStruct(scratch.arena, W_Event);
e->name = CopyString(scratch.arena, src_event->name); e->name = PushString(scratch.arena, src_event->name);
if (last_watch_event) if (last_watch_event)
{ {
last_watch_event->next = e; last_watch_event->next = e;
@ -200,8 +200,8 @@ P_JobDef(W_DispatcherJob, _)
W_RunCallbackJobSig sig = ZI; W_RunCallbackJobSig sig = ZI;
sig.name = e->name; sig.name = e->name;
sig.callbacks = callbacks; sig.callbacks = callbacks;
P_Counter counter = ZI; Counter counter = ZI;
P_Run(num_callbacks, W_RunCallbackJob, &sig, P_Pool_Background, P_Priority_Low, &counter); P_Run(num_callbacks, W_RunCallbackJob, &sig, PoolKind_Background, PriorityKind_Low, &counter);
P_WaitOnCounter(&counter); P_WaitOnCounter(&counter);
} }
} }

View File

@ -29,7 +29,7 @@ Struct(W_SharedState)
{ {
P_Watch *watch; P_Watch *watch;
Atomic32 W_Shutdown; Atomic32 W_Shutdown;
P_Counter watch_jobs_counter; Counter watch_jobs_counter;
P_Mutex watch_dispatcher_mutex; P_Mutex watch_dispatcher_mutex;
Arena *watch_events_arena; Arena *watch_events_arena;
@ -58,10 +58,10 @@ void W_RegisterCallback(W_CallbackFunc *callback);
//////////////////////////////// ////////////////////////////////
//~ Callback job //~ Callback job
P_JobDef(W_RunCallbackJob, job); JobDecl(W_RunCallbackJob, EmptySig);
//////////////////////////////// ////////////////////////////////
//~ Long running jobs //~ Long running jobs
P_JobDef(W_MonitorJob, job); JobDecl(W_MonitorJob, { i32 _; });
P_JobDef(W_DispatcherJob, job); JobDecl(W_DispatcherJob, { i32 _; });