formatting

This commit is contained in:
jacob 2025-09-12 13:03:00 -05:00
parent 64dad2457c
commit 2fbaef09ec
20 changed files with 143 additions and 169 deletions

View File

@ -135,7 +135,6 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
.hash = hash, .hash = hash,
.key = key_stored .key = key_stored
}; };
AddCounter(&asset->counter, 1);
if (is_first_touch) if (is_first_touch)
{ {
*is_first_touch = 1; *is_first_touch = 1;
@ -165,12 +164,12 @@ void AC_MarkReady(AC_Asset *asset, void *store_data)
{ {
asset->store_data = store_data; asset->store_data = store_data;
asset->status = ASSET_STATUS_READY; asset->status = ASSET_STATUS_READY;
AddCounter(&asset->counter, -1); SetFence(&asset->ready_fence, 1);
} }
void AC_YieldOnAssetReady(AC_Asset *asset) void AC_YieldOnAssetReady(AC_Asset *asset)
{ {
YieldOnCounter(&asset->counter); YieldOnFence(&asset->ready_fence, 1);
} }
//////////////////////////////// ////////////////////////////////

View File

@ -17,7 +17,8 @@ Struct(AC_Asset)
u64 hash; u64 hash;
String key; String key;
Counter counter; /* Asset is ready when fence >= 1 */
Fence ready_fence;
/* Managed via asset_cache_mark_x functions */ /* Managed via asset_cache_mark_x functions */
AC_Status status; AC_Status status;

View File

@ -545,30 +545,37 @@ StaticAssert(alignof(Atomic32Padded) == CachelineSize && sizeof(Atomic32Padded)
StaticAssert(alignof(Atomic64Padded) == CachelineSize && sizeof(Atomic64Padded) % CachelineSize == 0); StaticAssert(alignof(Atomic64Padded) == CachelineSize && sizeof(Atomic64Padded) % CachelineSize == 0);
#if PlatformIsWindows && ArchIsX64 #if PlatformIsWindows && ArchIsX64
//- Memory barriers
# define CompilerMemoryBarrier() _ReadWriteBarrier()
# define HardwareMemoryBarrier() MemoryBarrier()
//- 8 bit atomic operations //- 8 bit atomic operations
#define Atomic8Fetch(x) (x)->_v ForceInline i8 Atomic8Fetch (Atomic8 *x) { i8 result = (x)->_v; CompilerMemoryBarrier(); return result; }
#define Atomic8FetchSet(x, e) (i8)_InterlockedExchange8((volatile char *)&(x)->_v, (e)) ForceInline void Atomic8Set (Atomic8 *x, i8 e) { CompilerMemoryBarrier(); (x)->_v = e; }
#define Atomic8FetchTestSet(x, c, e) (i8)_InterlockedCompareExchange8((volatile char *)&(x)->_v, (e), (c)) ForceInline i8 Atomic8FetchSet (Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((volatile char *)&(x)->_v, (e)); }
#define Atomic8FetchXor(x, c) (i8)_InterlockedXor8((volatile char *)&(x)->_v, (c)) ForceInline i8 Atomic8FetchTestSet (Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((volatile char *)&(x)->_v, (e), (c)); }
#define Atomic8FetchAdd(x, a) (i8)_InterlockedExchangeAdd8((volatile char *)&(x)->_v, (a)) ForceInline i8 Atomic8FetchXor (Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((volatile char *)&(x)->_v, (c)); }
ForceInline i8 Atomic8FetchAdd (Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((volatile char *)&(x)->_v, (a)); }
//- 16 bit atomic operations //- 16 bit atomic operations
#define Atomic16Fetch(x) (x)->_v ForceInline i16 Atomic16Fetch (Atomic16 *x) { i16 result = (x)->_v; CompilerMemoryBarrier(); return result; }
#define Atomic16FetchSet(x, e) (i16)_InterlockedExchange16(&(x)->_v, (e)) ForceInline void Atomic16Set (Atomic16 *x, i16 e) { CompilerMemoryBarrier(); (x)->_v = e; }
#define Atomic16FetchTestSet(x, c, e) (i16)_InterlockedCompareExchange16(&(x)->_v, (e), (c)) ForceInline i16 Atomic16FetchSet (Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&(x)->_v, (e)); }
#define Atomic16FetchXor(x, c) (i16)_InterlockedXor16(&(x)->_v, (c)) ForceInline i16 Atomic16FetchTestSet (Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&(x)->_v, (e), (c)); }
#define Atomic16FetchAdd(x, a) (i16)_InterlockedExchangeAdd16(&(x)->_v, (a)) ForceInline i16 Atomic16FetchXor (Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&(x)->_v, (c)); }
ForceInline i16 Atomic16FetchAdd (Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&(x)->_v, (a)); }
//- 32 bit atomic operations //- 32 bit atomic operations
#define Atomic32Fetch(x) (x)->_v ForceInline i32 Atomic32Fetch (Atomic32 *x) { i32 result = (x)->_v; CompilerMemoryBarrier(); return result; }
#define Atomic32FetchSet(x, e) (i32)_InterlockedExchange((volatile long *)&(x)->_v, (e)) ForceInline void Atomic32Set (Atomic32 *x, i32 e) { CompilerMemoryBarrier(); (x)->_v = e; }
#define Atomic32FetchTestSet(x, c, e) (i32)_InterlockedCompareExchange((volatile long *)&(x)->_v, (e), (c)) ForceInline i32 Atomic32FetchSet (Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&(x)->_v, (e)); }
#define Atomic32FetchXor(x, c) (i32)_InterlockedXor((volatile long *)&(x)->_v, (c)) ForceInline i32 Atomic32FetchTestSet (Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&(x)->_v, (e), (c)); }
#define Atomic32FetchAdd(x, a) (i32)_InterlockedExchangeAdd((volatile long *)&(x)->_v, (a)) 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 //- 64 bit atomic operations
#define Atomic64Fetch(x) (x)->_v ForceInline i64 Atomic64Fetch (Atomic64 *x) { i16 result = (x)->_v; CompilerMemoryBarrier(); return result; }
#define Atomic64FetchSet(x, e) (i64)_InterlockedExchange64(&(x)->_v, (e)) ForceInline void Atomic64Set (Atomic64 *x, i64 e) { CompilerMemoryBarrier(); (x)->_v = e; }
#define Atomic64FetchTestSet(x, c, e) (i64)_InterlockedCompareExchange64(&(x)->_v, (e), (c)) ForceInline i64 Atomic64FetchSet (Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&(x)->_v, (e)); }
#define Atomic64FetchXor(x, c) (i64)_InterlockedXor64(&(x)->_v, (c)) ForceInline i64 Atomic64FetchTestSet (Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&(x)->_v, (e), (c)); }
#define Atomic64FetchAdd(x, a) (i64)_InterlockedExchangeAdd64(&(x)->_v, (a)) 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 #else
# error Atomics not implemented # error Atomics not implemented
#endif #endif
@ -712,8 +719,8 @@ Struct(ComputeShader) { Resource resource; };
# else # else
# error FiberId not implemented # error FiberId not implemented
# endif # endif
# define MaxFibers 1024 # define MaxFibers 4096
StaticAssert(MaxFibers < I16Max); /* FiberId type should fit MaxFibers */ StaticAssert(MaxFibers < I16Max); /* MaxFibers should fit in FiberId */
#endif #endif

View File

@ -14,7 +14,7 @@ Struct(SharedGstatCtx)
extern SharedGstatCtx _shared_gstat_ctx; extern SharedGstatCtx _shared_gstat_ctx;
#define SetGstat(name, value) Atomic64FetchSet(&_shared_gstat_ctx.name.v, (value)) #define SetGstat(name, value) Atomic64Set(&_shared_gstat_ctx.name.v, (value))
#define AddGstat(name, value) Atomic64FetchAdd(&_shared_gstat_ctx.name.v, (value)) #define AddGstat(name, value) Atomic64FetchAdd(&_shared_gstat_ctx.name.v, (value))
#define GetGstat(name) Atomic64Fetch(&_shared_gstat_ctx.name.v) #define GetGstat(name) Atomic64Fetch(&_shared_gstat_ctx.name.v)

View File

@ -12,24 +12,24 @@ Enum(JobPool)
{ {
JobPool_Inherit = -1, JobPool_Inherit = -1,
/* Contains worker threads affinitized over the entire CPU. /* Contains un-affinitized worker threads.
* Meant to take on high-bandwidth temporary work (e.g. loading a level). */ * Meant to take on temporary high-throughput work that is allowed to interfere with all other pools (e.g. loading a level). */
JobPool_Hyper = 0, /* High-priority */ JobPool_Hyper = 0,
/* Contains worker threads affinitized over the entire CPU. /* Contains un-affinitized worker threads.
* Meant to take on blocking work so that affinitized workers workers can continue doing actual work. */ * Meant to take on blocking work so that affinitized workers can continue doing actual work. */
JobPool_Blocking = 1, /* Normal priority */ JobPool_Blocking = 1,
/* Contains worker threads affinitized to cores that don't interfere with workers in specialized pools. /* Contains worker threads affinitized to cores that don't interfere with workers in specialized pools.
* Meant to consume asynchronous work from higher priority pools. */ * Meant to consume asynchronous work from higher priority pools. */
JobPool_Background = 2, /* Normal priority */ JobPool_Background = 2,
/* Contains worker threads affinitized to cores that don't interfere with workers in other specialized pools. /* Contains worker threads affinitized to cores that don't interfere with workers in other specialized pools.
* These pools are meant to only have work pushed onto them from jobs within the same pool (e.g. 100 jobs pushed onto the * These pools are meant to only have work pushed onto them from jobs within the same pool (e.g. 100 jobs pushed onto the
* User pool will not interfere with cores running workers on the Sim pool). */ * User pool will not interfere with cores running the Sim pool). */
JobPool_Audio = 3, /* Critical priority */ JobPool_Audio = 3,
JobPool_User = 4, /* Above-normal priority */ JobPool_User = 4,
JobPool_Sim = 5, /* Above-normal priority */ JobPool_Sim = 5,
JobPool_Count JobPool_Count
}; };
@ -37,26 +37,29 @@ Enum(JobPool)
//////////////////////////////// ////////////////////////////////
//~ Job types //~ Job types
typedef void JobFunc(void *, i32);
Struct(JobCounter) Struct(JobCounter)
{ {
Fence jobs_completed_fence;
Atomic64Padded num_jobs_dispatched; Atomic64Padded num_jobs_dispatched;
Fence num_jobs_completed_fence;
}; };
typedef void JobFunc(void *, i32);
Struct(Job) Struct(Job)
{ {
/* Internal */
Job *next; Job *next;
Atomic32Padded num_tasks_completed;
/* Initialized & constant after OpenJob */
Arena *arena; Arena *arena;
JobFunc *func; JobFunc *func;
JobPool pool; JobPool pool;
/* Configurable between OpenJob & CloseJob */
i32 count; i32 count;
JobCounter *counter; JobCounter *counter;
void *sig; void *sig;
Atomic64Padded num_tasks_completed;
}; };
//////////////////////////////// ////////////////////////////////
@ -112,4 +115,4 @@ do {
Job *OpenJob(JobFunc *func, JobPool pool_kind); Job *OpenJob(JobFunc *func, JobPool pool_kind);
void CloseJob(Job *job); void CloseJob(Job *job);
#define YieldOnJobs(counter) (YieldOnFence(&(counter)->jobs_completed_fence, Atomic64Fetch(&(counter)->num_jobs_dispatched.v))) #define YieldOnJobs(counter) (YieldOnFence(&(counter)->num_jobs_completed_fence, Atomic64Fetch(&(counter)->num_jobs_dispatched.v)))

View File

@ -56,7 +56,7 @@ Lock LockSpinE(Mutex *m, i32 spin)
} }
#if RtcIsEnabled #if RtcIsEnabled
Atomic32FetchSet(&m->exclusive_fiber_id, FiberId()); Atomic32Set(&m->exclusive_fiber_id, FiberId());
#endif #endif
Lock lock = ZI; Lock lock = ZI;
@ -123,9 +123,9 @@ void Unlock(Lock *l)
if (l->exclusive) if (l->exclusive)
{ {
#if RtcIsEnabled #if RtcIsEnabled
Atomic32FetchSet(&m->exclusive_fiber_id, 0); Atomic32Set(&m->exclusive_fiber_id, 0);
#endif #endif
Atomic32FetchSet(&m->v, 0); Atomic32Set(&m->v, 0);
} }
else else
{ {
@ -165,34 +165,6 @@ void SignalCv(Cv *cv)
FutexWakeNeq(&cv->wake_gen); FutexWakeNeq(&cv->wake_gen);
} }
////////////////////////////////
//~ Counter
i64 ValueFromCounter(Counter *counter)
{
return Atomic64Fetch(&counter->v);
}
void AddCounter(Counter *counter, i64 x)
{
i64 old_v = Atomic64FetchAdd(&counter->v, x);
i64 new_v = old_v + x;
if (old_v > 0 && new_v <= 0)
{
FutexWakeNeq(&counter->v);
}
}
void YieldOnCounter(Counter *counter)
{
i64 v = Atomic64Fetch(&counter->v);
while (v > 0)
{
FutexYieldNeq(&counter->v, &v, sizeof(v));
v = Atomic64Fetch(&counter->v);
}
}
//////////////////////////////// ////////////////////////////////
//~ Fence //~ Fence
@ -201,13 +173,16 @@ i64 FetchFence(Fence *fence)
return Atomic64Fetch(&fence->v.v); return Atomic64Fetch(&fence->v.v);
} }
void SetFence(Fence *fence, i64 x)
{
Atomic64Set(&fence->v.v, x);
FutexWakeGte(&fence->v.v);
}
i64 FetchSetFence(Fence *fence, i64 x) i64 FetchSetFence(Fence *fence, i64 x)
{ {
i64 fetch = Atomic64FetchSet(&fence->v.v, x); i64 fetch = Atomic64FetchSet(&fence->v.v, x);
if (x > fetch)
{
FutexWakeGte(&fence->v.v); FutexWakeGte(&fence->v.v);
}
return fetch; return fetch;
} }

View File

@ -32,15 +32,6 @@ AlignedStruct(Cv, CachelineSize)
}; };
StaticAssert(alignof(Cv) == CachelineSize && sizeof(Cv) % CachelineSize == 0); StaticAssert(alignof(Cv) == CachelineSize && sizeof(Cv) % CachelineSize == 0);
////////////////////////////////
//~ Counter types
AlignedStruct(Counter, CachelineSize)
{
Atomic64 v;
};
StaticAssert(alignof(Counter) == CachelineSize && sizeof(Counter) % CachelineSize == 0);
//////////////////////////////// ////////////////////////////////
//~ Fence types //~ Fence types
@ -75,17 +66,11 @@ void Unlock(Lock *lock);
void YieldOnCv(Cv *cv, Lock *lock); void YieldOnCv(Cv *cv, Lock *lock);
void SignalCv(Cv *cv); void SignalCv(Cv *cv);
////////////////////////////////
//~ Counter operations
i64 ValueFromCounter(Counter *counter);
void AddCounter(Counter *counter, i64 x);
void YieldOnCounter(Counter *counter);
//////////////////////////////// ////////////////////////////////
//~ Fence operations //~ Fence operations
i64 FetchFence(Fence *fence); i64 FetchFence(Fence *fence);
void SetFence(Fence *fence, i64 x);
i64 FetchSetFence(Fence *fence, i64 x); i64 FetchSetFence(Fence *fence, i64 x);
i64 FetchAddFence(Fence *fence, i64 x); i64 FetchAddFence(Fence *fence, i64 x);

View File

@ -123,7 +123,7 @@ void OnExit(ExitFunc *func)
void SignalExit(i32 code) void SignalExit(i32 code)
{ {
W32_SharedState *g = &W32_shared_state; W32_SharedState *g = &W32_shared_state;
Atomic32FetchSet(&g->exit_code, code); Atomic32Set(&g->exit_code, code);
SetEvent(g->exit_begin_event); SetEvent(g->exit_begin_event);
} }
@ -241,13 +241,7 @@ i32 W32_Main(void)
} }
#endif #endif
/* Set up exit events */ /* Init time */
g->panic_event = CreateEventW(0, 1, 0, 0);
g->startup_end_event = CreateEventW(0, 1, 0, 0);
g->exit_begin_event = CreateEventW(0, 1, 0, 0);
g->exit_end_event = CreateEventW(0, 1, 0, 0);
/* Query performance frequency */
{ {
LARGE_INTEGER qpf; LARGE_INTEGER qpf;
QueryPerformanceFrequency(&qpf); QueryPerformanceFrequency(&qpf);
@ -259,6 +253,12 @@ i32 W32_Main(void)
g->timer_start_qpc = qpc.QuadPart; g->timer_start_qpc = qpc.QuadPart;
} }
/* Set up exit events */
g->panic_event = CreateEventW(0, 1, 0, 0);
g->startup_end_event = CreateEventW(0, 1, 0, 0);
g->exit_begin_event = CreateEventW(0, 1, 0, 0);
g->exit_end_event = CreateEventW(0, 1, 0, 0);
g->main_thread_id = GetCurrentThreadId(); g->main_thread_id = GetCurrentThreadId();
SetThreadDescription(GetCurrentThread(), L"Main thread"); SetThreadDescription(GetCurrentThread(), L"Main thread");

View File

@ -187,19 +187,6 @@ void W32_WaitEndThread(W32_Thread *thread)
Assert(success); Assert(success);
} }
////////////////////////////////
//~ Pool operations
W32_JobPool *W32_JobPoolFromKind(JobPool pool_kind)
{
if (pool_kind == JobPool_Inherit)
{
W32_Fiber *fiber = W32_FiberFromId(FiberId());
pool_kind = fiber->pool;
}
return &W32_shared_job_state.job_pools[pool_kind];
}
//////////////////////////////// ////////////////////////////////
//~ Win32 fiber //~ Win32 fiber
@ -334,7 +321,7 @@ void W32_FiberEntryPoint(void *win32_fiber_data)
{ {
i16 fiber_id = (i16)(i64)win32_fiber_data; i16 fiber_id = (i16)(i64)win32_fiber_data;
volatile W32_Fiber *fiber = W32_FiberFromId(fiber_id); volatile W32_Fiber *fiber = W32_FiberFromId(fiber_id);
W32_JobPool *pool = W32_JobPoolFromKind(fiber->pool); W32_JobPool *pool = &W32_shared_job_state.job_pools[fiber->pool];
JobPool pool_kind = fiber->pool; JobPool pool_kind = fiber->pool;
char *fiber_name_cstr = fiber->name_cstr; char *fiber_name_cstr = fiber->name_cstr;
for (;;) for (;;)
@ -349,10 +336,10 @@ void W32_FiberEntryPoint(void *win32_fiber_data)
/* Check if we've completed the last task in the job */ /* Check if we've completed the last task in the job */
if (Atomic32FetchAdd(&job->num_tasks_completed.v, 1) + 1 >= job->count) if (Atomic32FetchAdd(&job->num_tasks_completed.v, 1) + 1 >= job->count)
{ {
/* Increment fence */ /* Increment counter */
if (job->counter) if (job->counter)
{ {
FetchAddFence(&job->counter->jobs_completed_fence, 1); FetchAddFence(&job->counter->num_jobs_completed_fence, 1);
} }
/* Free job */ /* Free job */
LockTicketMutex(&pool->free_jobs_tm); LockTicketMutex(&pool->free_jobs_tm);
@ -387,7 +374,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
{ {
W32_WorkerCtx *ctx = worker_ctx_arg; W32_WorkerCtx *ctx = worker_ctx_arg;
JobPool pool_kind = ctx->pool_kind; JobPool pool_kind = ctx->pool_kind;
W32_JobPool *pool = W32_JobPoolFromKind(pool_kind); W32_JobPool *pool = &W32_shared_job_state.job_pools[pool_kind];
i16 worker_fiber_id = FiberId(); i16 worker_fiber_id = FiberId();
@ -514,7 +501,7 @@ void SuspendFiber(void)
Assert(parent_fiber->id > 0); Assert(parent_fiber->id > 0);
{ {
__prof_fiber_leave(); __prof_fiber_leave();
Atomic8FetchSet(&fiber->is_suspending, 1); Atomic8Set(&fiber->is_suspending, 1);
W32_SwitchToFiber(parent_fiber); W32_SwitchToFiber(parent_fiber);
__prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS - Mebi(fiber->pool) + Kibi(1) + fiber->id); __prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS - Mebi(fiber->pool) + Kibi(1) + fiber->id);
} }
@ -584,7 +571,12 @@ void ResumeFibers(i16 fiber_ids_count, i16 *fiber_ids)
Job *OpenJob(JobFunc *func, JobPool pool_kind) Job *OpenJob(JobFunc *func, JobPool pool_kind)
{ {
W32_JobPool *pool = W32_JobPoolFromKind(pool_kind); if (pool_kind == JobPool_Inherit)
{
W32_Fiber *fiber = W32_FiberFromId(FiberId());
pool_kind = fiber->pool;
}
W32_JobPool *pool = &W32_shared_job_state.job_pools[pool_kind];
Job *job = 0; Job *job = 0;
{ {
Arena *job_arena = 0; Arena *job_arena = 0;
@ -621,7 +613,7 @@ void CloseJob(Job *job)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
W32_JobPool *pool = W32_JobPoolFromKind(job->pool); W32_JobPool *pool = &W32_shared_job_state.job_pools[job->pool];
u32 num_tasks = job->count; u32 num_tasks = job->count;
if (num_tasks > 0) if (num_tasks > 0)
@ -684,7 +676,6 @@ void CloseJob(Job *job)
{ {
LockTicketMutex(&pool->tasks_tm); LockTicketMutex(&pool->tasks_tm);
{ {
// QueuePush(pool->first_task, pool->last_task, tasks.first);
if (pool->last_task) if (pool->last_task)
{ {
pool->last_task->next = tasks.first; pool->last_task->next = tasks.first;

View File

@ -178,11 +178,6 @@ W32_Thread *W32_StartThread(W32_ThreadFunc *entry_point, void *thread_udata, Str
b32 W32_TryEndThread(W32_Thread *thread, f32 timeout_seconds); b32 W32_TryEndThread(W32_Thread *thread, f32 timeout_seconds);
void W32_WaitEndThread(W32_Thread *thread); void W32_WaitEndThread(W32_Thread *thread);
////////////////////////////////
//~ Pool operations
W32_JobPool *W32_JobPoolFromKind(JobPool pool_kind);
//////////////////////////////// ////////////////////////////////
//~ Fiber operations //~ Fiber operations

View File

@ -283,7 +283,7 @@ GPU_Fence GPU_GetGlobalFence(void);
//~ @hookdecl Resource operations //~ @hookdecl Resource operations
GPU_Resource *GPU_AcquireResource(GPU_ResourceDesc desc); GPU_Resource *GPU_AcquireResource(GPU_ResourceDesc desc);
void GPU_ReleaseResource(GPU_Resource *resource, GPU_Fence fence, GPU_ReleaseFlag flags); void GPU_ReleaseResource(GPU_Resource *resource, GPU_ReleaseFlag flags);
u32 GPU_GetResourceId(GPU_Resource *resource); u32 GPU_GetResourceId(GPU_Resource *resource);
Vec2I32 GPU_GetTextureSize(GPU_Resource *resource); Vec2I32 GPU_GetTextureSize(GPU_Resource *resource);

View File

@ -110,7 +110,7 @@ GPU_Resource *GPU_AcquireResource(GPU_ResourceDesc desc)
return 0; return 0;
} }
void GPU_ReleaseResource(GPU_Resource *resource, GPU_Fence fence, GPU_ReleaseFlag flags) void GPU_ReleaseResource(GPU_Resource *resource, GPU_ReleaseFlag flags)
{ {
/* TODO */ /* TODO */
} }

View File

@ -529,6 +529,7 @@ JobDef(Step, sig, id)
++i; ++i;
} }
} }
JobCounter counter = ZI; JobCounter counter = ZI;
RunJob(RunCommand, RunJob(RunCommand,
.count = shader_entries_count, .count = shader_entries_count,
@ -1098,7 +1099,7 @@ JobDef(Build, _, __)
EchoLine(msg); EchoLine(msg);
} }
EchoLine(StringF(arena, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs()))));
ExitNow(ret); ExitNow(ret);
} }

View File

@ -21,7 +21,7 @@ void P_StartupLog(void)
ctx->file_valid = 1; ctx->file_valid = 1;
} }
} }
Atomic32FetchSet(&ctx->initialized, 1); Atomic32Set(&ctx->initialized, 1);
} }
//////////////////////////////// ////////////////////////////////

View File

@ -183,9 +183,8 @@ P_W32_Window *P_W32_AcquireWindow(void)
/* NOTE: This thread must finish building for the window to actually be /* NOTE: This thread must finish building for the window to actually be
* created and receive a HWND, because on Windows a the event proc must run on * created and receive a HWND, because on Windows a the event proc must run on
* the same thread that created the window. */ * the same thread that created the window. */
AddCounter(&window->ready_fence, 1);
window->window_thread = W32_StartThread(&P_W32_WindowThreadEntryFunc, window, Lit("Window thread"), PROF_THREAD_GROUP_WINDOW); window->window_thread = W32_StartThread(&P_W32_WindowThreadEntryFunc, window, Lit("Window thread"), PROF_THREAD_GROUP_WINDOW);
YieldOnCounter(&window->ready_fence); YieldOnFence(&window->ready_fence, 1);
return window; return window;
} }
@ -193,7 +192,7 @@ P_W32_Window *P_W32_AcquireWindow(void)
void P_W32_ReleaseWindow(P_W32_Window *window) void P_W32_ReleaseWindow(P_W32_Window *window)
{ {
/* Stop window threads */ /* Stop window threads */
Atomic32FetchSet(&window->shutdown, 1); Atomic32Set(&window->shutdown, 1);
P_W32_SharedState *g = &P_W32_shared_state; P_W32_SharedState *g = &P_W32_shared_state;
P_W32_WakeWindow(window); P_W32_WakeWindow(window);
W32_WaitEndThread(window->window_thread); W32_WaitEndThread(window->window_thread);
@ -400,7 +399,7 @@ W32_ThreadDef(P_W32_WindowThreadEntryFunc, arg)
window->hwnd = P_W32_InitWindow(window); window->hwnd = P_W32_InitWindow(window);
P_W32_UpdateWindowFromSystem(window); P_W32_UpdateWindowFromSystem(window);
BringWindowToTop(window->hwnd); BringWindowToTop(window->hwnd);
AddCounter(&window->ready_fence, -1); SetFence(&window->ready_fence, 1);
while (!Atomic32Fetch(&window->shutdown)) while (!Atomic32Fetch(&window->shutdown))
{ {
@ -887,14 +886,13 @@ JobDef(P_W32_UpdateTimer, _, __)
periods[i] = P_W32_DefaultTimerPeriodNs; periods[i] = P_W32_DefaultTimerPeriodNs;
} }
Echo(Lit("Starting timer\n"));
i64 last_cycle_ns = 0; i64 last_cycle_ns = 0;
/* FIXME: shutdown */ /* FIXME: shutdown */
for (;;) for (;;)
{ {
__profn("Job scheduler cycle"); __profn("Job scheduler cycle");
{ {
/* TODO: Minimum timer frequency in case windows timers ever become ultra precise in the future */
__profn("Job scheduler wait"); __profn("Job scheduler wait");
LARGE_INTEGER due = ZI; LARGE_INTEGER due = ZI;
due.QuadPart = -1; due.QuadPart = -1;
@ -922,11 +920,11 @@ JobDef(P_W32_UpdateTimer, _, __)
periods_sum_ns += (f64)periods[i]; periods_sum_ns += (f64)periods[i];
} }
f64 mean_ns = periods_sum_ns / (f64)countof(periods); f64 mean_ns = periods_sum_ns / (f64)countof(periods);
Atomic64FetchSet(&g->average_timer_period_ns.v, RoundF64ToI64(mean_ns)); Atomic64Set(&g->average_timer_period_ns.v, RoundF64ToI64(mean_ns));
} }
/* Update fence */ /* Update fence */
FetchSetFence(&g->timer_fence, now_ns); SetFence(&g->timer_fence, now_ns);
} }
} }

View File

@ -41,7 +41,7 @@ Struct(P_W32_Window)
u32 flags; u32 flags;
HWND hwnd; HWND hwnd;
Counter ready_fence; Fence ready_fence;
u16 utf16_high_surrogate_last_input; u16 utf16_high_surrogate_last_input;

View File

@ -23,7 +23,7 @@ ExitFuncDef(PB_WSP_Shutdown)
{ {
__prof; __prof;
PB_WSP_SharedState *g = &PB_WSP_shared_state; PB_WSP_SharedState *g = &PB_WSP_shared_state;
Atomic32FetchSet(&g->shutdown, 1); Atomic32Set(&g->shutdown, 1);
YieldOnJobs(&g->shutdown_job_counter); YieldOnJobs(&g->shutdown_job_counter);
} }

View File

@ -60,7 +60,7 @@ ExitFuncDef(ShutdownUser)
{ {
__prof; __prof;
SharedUserState *g = &shared_user_state; SharedUserState *g = &shared_user_state;
Atomic32FetchSet(&g->shutdown, 1); Atomic32Set(&g->shutdown, 1);
YieldOnJobs(&g->shutdown_job_counter); YieldOnJobs(&g->shutdown_job_counter);
P_ReleaseWindow(g->window); P_ReleaseWindow(g->window);
} }
@ -2149,12 +2149,13 @@ void UpdateUser(P_Window *window)
if (g->shade_target && !EqVec2I32(g->render_size, GPU_GetTextureSize(g->shade_target))) if (g->shade_target && !EqVec2I32(g->render_size, GPU_GetTextureSize(g->shade_target)))
{ {
__profn("Release render resources"); __profn("Release render resources");
GPU_ReleaseResource(g->albedo, g->render_fence, GPU_ReleaseFlag_None); /* FIXME: Yield on render fence */
GPU_ReleaseResource(g->emittance, g->render_fence, GPU_ReleaseFlag_None); GPU_ReleaseResource(g->albedo, GPU_ReleaseFlag_None);
GPU_ReleaseResource(g->emittance_flood_read, g->render_fence, GPU_ReleaseFlag_None); GPU_ReleaseResource(g->emittance, GPU_ReleaseFlag_None);
GPU_ReleaseResource(g->emittance_flood_target, g->render_fence, GPU_ReleaseFlag_None); GPU_ReleaseResource(g->emittance_flood_read, GPU_ReleaseFlag_None);
GPU_ReleaseResource(g->shade_read, g->render_fence, GPU_ReleaseFlag_None); GPU_ReleaseResource(g->emittance_flood_target, GPU_ReleaseFlag_None);
GPU_ReleaseResource(g->shade_target, g->render_fence, GPU_ReleaseFlag_None); GPU_ReleaseResource(g->shade_read, GPU_ReleaseFlag_None);
GPU_ReleaseResource(g->shade_target, GPU_ReleaseFlag_None);
g->shade_target = 0; g->shade_target = 0;
} }
if (!g->shade_target) if (!g->shade_target)
@ -2171,7 +2172,8 @@ void UpdateUser(P_Window *window)
/* Acquire ui buffers */ /* Acquire ui buffers */
if (g->ui_target && !EqVec2I32(g->ui_size, GPU_GetTextureSize(g->ui_target))) if (g->ui_target && !EqVec2I32(g->ui_size, GPU_GetTextureSize(g->ui_target)))
{ {
GPU_ReleaseResource(g->ui_target, g->render_fence, GPU_ReleaseFlag_None); /* FIXME: Wait on render fence */
GPU_ReleaseResource(g->ui_target, GPU_ReleaseFlag_None);
g->ui_target = 0; g->ui_target = 0;
} }
if (!g->ui_target) if (!g->ui_target)
@ -2416,16 +2418,34 @@ void UpdateUser(P_Window *window)
GPU_RasterizeMode_TriangleList); GPU_RasterizeMode_TriangleList);
} }
} }
g->render_fence = GPU_EndCommandList(cl);
/* FIXME: Enable this */
#if 0
g->most_recent_render_counter = GPU_EndCommandList(cl);
/* Release transfer buffers */ /* Release transfer buffers */
{ {
GPU_ReleaseResource(quad_index_buffer, g->render_fence, GPU_ReleaseFlag_Reuse); {
GPU_ReleaseResource(material_instance_buffer, g->render_fence, GPU_ReleaseFlag_Reuse); /* FIXME: Release resources */
GPU_ReleaseResource(ui_rect_instance_buffer, g->render_fence, GPU_ReleaseFlag_Reuse); GPU_Resource *release_resources[] = {
GPU_ReleaseResource(ui_shape_verts_buffer, g->render_fence, GPU_ReleaseFlag_Reuse); quad_index_buffer,
GPU_ReleaseResource(ui_shape_indices_buffer, g->render_fence, GPU_ReleaseFlag_Reuse); material_instance_buffer,
GPU_ReleaseResource(grids_buffer, g->render_fence, GPU_ReleaseFlag_Reuse); ui_rect_instance_buffer,
ui_shape_verts_buffer,
ui_shape_indices_buffer,
};
Job *job = OpenJob(ReleaseRenderResources);
{
ReleaseRenderResources_Sig *sig = PushStruct(job->arena, ReleaseRenderResources_Sig);
job->count = countof(resources);
sig->render_counter = g->most_recent_render_counter;
sig->resources = PushStructsNoZero(sig->arena, GPU_Resource *, job->count);
sig->flags = GPU_ReleaseFlag_Reuse;
CopyBytes(sig->resources, resources, sizeof(resources));
job->sig = sig;
}
CloseJob(job);
}
ResetArena(g->material_instances_arena); ResetArena(g->material_instances_arena);
ResetArena(g->ui_rect_instances_arena); ResetArena(g->ui_rect_instances_arena);
ResetArena(g->ui_shape_verts_arena); ResetArena(g->ui_shape_verts_arena);
@ -2437,6 +2457,7 @@ void UpdateUser(P_Window *window)
g->ui_shape_indices_count = 0; g->ui_shape_indices_count = 0;
g->grids_count = 0; g->grids_count = 0;
} }
#endif
} }
EndScratch(scratch); EndScratch(scratch);
@ -2459,7 +2480,7 @@ JobDef(UpdateUserOrSleep, UNUSED sig, UNUSED id)
GPU_WaitOnSwapchain(g->swapchain); GPU_WaitOnSwapchain(g->swapchain);
} }
{ {
__profn("Frame limiter wait");; __profn("Frame limiter wait");
P_SleepFrame(time_ns, 1000000000 / FPS_LIMIT); P_SleepFrame(time_ns, 1000000000 / FPS_LIMIT);
time_ns = TimeNs(); time_ns = TimeNs();
} }

View File

@ -36,7 +36,7 @@ JobDef(S_LoadTexture, sig, _)
} }
texture->loaded = 1; texture->loaded = 1;
AddCounter(&entry->texture_load_counter, -1); SetFence(&entry->texture_ready_fence, 1);
EndScratch(scratch); EndScratch(scratch);
} }
@ -224,7 +224,7 @@ JobDef(S_LoadSheet, sig, _)
} }
sheet->loaded = 1; sheet->loaded = 1;
AddCounter(&entry->sheet_load_counter, -1); SetFence(&entry->sheet_ready_fence, 1);
EndScratch(scratch); EndScratch(scratch);
} }
@ -273,8 +273,6 @@ S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags)
Arena *perm = PermArena(); Arena *perm = PermArena();
entry = PushStruct(perm, S_Entry); entry = PushStruct(perm, S_Entry);
entry->resource = resource; entry->resource = resource;
AddCounter(&entry->texture_load_counter, 1);
AddCounter(&entry->sheet_load_counter, 1);
QueuePushN(bin->first, bin->last, entry, next_in_bin); QueuePushN(bin->first, bin->last, entry, next_in_bin);
} }
} }
@ -303,7 +301,7 @@ S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags)
S_Texture *S_TextureFromResource(Resource resource) S_Texture *S_TextureFromResource(Resource resource)
{ {
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Texture); S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Texture);
YieldOnCounter(&entry->texture_load_counter); YieldOnFence(&entry->texture_ready_fence, 1);
return &entry->texture; return &entry->texture;
} }
@ -311,7 +309,7 @@ S_Texture *S_TextureFromResourceAsync(Resource resource)
{ {
S_Texture *result = &S_NilTexture; S_Texture *result = &S_NilTexture;
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Texture); S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Texture);
if (ValueFromCounter(&entry->texture_load_counter) <= 0) if (FetchFence(&entry->texture_ready_fence) >= 1)
{ {
result = &entry->texture; result = &entry->texture;
} }
@ -321,7 +319,7 @@ S_Texture *S_TextureFromResourceAsync(Resource resource)
S_Sheet *S_SheetFromResource(Resource resource) S_Sheet *S_SheetFromResource(Resource resource)
{ {
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Sheet); S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Sheet);
YieldOnCounter(&entry->sheet_load_counter); YieldOnFence(&entry->sheet_ready_fence, 1);
return &entry->sheet; return &entry->sheet;
} }
@ -329,7 +327,7 @@ S_Sheet *S_SheetFromResourceAsync(Resource resource)
{ {
S_Sheet *result = &S_NilSheet; S_Sheet *result = &S_NilSheet;
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Sheet); S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Sheet);
if (ValueFromCounter(&entry->sheet_load_counter) <= 0) if (FetchFence(&entry->sheet_ready_fence) >= 1)
{ {
result = &entry->sheet; result = &entry->sheet;
} }

View File

@ -109,8 +109,8 @@ Struct(S_Entry)
Atomic32 sheet_touched; Atomic32 sheet_touched;
Resource resource; Resource resource;
Counter texture_load_counter; Fence texture_ready_fence;
Counter sheet_load_counter; Fence sheet_ready_fence;
}; };
Struct(S_EntryBin) Struct(S_EntryBin)