formatting
This commit is contained in:
parent
64dad2457c
commit
2fbaef09ec
@ -135,7 +135,6 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
|
||||
.hash = hash,
|
||||
.key = key_stored
|
||||
};
|
||||
AddCounter(&asset->counter, 1);
|
||||
if (is_first_touch)
|
||||
{
|
||||
*is_first_touch = 1;
|
||||
@ -165,12 +164,12 @@ void AC_MarkReady(AC_Asset *asset, void *store_data)
|
||||
{
|
||||
asset->store_data = store_data;
|
||||
asset->status = ASSET_STATUS_READY;
|
||||
AddCounter(&asset->counter, -1);
|
||||
SetFence(&asset->ready_fence, 1);
|
||||
}
|
||||
|
||||
void AC_YieldOnAssetReady(AC_Asset *asset)
|
||||
{
|
||||
YieldOnCounter(&asset->counter);
|
||||
YieldOnFence(&asset->ready_fence, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@ -17,7 +17,8 @@ Struct(AC_Asset)
|
||||
u64 hash;
|
||||
String key;
|
||||
|
||||
Counter counter;
|
||||
/* Asset is ready when fence >= 1 */
|
||||
Fence ready_fence;
|
||||
|
||||
/* Managed via asset_cache_mark_x functions */
|
||||
AC_Status status;
|
||||
|
||||
@ -545,30 +545,37 @@ StaticAssert(alignof(Atomic32Padded) == CachelineSize && sizeof(Atomic32Padded)
|
||||
StaticAssert(alignof(Atomic64Padded) == CachelineSize && sizeof(Atomic64Padded) % CachelineSize == 0);
|
||||
|
||||
#if PlatformIsWindows && ArchIsX64
|
||||
//- Memory barriers
|
||||
# define CompilerMemoryBarrier() _ReadWriteBarrier()
|
||||
# define HardwareMemoryBarrier() MemoryBarrier()
|
||||
//- 8 bit atomic operations
|
||||
#define Atomic8Fetch(x) (x)->_v
|
||||
#define Atomic8FetchSet(x, e) (i8)_InterlockedExchange8((volatile char *)&(x)->_v, (e))
|
||||
#define Atomic8FetchTestSet(x, c, e) (i8)_InterlockedCompareExchange8((volatile char *)&(x)->_v, (e), (c))
|
||||
#define Atomic8FetchXor(x, c) (i8)_InterlockedXor8((volatile char *)&(x)->_v, (c))
|
||||
#define Atomic8FetchAdd(x, a) (i8)_InterlockedExchangeAdd8((volatile char *)&(x)->_v, (a))
|
||||
ForceInline i8 Atomic8Fetch (Atomic8 *x) { i8 result = (x)->_v; CompilerMemoryBarrier(); return result; }
|
||||
ForceInline void Atomic8Set (Atomic8 *x, i8 e) { CompilerMemoryBarrier(); (x)->_v = e; }
|
||||
ForceInline i8 Atomic8FetchSet (Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((volatile char *)&(x)->_v, (e)); }
|
||||
ForceInline i8 Atomic8FetchTestSet (Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((volatile char *)&(x)->_v, (e), (c)); }
|
||||
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
|
||||
#define Atomic16Fetch(x) (x)->_v
|
||||
#define Atomic16FetchSet(x, e) (i16)_InterlockedExchange16(&(x)->_v, (e))
|
||||
#define Atomic16FetchTestSet(x, c, e) (i16)_InterlockedCompareExchange16(&(x)->_v, (e), (c))
|
||||
#define Atomic16FetchXor(x, c) (i16)_InterlockedXor16(&(x)->_v, (c))
|
||||
#define Atomic16FetchAdd(x, a) (i16)_InterlockedExchangeAdd16(&(x)->_v, (a))
|
||||
ForceInline i16 Atomic16Fetch (Atomic16 *x) { i16 result = (x)->_v; CompilerMemoryBarrier(); return result; }
|
||||
ForceInline void Atomic16Set (Atomic16 *x, i16 e) { CompilerMemoryBarrier(); (x)->_v = e; }
|
||||
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 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
|
||||
#define Atomic32Fetch(x) (x)->_v
|
||||
#define Atomic32FetchSet(x, e) (i32)_InterlockedExchange((volatile long *)&(x)->_v, (e))
|
||||
#define Atomic32FetchTestSet(x, c, e) (i32)_InterlockedCompareExchange((volatile long *)&(x)->_v, (e), (c))
|
||||
#define Atomic32FetchXor(x, c) (i32)_InterlockedXor((volatile long *)&(x)->_v, (c))
|
||||
#define Atomic32FetchAdd(x, a) (i32)_InterlockedExchangeAdd((volatile long *)&(x)->_v, (a))
|
||||
ForceInline i32 Atomic32Fetch (Atomic32 *x) { i32 result = (x)->_v; CompilerMemoryBarrier(); return result; }
|
||||
ForceInline void Atomic32Set (Atomic32 *x, i32 e) { CompilerMemoryBarrier(); (x)->_v = e; }
|
||||
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
|
||||
#define Atomic64Fetch(x) (x)->_v
|
||||
#define Atomic64FetchSet(x, e) (i64)_InterlockedExchange64(&(x)->_v, (e))
|
||||
#define Atomic64FetchTestSet(x, c, e) (i64)_InterlockedCompareExchange64(&(x)->_v, (e), (c))
|
||||
#define Atomic64FetchXor(x, c) (i64)_InterlockedXor64(&(x)->_v, (c))
|
||||
#define Atomic64FetchAdd(x, a) (i64)_InterlockedExchangeAdd64(&(x)->_v, (a))
|
||||
ForceInline i64 Atomic64Fetch (Atomic64 *x) { i16 result = (x)->_v; CompilerMemoryBarrier(); return result; }
|
||||
ForceInline void Atomic64Set (Atomic64 *x, i64 e) { CompilerMemoryBarrier(); (x)->_v = e; }
|
||||
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
|
||||
@ -712,8 +719,8 @@ Struct(ComputeShader) { Resource resource; };
|
||||
# else
|
||||
# error FiberId not implemented
|
||||
# endif
|
||||
# define MaxFibers 1024
|
||||
StaticAssert(MaxFibers < I16Max); /* FiberId type should fit MaxFibers */
|
||||
# define MaxFibers 4096
|
||||
StaticAssert(MaxFibers < I16Max); /* MaxFibers should fit in FiberId */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ Struct(SharedGstatCtx)
|
||||
|
||||
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 GetGstat(name) Atomic64Fetch(&_shared_gstat_ctx.name.v)
|
||||
|
||||
|
||||
@ -12,24 +12,24 @@ Enum(JobPool)
|
||||
{
|
||||
JobPool_Inherit = -1,
|
||||
|
||||
/* Contains worker threads affinitized over the entire CPU.
|
||||
* Meant to take on high-bandwidth temporary work (e.g. loading a level). */
|
||||
JobPool_Hyper = 0, /* High-priority */
|
||||
/* Contains un-affinitized worker threads.
|
||||
* 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,
|
||||
|
||||
/* Contains worker threads affinitized over the entire CPU.
|
||||
* Meant to take on blocking work so that affinitized workers workers can continue doing actual work. */
|
||||
JobPool_Blocking = 1, /* Normal priority */
|
||||
/* Contains un-affinitized worker threads.
|
||||
* Meant to take on blocking work so that affinitized workers can continue doing actual work. */
|
||||
JobPool_Blocking = 1,
|
||||
|
||||
/* Contains worker threads affinitized to cores that don't interfere with workers in specialized 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.
|
||||
* 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). */
|
||||
JobPool_Audio = 3, /* Critical priority */
|
||||
JobPool_User = 4, /* Above-normal priority */
|
||||
JobPool_Sim = 5, /* Above-normal priority */
|
||||
* User pool will not interfere with cores running the Sim pool). */
|
||||
JobPool_Audio = 3,
|
||||
JobPool_User = 4,
|
||||
JobPool_Sim = 5,
|
||||
|
||||
JobPool_Count
|
||||
};
|
||||
@ -37,26 +37,29 @@ Enum(JobPool)
|
||||
////////////////////////////////
|
||||
//~ Job types
|
||||
|
||||
typedef void JobFunc(void *, i32);
|
||||
|
||||
Struct(JobCounter)
|
||||
{
|
||||
Fence jobs_completed_fence;
|
||||
Atomic64Padded num_jobs_dispatched;
|
||||
Fence num_jobs_completed_fence;
|
||||
};
|
||||
|
||||
typedef void JobFunc(void *, i32);
|
||||
|
||||
Struct(Job)
|
||||
{
|
||||
/* Internal */
|
||||
Job *next;
|
||||
Atomic32Padded num_tasks_completed;
|
||||
|
||||
/* Initialized & constant after OpenJob */
|
||||
Arena *arena;
|
||||
JobFunc *func;
|
||||
JobPool pool;
|
||||
|
||||
/* Configurable between OpenJob & CloseJob */
|
||||
i32 count;
|
||||
JobCounter *counter;
|
||||
void *sig;
|
||||
|
||||
Atomic64Padded num_tasks_completed;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@ -112,4 +115,4 @@ do {
|
||||
|
||||
Job *OpenJob(JobFunc *func, JobPool pool_kind);
|
||||
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)))
|
||||
|
||||
@ -56,7 +56,7 @@ Lock LockSpinE(Mutex *m, i32 spin)
|
||||
}
|
||||
|
||||
#if RtcIsEnabled
|
||||
Atomic32FetchSet(&m->exclusive_fiber_id, FiberId());
|
||||
Atomic32Set(&m->exclusive_fiber_id, FiberId());
|
||||
#endif
|
||||
|
||||
Lock lock = ZI;
|
||||
@ -123,9 +123,9 @@ void Unlock(Lock *l)
|
||||
if (l->exclusive)
|
||||
{
|
||||
#if RtcIsEnabled
|
||||
Atomic32FetchSet(&m->exclusive_fiber_id, 0);
|
||||
Atomic32Set(&m->exclusive_fiber_id, 0);
|
||||
#endif
|
||||
Atomic32FetchSet(&m->v, 0);
|
||||
Atomic32Set(&m->v, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -165,34 +165,6 @@ void SignalCv(Cv *cv)
|
||||
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
|
||||
|
||||
@ -201,13 +173,16 @@ i64 FetchFence(Fence *fence)
|
||||
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 fetch = Atomic64FetchSet(&fence->v.v, x);
|
||||
if (x > fetch)
|
||||
{
|
||||
FutexWakeGte(&fence->v.v);
|
||||
}
|
||||
FutexWakeGte(&fence->v.v);
|
||||
return fetch;
|
||||
}
|
||||
|
||||
|
||||
@ -32,15 +32,6 @@ AlignedStruct(Cv, CachelineSize)
|
||||
};
|
||||
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
|
||||
|
||||
@ -75,17 +66,11 @@ void Unlock(Lock *lock);
|
||||
void YieldOnCv(Cv *cv, Lock *lock);
|
||||
void SignalCv(Cv *cv);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Counter operations
|
||||
|
||||
i64 ValueFromCounter(Counter *counter);
|
||||
void AddCounter(Counter *counter, i64 x);
|
||||
void YieldOnCounter(Counter *counter);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Fence operations
|
||||
|
||||
i64 FetchFence(Fence *fence);
|
||||
void SetFence(Fence *fence, i64 x);
|
||||
i64 FetchSetFence(Fence *fence, i64 x);
|
||||
i64 FetchAddFence(Fence *fence, i64 x);
|
||||
|
||||
|
||||
@ -123,7 +123,7 @@ void OnExit(ExitFunc *func)
|
||||
void SignalExit(i32 code)
|
||||
{
|
||||
W32_SharedState *g = &W32_shared_state;
|
||||
Atomic32FetchSet(&g->exit_code, code);
|
||||
Atomic32Set(&g->exit_code, code);
|
||||
SetEvent(g->exit_begin_event);
|
||||
}
|
||||
|
||||
@ -241,13 +241,7 @@ i32 W32_Main(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Query performance frequency */
|
||||
/* Init time */
|
||||
{
|
||||
LARGE_INTEGER qpf;
|
||||
QueryPerformanceFrequency(&qpf);
|
||||
@ -259,6 +253,12 @@ i32 W32_Main(void)
|
||||
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();
|
||||
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
||||
|
||||
|
||||
@ -187,19 +187,6 @@ void W32_WaitEndThread(W32_Thread *thread)
|
||||
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
|
||||
|
||||
@ -334,7 +321,7 @@ void W32_FiberEntryPoint(void *win32_fiber_data)
|
||||
{
|
||||
i16 fiber_id = (i16)(i64)win32_fiber_data;
|
||||
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;
|
||||
char *fiber_name_cstr = fiber->name_cstr;
|
||||
for (;;)
|
||||
@ -349,10 +336,10 @@ void W32_FiberEntryPoint(void *win32_fiber_data)
|
||||
/* Check if we've completed the last task in the job */
|
||||
if (Atomic32FetchAdd(&job->num_tasks_completed.v, 1) + 1 >= job->count)
|
||||
{
|
||||
/* Increment fence */
|
||||
/* Increment counter */
|
||||
if (job->counter)
|
||||
{
|
||||
FetchAddFence(&job->counter->jobs_completed_fence, 1);
|
||||
FetchAddFence(&job->counter->num_jobs_completed_fence, 1);
|
||||
}
|
||||
/* Free job */
|
||||
LockTicketMutex(&pool->free_jobs_tm);
|
||||
@ -387,7 +374,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
|
||||
{
|
||||
W32_WorkerCtx *ctx = worker_ctx_arg;
|
||||
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();
|
||||
|
||||
|
||||
@ -514,7 +501,7 @@ void SuspendFiber(void)
|
||||
Assert(parent_fiber->id > 0);
|
||||
{
|
||||
__prof_fiber_leave();
|
||||
Atomic8FetchSet(&fiber->is_suspending, 1);
|
||||
Atomic8Set(&fiber->is_suspending, 1);
|
||||
W32_SwitchToFiber(parent_fiber);
|
||||
__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)
|
||||
{
|
||||
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;
|
||||
{
|
||||
Arena *job_arena = 0;
|
||||
@ -621,7 +613,7 @@ void CloseJob(Job *job)
|
||||
{
|
||||
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;
|
||||
|
||||
if (num_tasks > 0)
|
||||
@ -684,7 +676,6 @@ void CloseJob(Job *job)
|
||||
{
|
||||
LockTicketMutex(&pool->tasks_tm);
|
||||
{
|
||||
// QueuePush(pool->first_task, pool->last_task, tasks.first);
|
||||
if (pool->last_task)
|
||||
{
|
||||
pool->last_task->next = tasks.first;
|
||||
|
||||
@ -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);
|
||||
void W32_WaitEndThread(W32_Thread *thread);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Pool operations
|
||||
|
||||
W32_JobPool *W32_JobPoolFromKind(JobPool pool_kind);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Fiber operations
|
||||
|
||||
|
||||
@ -283,7 +283,7 @@ GPU_Fence GPU_GetGlobalFence(void);
|
||||
//~ @hookdecl Resource operations
|
||||
|
||||
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);
|
||||
Vec2I32 GPU_GetTextureSize(GPU_Resource *resource);
|
||||
|
||||
@ -110,7 +110,7 @@ GPU_Resource *GPU_AcquireResource(GPU_ResourceDesc desc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GPU_ReleaseResource(GPU_Resource *resource, GPU_Fence fence, GPU_ReleaseFlag flags)
|
||||
void GPU_ReleaseResource(GPU_Resource *resource, GPU_ReleaseFlag flags)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
@ -529,6 +529,7 @@ JobDef(Step, sig, id)
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
JobCounter counter = ZI;
|
||||
RunJob(RunCommand,
|
||||
.count = shader_entries_count,
|
||||
@ -1098,7 +1099,7 @@ JobDef(Build, _, __)
|
||||
EchoLine(msg);
|
||||
}
|
||||
|
||||
|
||||
EchoLine(StringF(arena, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs()))));
|
||||
ExitNow(ret);
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ void P_StartupLog(void)
|
||||
ctx->file_valid = 1;
|
||||
}
|
||||
}
|
||||
Atomic32FetchSet(&ctx->initialized, 1);
|
||||
Atomic32Set(&ctx->initialized, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@ -183,9 +183,8 @@ P_W32_Window *P_W32_AcquireWindow(void)
|
||||
/* 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
|
||||
* 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);
|
||||
YieldOnCounter(&window->ready_fence);
|
||||
YieldOnFence(&window->ready_fence, 1);
|
||||
|
||||
return window;
|
||||
}
|
||||
@ -193,7 +192,7 @@ P_W32_Window *P_W32_AcquireWindow(void)
|
||||
void P_W32_ReleaseWindow(P_W32_Window *window)
|
||||
{
|
||||
/* Stop window threads */
|
||||
Atomic32FetchSet(&window->shutdown, 1);
|
||||
Atomic32Set(&window->shutdown, 1);
|
||||
P_W32_SharedState *g = &P_W32_shared_state;
|
||||
P_W32_WakeWindow(window);
|
||||
W32_WaitEndThread(window->window_thread);
|
||||
@ -400,7 +399,7 @@ W32_ThreadDef(P_W32_WindowThreadEntryFunc, arg)
|
||||
window->hwnd = P_W32_InitWindow(window);
|
||||
P_W32_UpdateWindowFromSystem(window);
|
||||
BringWindowToTop(window->hwnd);
|
||||
AddCounter(&window->ready_fence, -1);
|
||||
SetFence(&window->ready_fence, 1);
|
||||
|
||||
while (!Atomic32Fetch(&window->shutdown))
|
||||
{
|
||||
@ -887,14 +886,13 @@ JobDef(P_W32_UpdateTimer, _, __)
|
||||
periods[i] = P_W32_DefaultTimerPeriodNs;
|
||||
}
|
||||
|
||||
Echo(Lit("Starting timer\n"));
|
||||
|
||||
i64 last_cycle_ns = 0;
|
||||
/* FIXME: shutdown */
|
||||
for (;;)
|
||||
{
|
||||
__profn("Job scheduler cycle");
|
||||
{
|
||||
/* TODO: Minimum timer frequency in case windows timers ever become ultra precise in the future */
|
||||
__profn("Job scheduler wait");
|
||||
LARGE_INTEGER due = ZI;
|
||||
due.QuadPart = -1;
|
||||
@ -922,11 +920,11 @@ JobDef(P_W32_UpdateTimer, _, __)
|
||||
periods_sum_ns += (f64)periods[i];
|
||||
}
|
||||
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 */
|
||||
FetchSetFence(&g->timer_fence, now_ns);
|
||||
SetFence(&g->timer_fence, now_ns);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ Struct(P_W32_Window)
|
||||
u32 flags;
|
||||
|
||||
HWND hwnd;
|
||||
Counter ready_fence;
|
||||
Fence ready_fence;
|
||||
|
||||
u16 utf16_high_surrogate_last_input;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ ExitFuncDef(PB_WSP_Shutdown)
|
||||
{
|
||||
__prof;
|
||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||
Atomic32FetchSet(&g->shutdown, 1);
|
||||
Atomic32Set(&g->shutdown, 1);
|
||||
YieldOnJobs(&g->shutdown_job_counter);
|
||||
}
|
||||
|
||||
|
||||
53
src/pp/pp.c
53
src/pp/pp.c
@ -60,7 +60,7 @@ ExitFuncDef(ShutdownUser)
|
||||
{
|
||||
__prof;
|
||||
SharedUserState *g = &shared_user_state;
|
||||
Atomic32FetchSet(&g->shutdown, 1);
|
||||
Atomic32Set(&g->shutdown, 1);
|
||||
YieldOnJobs(&g->shutdown_job_counter);
|
||||
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)))
|
||||
{
|
||||
__profn("Release render resources");
|
||||
GPU_ReleaseResource(g->albedo, g->render_fence, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->emittance, g->render_fence, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->emittance_flood_read, g->render_fence, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->emittance_flood_target, g->render_fence, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->shade_read, g->render_fence, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->shade_target, g->render_fence, GPU_ReleaseFlag_None);
|
||||
/* FIXME: Yield on render fence */
|
||||
GPU_ReleaseResource(g->albedo, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->emittance, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->emittance_flood_read, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->emittance_flood_target, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->shade_read, GPU_ReleaseFlag_None);
|
||||
GPU_ReleaseResource(g->shade_target, GPU_ReleaseFlag_None);
|
||||
g->shade_target = 0;
|
||||
}
|
||||
if (!g->shade_target)
|
||||
@ -2171,7 +2172,8 @@ void UpdateUser(P_Window *window)
|
||||
/* Acquire ui buffers */
|
||||
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;
|
||||
}
|
||||
if (!g->ui_target)
|
||||
@ -2416,16 +2418,34 @@ void UpdateUser(P_Window *window)
|
||||
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 */
|
||||
{
|
||||
GPU_ReleaseResource(quad_index_buffer, g->render_fence, GPU_ReleaseFlag_Reuse);
|
||||
GPU_ReleaseResource(material_instance_buffer, g->render_fence, GPU_ReleaseFlag_Reuse);
|
||||
GPU_ReleaseResource(ui_rect_instance_buffer, g->render_fence, GPU_ReleaseFlag_Reuse);
|
||||
GPU_ReleaseResource(ui_shape_verts_buffer, g->render_fence, GPU_ReleaseFlag_Reuse);
|
||||
GPU_ReleaseResource(ui_shape_indices_buffer, g->render_fence, GPU_ReleaseFlag_Reuse);
|
||||
GPU_ReleaseResource(grids_buffer, g->render_fence, GPU_ReleaseFlag_Reuse);
|
||||
{
|
||||
/* FIXME: Release resources */
|
||||
GPU_Resource *release_resources[] = {
|
||||
quad_index_buffer,
|
||||
material_instance_buffer,
|
||||
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->ui_rect_instances_arena);
|
||||
ResetArena(g->ui_shape_verts_arena);
|
||||
@ -2437,6 +2457,7 @@ void UpdateUser(P_Window *window)
|
||||
g->ui_shape_indices_count = 0;
|
||||
g->grids_count = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
EndScratch(scratch);
|
||||
@ -2459,7 +2480,7 @@ JobDef(UpdateUserOrSleep, UNUSED sig, UNUSED id)
|
||||
GPU_WaitOnSwapchain(g->swapchain);
|
||||
}
|
||||
{
|
||||
__profn("Frame limiter wait");;
|
||||
__profn("Frame limiter wait");
|
||||
P_SleepFrame(time_ns, 1000000000 / FPS_LIMIT);
|
||||
time_ns = TimeNs();
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ JobDef(S_LoadTexture, sig, _)
|
||||
}
|
||||
|
||||
texture->loaded = 1;
|
||||
AddCounter(&entry->texture_load_counter, -1);
|
||||
SetFence(&entry->texture_ready_fence, 1);
|
||||
EndScratch(scratch);
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ JobDef(S_LoadSheet, sig, _)
|
||||
}
|
||||
|
||||
sheet->loaded = 1;
|
||||
AddCounter(&entry->sheet_load_counter, -1);
|
||||
SetFence(&entry->sheet_ready_fence, 1);
|
||||
EndScratch(scratch);
|
||||
}
|
||||
|
||||
@ -273,8 +273,6 @@ S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags)
|
||||
Arena *perm = PermArena();
|
||||
entry = PushStruct(perm, S_Entry);
|
||||
entry->resource = resource;
|
||||
AddCounter(&entry->texture_load_counter, 1);
|
||||
AddCounter(&entry->sheet_load_counter, 1);
|
||||
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_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Texture);
|
||||
YieldOnCounter(&entry->texture_load_counter);
|
||||
YieldOnFence(&entry->texture_ready_fence, 1);
|
||||
return &entry->texture;
|
||||
}
|
||||
|
||||
@ -311,7 +309,7 @@ S_Texture *S_TextureFromResourceAsync(Resource resource)
|
||||
{
|
||||
S_Texture *result = &S_NilTexture;
|
||||
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;
|
||||
}
|
||||
@ -321,7 +319,7 @@ S_Texture *S_TextureFromResourceAsync(Resource resource)
|
||||
S_Sheet *S_SheetFromResource(Resource resource)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -329,7 +327,7 @@ S_Sheet *S_SheetFromResourceAsync(Resource resource)
|
||||
{
|
||||
S_Sheet *result = &S_NilSheet;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -109,8 +109,8 @@ Struct(S_Entry)
|
||||
Atomic32 sheet_touched;
|
||||
|
||||
Resource resource;
|
||||
Counter texture_load_counter;
|
||||
Counter sheet_load_counter;
|
||||
Fence texture_ready_fence;
|
||||
Fence sheet_ready_fence;
|
||||
};
|
||||
|
||||
Struct(S_EntryBin)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user