job refactor progress
This commit is contained in:
parent
7906108994
commit
63e1412752
@ -29,7 +29,7 @@ void AC_RefreshDebugTable(void)
|
|||||||
{
|
{
|
||||||
#if RtcIsEnabled
|
#if RtcIsEnabled
|
||||||
AC_SharedState *g = &AC_shared_state;
|
AC_SharedState *g = &AC_shared_state;
|
||||||
P_Lock lock = P_LockE(&g->dbg_table_mutex);
|
Lock lock = LockE(&g->dbg_table_mutex);
|
||||||
ZeroArray(g->dbg_table);
|
ZeroArray(g->dbg_table);
|
||||||
g->dbg_table_count = 0;
|
g->dbg_table_count = 0;
|
||||||
for (u64 i = 0; i < countof(g->lookup); ++i)
|
for (u64 i = 0; i < countof(g->lookup); ++i)
|
||||||
@ -40,16 +40,16 @@ void AC_RefreshDebugTable(void)
|
|||||||
g->dbg_table[g->dbg_table_count++] = asset;
|
g->dbg_table[g->dbg_table_count++] = asset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns first matching slot or first empty slot if not found.
|
/* Returns first matching slot or first empty slot if not found.
|
||||||
* Check returned slot->hash != 0 for presence. */
|
* Check returned slot->hash != 0 for presence. */
|
||||||
AC_Asset *AC_GetAssetCacheSlotLocked(P_Lock *lock, String key, u64 hash)
|
AC_Asset *AC_GetAssetCacheSlotLocked(Lock *lock, String key, u64 hash)
|
||||||
{
|
{
|
||||||
AC_SharedState *g = &AC_shared_state;
|
AC_SharedState *g = &AC_shared_state;
|
||||||
P_AssertLockedES(lock, &g->lookup_mutex);
|
AssertLockedES(lock, &g->lookup_mutex);
|
||||||
LAX lock;
|
LAX lock;
|
||||||
|
|
||||||
u64 index = hash % countof(g->lookup);
|
u64 index = hash % countof(g->lookup);
|
||||||
@ -96,9 +96,9 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
|
|||||||
|
|
||||||
/* Lookup */
|
/* Lookup */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockS(&g->lookup_mutex);
|
Lock lock = LockS(&g->lookup_mutex);
|
||||||
asset = AC_GetAssetCacheSlotLocked(&lock, key, hash);
|
asset = AC_GetAssetCacheSlotLocked(&lock, key, hash);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert if not found */
|
/* Insert if not found */
|
||||||
@ -111,7 +111,7 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->lookup_mutex);
|
Lock lock = LockE(&g->lookup_mutex);
|
||||||
|
|
||||||
/* Re-check asset presence in case it was inserted since lock */
|
/* Re-check asset presence in case it was inserted since lock */
|
||||||
asset = AC_GetAssetCacheSlotLocked(&lock, key, hash);
|
asset = AC_GetAssetCacheSlotLocked(&lock, key, hash);
|
||||||
@ -136,7 +136,7 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
|
|||||||
.hash = hash,
|
.hash = hash,
|
||||||
.key = key_stored
|
.key = key_stored
|
||||||
};
|
};
|
||||||
P_CounterAdd(&asset->counter, 1);
|
AddCounter(&asset->counter, 1);
|
||||||
if (is_first_touch)
|
if (is_first_touch)
|
||||||
{
|
{
|
||||||
*is_first_touch = 1;
|
*is_first_touch = 1;
|
||||||
@ -146,7 +146,7 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
|
|||||||
AC_RefreshDebugTable();
|
AC_RefreshDebugTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return asset;
|
return asset;
|
||||||
@ -166,12 +166,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;
|
||||||
P_CounterAdd(&asset->counter, -1);
|
AddCounter(&asset->counter, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AC_WaitOnAssetReady(AC_Asset *asset)
|
void AC_WaitOnAssetReady(AC_Asset *asset)
|
||||||
{
|
{
|
||||||
P_WaitOnCounter(&asset->counter);
|
WaitOnCounter(&asset->counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -193,7 +193,7 @@ void *AC_DataFromStore(AC_Asset *asset)
|
|||||||
AC_Store AC_OpenStore(void)
|
AC_Store AC_OpenStore(void)
|
||||||
{
|
{
|
||||||
AC_SharedState *g = &AC_shared_state;
|
AC_SharedState *g = &AC_shared_state;
|
||||||
P_Lock lock = P_LockE(&g->store_mutex);
|
Lock lock = LockE(&g->store_mutex);
|
||||||
AC_Store store = {
|
AC_Store store = {
|
||||||
.lock = lock,
|
.lock = lock,
|
||||||
.arena = g->store_arena
|
.arena = g->store_arena
|
||||||
@ -203,5 +203,5 @@ AC_Store AC_OpenStore(void)
|
|||||||
|
|
||||||
void AC_CloseStore(AC_Store *store)
|
void AC_CloseStore(AC_Store *store)
|
||||||
{
|
{
|
||||||
P_Unlock(&store->lock);
|
Unlock(&store->lock);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ Struct(AC_Store)
|
|||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
P_Lock lock;
|
Lock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -45,18 +45,18 @@ Struct(AC_Store)
|
|||||||
|
|
||||||
Struct(AC_SharedState)
|
Struct(AC_SharedState)
|
||||||
{
|
{
|
||||||
P_Mutex lookup_mutex;
|
Mutex lookup_mutex;
|
||||||
AC_Asset lookup[AC_AssetLookupTableCapacity];
|
AC_Asset lookup[AC_AssetLookupTableCapacity];
|
||||||
u64 num_assets;
|
u64 num_assets;
|
||||||
|
|
||||||
P_Mutex store_mutex;
|
Mutex store_mutex;
|
||||||
Arena *store_arena;
|
Arena *store_arena;
|
||||||
|
|
||||||
#if RtcIsEnabled
|
#if RtcIsEnabled
|
||||||
/* Array of len `num_assets` pointing into populated entries of `lookup`. */
|
/* Array of len `num_assets` pointing into populated entries of `lookup`. */
|
||||||
AC_Asset *dbg_table[AC_AssetLookupTableCapacity];
|
AC_Asset *dbg_table[AC_AssetLookupTableCapacity];
|
||||||
u64 dbg_table_count;
|
u64 dbg_table_count;
|
||||||
P_Mutex dbg_table_mutex;
|
Mutex dbg_table_mutex;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ u64 AC_HashFromKey(String key);
|
|||||||
//~ Cache operations
|
//~ Cache operations
|
||||||
|
|
||||||
void AC_RefreshDebugTable(void);
|
void AC_RefreshDebugTable(void);
|
||||||
AC_Asset *AC_GetAssetCacheSlotLocked(P_Lock *lock, String key, u64 hash);
|
AC_Asset *AC_GetAssetCacheSlotLocked(Lock *lock, String key, u64 hash);
|
||||||
AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch);
|
AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
@ -10,9 +10,10 @@
|
|||||||
#include "base_uid.c"
|
#include "base_uid.c"
|
||||||
#include "base_uni.c"
|
#include "base_uni.c"
|
||||||
#include "base_incbin.c"
|
#include "base_incbin.c"
|
||||||
|
#include "base_snc.c"
|
||||||
|
|
||||||
#if PlatformIsWindows
|
#if PlatformIsWindows
|
||||||
# include "win32/base_win32.c"
|
# include "win32/base_win32.c"
|
||||||
#else
|
#else
|
||||||
# error Base layer platform backend not implemented
|
# error Base layer platform backend not implemented
|
||||||
#enidf
|
#endif
|
||||||
|
|||||||
@ -8,8 +8,9 @@
|
|||||||
#include "../prof/prof.h"
|
#include "../prof/prof.h"
|
||||||
# include "base_intrinsics.h"
|
# include "base_intrinsics.h"
|
||||||
# include "base_memory.h"
|
# include "base_memory.h"
|
||||||
# include "base_job.h"
|
|
||||||
# include "base_arena.h"
|
# include "base_arena.h"
|
||||||
|
# include "base_snc.h"
|
||||||
|
# include "base_job.h"
|
||||||
# include "base_uid.h"
|
# include "base_uid.h"
|
||||||
# include "base_string.h"
|
# include "base_string.h"
|
||||||
# include "base_uni.h"
|
# include "base_uni.h"
|
||||||
|
|||||||
@ -548,6 +548,23 @@ ForceInline void UnlockTicketMutex(TicketMutex *tm)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Fibers
|
||||||
|
|
||||||
|
#define MaxFibers 4096
|
||||||
|
|
||||||
|
#if !LanguageIsGpu
|
||||||
|
ForceInline i16 FiberId(void)
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
//return (i16)(i64)GetFiberData();
|
||||||
|
Assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
StaticAssert(MaxFibers < I16Max); /* Fiber id type should fit max fibers */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Config
|
//~ Config
|
||||||
|
|
||||||
|
|||||||
@ -33,30 +33,59 @@ typedef i32 PriorityKind; enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl Fiber helpers
|
//~ @hookdecl Futex
|
||||||
|
|
||||||
#define MaxFibers 4096
|
/* Futex-like wait & wake */
|
||||||
|
void FutexWait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns);
|
||||||
i16 FiberId(void);
|
void FutexWake(void *addr, i32 count);
|
||||||
StaticAssert(MaxFibers < I16Max); /* Fiber id type should fit max fibers */
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl Job helpers
|
//~ @hookdecl Job helpers
|
||||||
|
|
||||||
#define EmptySig { i32 _; }
|
#define EmptySig { i32 _; }
|
||||||
|
|
||||||
|
typedef void GenericJobFunc(void *, i32);
|
||||||
|
|
||||||
|
Struct(GenericJobDesc)
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
void *sig;
|
||||||
|
GenericJobFunc *func;
|
||||||
|
i32 count;
|
||||||
|
PoolKind pool;
|
||||||
|
PriorityKind priority;
|
||||||
|
Counter *counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(JobDescParams)
|
||||||
|
{
|
||||||
|
i32 count;
|
||||||
|
PoolKind pool;
|
||||||
|
PriorityKind priority;
|
||||||
|
Counter *counter;
|
||||||
|
};
|
||||||
|
|
||||||
#define JobDecl(job, sigdef) \
|
#define JobDecl(job, sigdef) \
|
||||||
typedef struct job##_Sig sigdef job##_Sig; \
|
typedef struct job##_Sig sigdef job##_Sig; \
|
||||||
Struct(job##_Desc) { Counter *counter; Arena *job_arena; job##_Sig *sig; }; \
|
Struct(job##_Desc) { Arena *arena; job##_Sig *sig; GenericJobFunc *func; i32 count; PoolKind pool; PriorityKind priority; Counter *counter;}; \
|
||||||
void job(job##_Sig *)
|
void job(job##_Sig *, i32)
|
||||||
|
|
||||||
#define JobDef(job, sig_arg) void job(job##_Sig *sig_arg)
|
#define PushJobDesc(job, ...) (job##_Desc *)PushJobDesc_(sizeof(job##_Sig), alignof(job##_Sig), (GenericJobFunc *)(i64)job, (JobDescParams) { .count = 1, .pool = PoolKind_Inherit, .priority = PriorityKind_Inherit, .counter = 0, __VA_ARGS__ })
|
||||||
|
GenericJobDesc *PushJobDesc_(u64 sig_size, u64 sig_align, GenericJobFunc *func, JobDescParams params);
|
||||||
|
|
||||||
#define RunJob(job, desc) job(&desc->sig)
|
#define JobDef(job, sig_arg, id_arg) void job(job##_Sig *sig_arg, i32 id_arg)
|
||||||
|
|
||||||
|
#define RunJob(_count, job, _pool, _priority, _counter, ...) do { \
|
||||||
|
job##_Desc *__job_desc = (job##_Desc *)PushJobDesc_(sizeof(job##_Sig), alignof(job##_Sig), (GenericJobFunc *)(i64)job, (JobDescParams) { .count = _count, .pool = _pool, .priority = _priority, .counter = _counter,}); \
|
||||||
|
*__job_desc->sig = (job##_Sig) { __VA_ARGS__ }; \
|
||||||
|
} while (0)
|
||||||
|
void RunJobEx(GenericJobDesc *desc);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl Wait
|
//~ @hookdecl Helpers
|
||||||
|
|
||||||
/* Futex-like wait & wake */
|
i64 TimeNs(void);
|
||||||
void P_Wait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns);
|
|
||||||
void P_Wake(void *addr, i32 count);
|
u32 GetLogicalProcessorCount(void);
|
||||||
|
u32 ThreadId(void);
|
||||||
|
i64 GetCurrentSchedulerPeriodNs(void);
|
||||||
|
|||||||
@ -2,8 +2,10 @@
|
|||||||
//~ True randomness
|
//~ True randomness
|
||||||
|
|
||||||
#if PlatformIsWindows
|
#if PlatformIsWindows
|
||||||
|
#if 0
|
||||||
# define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
# define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
||||||
u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
||||||
|
#endif
|
||||||
void TrueRand(String buffer)
|
void TrueRand(String buffer)
|
||||||
{
|
{
|
||||||
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
//~ Mutex
|
//~ Mutex
|
||||||
|
|
||||||
//- Exclusive mutex lock
|
//- Exclusive mutex lock
|
||||||
P_Lock P_LockSpinE(P_Mutex *m, i32 spin)
|
Lock LockSpinE(Mutex *m, i32 spin)
|
||||||
{
|
{
|
||||||
b32 locked = 0;
|
b32 locked = 0;
|
||||||
i32 spin_cnt = 0;
|
i32 spin_cnt = 0;
|
||||||
@ -49,7 +49,7 @@ P_Lock P_LockSpinE(P_Mutex *m, i32 spin)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
P_Wait(&m->v, &v, 4, I64Max);
|
FutexWait(&m->v, &v, 4, I64Max);
|
||||||
spin_cnt = 0;
|
spin_cnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,14 +59,14 @@ P_Lock P_LockSpinE(P_Mutex *m, i32 spin)
|
|||||||
Atomic32FetchSet(&m->exclusive_fiber_id, FiberId());
|
Atomic32FetchSet(&m->exclusive_fiber_id, FiberId());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
P_Lock lock = ZI;
|
Lock lock = ZI;
|
||||||
lock.exclusive = 1;
|
lock.exclusive = 1;
|
||||||
lock.mutex = m;
|
lock.mutex = m;
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Shared mutex lock
|
//- Shared mutex lock
|
||||||
P_Lock P_LockSpinS(P_Mutex *m, i32 spin)
|
Lock LockSpinS(Mutex *m, i32 spin)
|
||||||
{
|
{
|
||||||
b32 locked = 0;
|
b32 locked = 0;
|
||||||
i32 spin_cnt = 0;
|
i32 spin_cnt = 0;
|
||||||
@ -96,30 +96,30 @@ P_Lock P_LockSpinS(P_Mutex *m, i32 spin)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
P_Wait(&m->v, &v, 4, I64Max);
|
FutexWait(&m->v, &v, 4, I64Max);
|
||||||
spin_cnt = 0;
|
spin_cnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Lock lock = ZI;
|
Lock lock = ZI;
|
||||||
lock.mutex = m;
|
lock.mutex = m;
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Mutex lock wrappers
|
//- Mutex lock wrappers
|
||||||
P_Lock P_LockE(P_Mutex *m)
|
Lock LockE(Mutex *m)
|
||||||
{
|
{
|
||||||
return P_LockSpinE(m, P_DefaultMutexSpin);
|
return LockSpinE(m, DefaultMutexSpin);
|
||||||
}
|
}
|
||||||
|
|
||||||
P_Lock P_LockS(P_Mutex *m)
|
Lock LockS(Mutex *m)
|
||||||
{
|
{
|
||||||
return P_LockSpinS(m, P_DefaultMutexSpin);
|
return LockSpinS(m, DefaultMutexSpin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_Unlock(P_Lock *l)
|
void Unlock(Lock *l)
|
||||||
{
|
{
|
||||||
P_Mutex *m = l->mutex;
|
Mutex *m = l->mutex;
|
||||||
if (l->exclusive)
|
if (l->exclusive)
|
||||||
{
|
{
|
||||||
#if RtcIsEnabled
|
#if RtcIsEnabled
|
||||||
@ -131,64 +131,64 @@ void P_Unlock(P_Lock *l)
|
|||||||
{
|
{
|
||||||
Atomic32FetchAdd(&m->v, -1);
|
Atomic32FetchAdd(&m->v, -1);
|
||||||
}
|
}
|
||||||
P_Wake(&m->v, I32Max);
|
FutexWake(&m->v, I32Max);
|
||||||
ZeroStruct(l);
|
ZeroStruct(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Condition variable
|
//~ Condition variable
|
||||||
|
|
||||||
void P_WaitOnCv(P_Cv *cv, P_Lock *l)
|
void WaitOnCv(Cv *cv, Lock *l)
|
||||||
{
|
{
|
||||||
P_WaitOnCvTime(cv, l, I64Max);
|
WaitOnCvTime(cv, l, I64Max);
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_WaitOnCvTime(P_Cv *cv, P_Lock *l, i64 timeout_ns)
|
void WaitOnCvTime(Cv *cv, Lock *l, i64 timeout_ns)
|
||||||
{
|
{
|
||||||
u64 old_wake_gen = Atomic64Fetch(&cv->wake_gen);
|
u64 old_wake_gen = Atomic64Fetch(&cv->wake_gen);
|
||||||
P_Mutex *mutex = l->mutex;
|
Mutex *mutex = l->mutex;
|
||||||
b32 exclusive = l->exclusive;
|
b32 exclusive = l->exclusive;
|
||||||
{
|
{
|
||||||
P_Unlock(l);
|
Unlock(l);
|
||||||
{
|
{
|
||||||
P_Wait(&cv->wake_gen, &old_wake_gen, sizeof(old_wake_gen), timeout_ns);
|
FutexWait(&cv->wake_gen, &old_wake_gen, sizeof(old_wake_gen), timeout_ns);
|
||||||
}
|
}
|
||||||
if (exclusive)
|
if (exclusive)
|
||||||
{
|
{
|
||||||
*l = P_LockE(mutex);
|
*l = LockE(mutex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*l = P_LockS(mutex);
|
*l = LockS(mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_SignalCv(P_Cv *cv, i32 count)
|
void SignalCv(Cv *cv, i32 count)
|
||||||
{
|
{
|
||||||
Atomic64FetchAdd(&cv->wake_gen, 1);
|
Atomic64FetchAdd(&cv->wake_gen, 1);
|
||||||
P_Wake(&cv->wake_gen, count);
|
FutexWake(&cv->wake_gen, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Counter
|
//~ Counter
|
||||||
|
|
||||||
void P_CounterAdd(Counter *counter, i64 x)
|
void AddCounter(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;
|
||||||
if (old_v > 0 && new_v <= 0)
|
if (old_v > 0 && new_v <= 0)
|
||||||
{
|
{
|
||||||
P_Wake(&counter->v, I32Max);
|
FutexWake(&counter->v, I32Max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_WaitOnCounter(Counter *counter)
|
void WaitOnCounter(Counter *counter)
|
||||||
{
|
{
|
||||||
i64 v = Atomic64Fetch(&counter->v);
|
i64 v = Atomic64Fetch(&counter->v);
|
||||||
while (v > 0)
|
while (v > 0)
|
||||||
{
|
{
|
||||||
P_Wait(&counter->v, &v, sizeof(v), I64Max);
|
FutexWait(&counter->v, &v, sizeof(v), I64Max);
|
||||||
v = Atomic64Fetch(&counter->v);
|
v = Atomic64Fetch(&counter->v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
83
src/base/base_snc.h
Normal file
83
src/base/base_snc.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
////////////////////////////////
|
||||||
|
//~ Mutex types
|
||||||
|
|
||||||
|
#define DefaultMutexSpin 4000
|
||||||
|
|
||||||
|
AlignedStruct(Mutex, 64)
|
||||||
|
{
|
||||||
|
/* Bit 31 = Exclusive lock is held
|
||||||
|
* Bit 30 = Exclusive lock is pending
|
||||||
|
* Bit 0-30 = Shared locks count
|
||||||
|
*/
|
||||||
|
Atomic32 v;
|
||||||
|
|
||||||
|
#if RtcIsEnabled
|
||||||
|
Atomic32 exclusive_fiber_id;
|
||||||
|
u8 _pad[56];
|
||||||
|
#else
|
||||||
|
u8 _pad[60];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
StaticAssert(sizeof(Mutex) == 64); /* Padding validation */
|
||||||
|
StaticAssert(alignof(Mutex) == 64); /* Prevent false sharing */
|
||||||
|
|
||||||
|
Struct(Lock)
|
||||||
|
{
|
||||||
|
Mutex *mutex;
|
||||||
|
b32 exclusive;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Condition variable types
|
||||||
|
|
||||||
|
AlignedStruct(Cv, 64)
|
||||||
|
{
|
||||||
|
Atomic64 wake_gen;
|
||||||
|
u8 _pad[56];
|
||||||
|
};
|
||||||
|
StaticAssert(sizeof(Cv) == 64); /* Padding validation */
|
||||||
|
StaticAssert(alignof(Cv) == 64); /* Prevent false sharing */
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Counter types
|
||||||
|
|
||||||
|
AlignedStruct(Counter, 64)
|
||||||
|
{
|
||||||
|
Atomic64 v;
|
||||||
|
u8 _pad[56];
|
||||||
|
};
|
||||||
|
StaticAssert(sizeof(Counter) == 64); /* Padding validation */
|
||||||
|
StaticAssert(alignof(Counter) == 64); /* Prevent false sharing */
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Mutex operations
|
||||||
|
|
||||||
|
Lock LockSpinE(Mutex *m, i32 spin);
|
||||||
|
Lock LockSpinS(Mutex *m, i32 spin);
|
||||||
|
|
||||||
|
Lock LockE(Mutex *m);
|
||||||
|
Lock LockS(Mutex *m);
|
||||||
|
|
||||||
|
void Unlock(Lock *lock);
|
||||||
|
|
||||||
|
//- Lock assertion
|
||||||
|
#if RtcIsEnabled
|
||||||
|
# define AssertLockedE(l, m) Assert((l)->mutex == (m) && (l)->exclusive == 1)
|
||||||
|
# define AssertLockedES(l, m) Assert((l)->mutex == (m))
|
||||||
|
#else
|
||||||
|
# define AssertLockedE(l, m) LAX l
|
||||||
|
# define AssertLockedES(l, m) LAX l
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Condition variable operations
|
||||||
|
|
||||||
|
void WaitOnCv(Cv *cv, Lock *lock);
|
||||||
|
void WaitOnCvTime(Cv *cv, Lock *l, i64 timeout_ns);
|
||||||
|
void SignalCv(Cv *cv, i32 count);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Counter operations
|
||||||
|
|
||||||
|
void AddCounter(Counter *counter, i64 x);
|
||||||
|
void WaitOnCounter(Counter *counter);
|
||||||
@ -63,12 +63,12 @@ String StringFromI64(Arena *arena, i64 n, u64 base, u64 zfill)
|
|||||||
u8 len = 0;
|
u8 len = 0;
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
/* PushStruct sign */
|
/* Push sign */
|
||||||
StringFromChar(arena, '-');
|
StringFromChar(arena, '-');
|
||||||
len = 1;
|
len = 1;
|
||||||
n = -n;
|
n = -n;
|
||||||
}
|
}
|
||||||
/* PushStruct unsigned number */
|
/* Push unsigned number */
|
||||||
String uint_str = StringFromU64(arena, n, base, zfill);
|
String uint_str = StringFromU64(arena, n, base, zfill);
|
||||||
return (String)
|
return (String)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
W32_SharedCtx W32_shared_ctx = ZI;
|
W32_SharedCtx W32_shared_ctx = ZI;
|
||||||
|
|
||||||
|
/* FIXME: Enable logs, panic, shutdown */
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Win32 libs
|
//~ Win32 libs
|
||||||
|
|
||||||
@ -21,6 +23,19 @@ void StartupJobs(void)
|
|||||||
{
|
{
|
||||||
W32_SharedCtx *g = &W32_shared_ctx;
|
W32_SharedCtx *g = &W32_shared_ctx;
|
||||||
|
|
||||||
|
/* Init timer */
|
||||||
|
{
|
||||||
|
LARGE_INTEGER qpf;
|
||||||
|
QueryPerformanceFrequency(&qpf);
|
||||||
|
g->ns_per_qpc = 1000000000 / qpf.QuadPart;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
LARGE_INTEGER qpc;
|
||||||
|
QueryPerformanceCounter(&qpc);
|
||||||
|
g->timer_start_qpc = qpc.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Init fibers */
|
/* Init fibers */
|
||||||
g->num_fibers = 1; /* Fiber at index 0 always nil */
|
g->num_fibers = 1; /* Fiber at index 0 always nil */
|
||||||
g->fiber_names_arena = AllocArena(Gibi(64));
|
g->fiber_names_arena = AllocArena(Gibi(64));
|
||||||
@ -47,6 +62,7 @@ void StartupJobs(void)
|
|||||||
/* Start job scheduler */
|
/* Start job scheduler */
|
||||||
Atomic64FetchSet(&g->current_scheduler_cycle_period_ns.v, W32_DefaultSchedulerPeriodNs);
|
Atomic64FetchSet(&g->current_scheduler_cycle_period_ns.v, W32_DefaultSchedulerPeriodNs);
|
||||||
W32_Thread *scheduler_thread = W32_AllocThread(W32_JobSchedulerEntryFunc, 0, Lit("Scheduler thread"), PROF_THREAD_GROUP_SCHEDULER);
|
W32_Thread *scheduler_thread = W32_AllocThread(W32_JobSchedulerEntryFunc, 0, Lit("Scheduler thread"), PROF_THREAD_GROUP_SCHEDULER);
|
||||||
|
LAX scheduler_thread;
|
||||||
|
|
||||||
//- Start job workers
|
//- Start job workers
|
||||||
/* TODO: Heuristic worker counts & affinities */
|
/* TODO: Heuristic worker counts & affinities */
|
||||||
@ -114,12 +130,12 @@ void StartupJobs(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
P_OnExit(ShutdownJobs);
|
//P_OnExit(ShutdownJobs);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Shutdown
|
//~ Shutdown
|
||||||
|
#if 0
|
||||||
void ShutdownJobs(void)
|
void ShutdownJobs(void)
|
||||||
{
|
{
|
||||||
/* Signal shutdown */
|
/* Signal shutdown */
|
||||||
@ -162,7 +178,7 @@ void ShutdownJobs(void)
|
|||||||
/* Find any dangling threads that haven't exited gracefully by now */
|
/* Find any dangling threads that haven't exited gracefully by now */
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockS(&g->threads_mutex);
|
LockTicketMutex(&g->threads_tm);
|
||||||
if (g->first_thread)
|
if (g->first_thread)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
@ -176,29 +192,13 @@ void ShutdownJobs(void)
|
|||||||
++num_dangling_threads;
|
++num_dangling_threads;
|
||||||
}
|
}
|
||||||
threads_msg = StringFormat(scratch.arena, Lit("%F dangling thread(s):\n%F"), FmtUint(num_dangling_threads), FmtString(threads_msg));
|
threads_msg = StringFormat(scratch.arena, Lit("%F dangling thread(s):\n%F"), FmtUint(num_dangling_threads), FmtString(threads_msg));
|
||||||
P_Panic(threads_msg);
|
//P_Panic(threads_msg);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
UnlockTicketMutex(&g->threads_tm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
////////////////////////////////
|
|
||||||
//~ Win32 ticket mutex
|
|
||||||
|
|
||||||
void LockTicketMutex(W32_TicketMutex *tm)
|
|
||||||
{
|
|
||||||
i64 ticket = Atomic64FetchAdd(&tm->ticket.v, 1);
|
|
||||||
while (Atomic64Fetch(&tm->serving.v) != ticket)
|
|
||||||
{
|
|
||||||
_mm_pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnlockTicketMutex(W32_TicketMutex *tm)
|
|
||||||
{
|
|
||||||
Atomic64FetchAdd(&tm->serving.v, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Win32 thread
|
//~ Win32 thread
|
||||||
@ -219,7 +219,7 @@ DWORD WINAPI W32_Win32ThreadProc(LPVOID vt)
|
|||||||
SetThreadDescription(GetCurrentThread(), t->thread_name_wstr);
|
SetThreadDescription(GetCurrentThread(), t->thread_name_wstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
P_LogInfoF("New thread \"%F\" created with ID %F", FmtString(StringFromCstrNoLimit(t->thread_name_cstr)), FmtUint(P_GetThreadId()));
|
//P_LogInfoF("New thread \"%F\" created with ID %F", FmtString(StringFromCstrNoLimit(t->thread_name_cstr)), FmtUint(ThreadId()));
|
||||||
|
|
||||||
/* Enter thread entry point */
|
/* Enter thread entry point */
|
||||||
t->entry_point(t->thread_data);
|
t->entry_point(t->thread_data);
|
||||||
@ -236,12 +236,12 @@ W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, Stri
|
|||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
W32_SharedCtx *g = &W32_shared_ctx;
|
W32_SharedCtx *g = &W32_shared_ctx;
|
||||||
Assert(entry_point != 0);
|
Assert(entry_point != 0);
|
||||||
P_LogInfoF("Creating thread \"%F\"", FmtString(thread_name));
|
//P_LogInfoF("Creating thread \"%F\"", FmtString(thread_name));
|
||||||
|
|
||||||
/* Allocate thread object */
|
/* Allocate thread object */
|
||||||
W32_Thread *t = 0;
|
W32_Thread *t = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->threads_mutex);
|
LockTicketMutex(&g->threads_tm);
|
||||||
if (g->first_free_thread)
|
if (g->first_free_thread)
|
||||||
{
|
{
|
||||||
t = g->first_free_thread;
|
t = g->first_free_thread;
|
||||||
@ -262,7 +262,7 @@ W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, Stri
|
|||||||
g->first_thread = t;
|
g->first_thread = t;
|
||||||
}
|
}
|
||||||
g->last_thread = t;
|
g->last_thread = t;
|
||||||
P_Unlock(&lock);
|
UnlockTicketMutex(&g->threads_tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
t->entry_point = entry_point;
|
t->entry_point = entry_point;
|
||||||
@ -293,7 +293,7 @@ W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, Stri
|
|||||||
|
|
||||||
if (!t->handle)
|
if (!t->handle)
|
||||||
{
|
{
|
||||||
P_Panic(Lit("Failed to create thread"));
|
//P_Panic(Lit("Failed to create thread"));
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
@ -319,7 +319,7 @@ b32 W32_TryReleaseThread(W32_Thread *thread, f32 timeout_seconds)
|
|||||||
success = 1;
|
success = 1;
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->threads_mutex);
|
LockTicketMutex(&g->threads_tm);
|
||||||
{
|
{
|
||||||
W32_Thread *prev = t->prev;
|
W32_Thread *prev = t->prev;
|
||||||
W32_Thread *next = t->next;
|
W32_Thread *next = t->next;
|
||||||
@ -342,7 +342,7 @@ b32 W32_TryReleaseThread(W32_Thread *thread, f32 timeout_seconds)
|
|||||||
t->next = g->first_free_thread;
|
t->next = g->first_free_thread;
|
||||||
g->first_free_thread = t;
|
g->first_free_thread = t;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
UnlockTicketMutex(&g->threads_tm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -710,30 +710,30 @@ W32_Fiber *W32_AllocFiber(W32_JobPool *pool)
|
|||||||
{
|
{
|
||||||
if (pool != 0)
|
if (pool != 0)
|
||||||
{
|
{
|
||||||
LockTicketMutex(&pool->free_fibers_lock);
|
LockTicketMutex(&pool->free_fibers_tm);
|
||||||
if (pool->first_free_fiber_id)
|
if (pool->first_free_fiber_id)
|
||||||
{
|
{
|
||||||
fiber_id = pool->first_free_fiber_id;
|
fiber_id = pool->first_free_fiber_id;
|
||||||
fiber = &g->fibers[fiber_id];
|
fiber = &g->fibers[fiber_id];
|
||||||
pool->first_free_fiber_id = fiber->parent_id;
|
pool->first_free_fiber_id = fiber->parent_id;
|
||||||
}
|
}
|
||||||
UnlockTicketMutex(&pool->free_fibers_lock);
|
UnlockTicketMutex(&pool->free_fibers_tm);
|
||||||
}
|
}
|
||||||
if (!fiber_id)
|
if (!fiber_id)
|
||||||
{
|
{
|
||||||
LockTicketMutex(&g->fibers_lock);
|
LockTicketMutex(&g->fibers_tm);
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
fiber_id = g->num_fibers++;
|
fiber_id = g->num_fibers++;
|
||||||
if (fiber_id >= MaxFibers)
|
if (fiber_id >= MaxFibers)
|
||||||
{
|
{
|
||||||
P_Panic(Lit("Max fibers reached"));
|
//P_Panic(Lit("Max fibers reached"));
|
||||||
}
|
}
|
||||||
fiber = &g->fibers[fiber_id];
|
fiber = &g->fibers[fiber_id];
|
||||||
new_name_cstr = PushStructs(g->fiber_names_arena, char, W32_FiberNameMaxSize);
|
new_name_cstr = PushStructs(g->fiber_names_arena, char, W32_FiberNameMaxSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UnlockTicketMutex(&g->fibers_lock);
|
UnlockTicketMutex(&g->fibers_tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -809,13 +809,13 @@ W32_Fiber *W32_AllocFiber(W32_JobPool *pool)
|
|||||||
//- Release fiber
|
//- Release fiber
|
||||||
void W32_ReleaseFiber(W32_JobPool *pool, W32_Fiber *fiber)
|
void W32_ReleaseFiber(W32_JobPool *pool, W32_Fiber *fiber)
|
||||||
{
|
{
|
||||||
LockTicketMutex(&pool->free_fibers_lock);
|
LockTicketMutex(&pool->free_fibers_tm);
|
||||||
{
|
{
|
||||||
i16 fiber_id = fiber->id;
|
i16 fiber_id = fiber->id;
|
||||||
fiber->parent_id = pool->first_free_fiber_id;
|
fiber->parent_id = pool->first_free_fiber_id;
|
||||||
pool->first_free_fiber_id = fiber_id;
|
pool->first_free_fiber_id = fiber_id;
|
||||||
}
|
}
|
||||||
UnlockTicketMutex(&pool->free_fibers_lock);
|
UnlockTicketMutex(&pool->free_fibers_tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -855,6 +855,7 @@ void W32_YieldFiber(W32_Fiber *fiber, W32_Fiber *parent_fiber)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- Fiber entry
|
//- Fiber entry
|
||||||
|
|
||||||
void W32_FiberEntryPoint(void *id_ptr)
|
void W32_FiberEntryPoint(void *id_ptr)
|
||||||
{
|
{
|
||||||
i16 id = (i32)(i64)id_ptr;
|
i16 id = (i32)(i64)id_ptr;
|
||||||
@ -866,12 +867,10 @@ void W32_FiberEntryPoint(void *id_ptr)
|
|||||||
{
|
{
|
||||||
W32_YieldParam *yield_param = fiber->yield_param;
|
W32_YieldParam *yield_param = fiber->yield_param;
|
||||||
yield_param->kind = W32_YieldKind_None;
|
yield_param->kind = W32_YieldKind_None;
|
||||||
P_JobData data = ZI;
|
|
||||||
data.id = fiber->job_id;
|
|
||||||
data.sig = fiber->job_sig;
|
|
||||||
{
|
{
|
||||||
MemoryBarrier();
|
MemoryBarrier();
|
||||||
fiber->job_func(data);
|
GenericJobFunc *job_func = fiber->job_func;
|
||||||
|
job_func(fiber->job_sig, fiber->job_id);
|
||||||
MemoryBarrier();
|
MemoryBarrier();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -881,7 +880,7 @@ void W32_FiberEntryPoint(void *id_ptr)
|
|||||||
Counter *job_counter = fiber->job_counter;
|
Counter *job_counter = fiber->job_counter;
|
||||||
if (job_counter)
|
if (job_counter)
|
||||||
{
|
{
|
||||||
P_CounterAdd(job_counter, -1);
|
AddCounter(job_counter, -1);
|
||||||
}
|
}
|
||||||
/* Yield to worker */
|
/* Yield to worker */
|
||||||
fiber->yield_param->kind = W32_YieldKind_Done;
|
fiber->yield_param->kind = W32_YieldKind_Done;
|
||||||
@ -959,7 +958,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
|
|||||||
PriorityKind job_priority = 0;
|
PriorityKind job_priority = 0;
|
||||||
i16 job_fiber_id = 0;
|
i16 job_fiber_id = 0;
|
||||||
i32 job_id = 0;
|
i32 job_id = 0;
|
||||||
P_JobFunc *job_func = 0;
|
GenericJobFunc *job_func = 0;
|
||||||
void *job_sig = 0;
|
void *job_sig = 0;
|
||||||
Counter *job_counter = 0;
|
Counter *job_counter = 0;
|
||||||
{
|
{
|
||||||
@ -1064,7 +1063,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
|
|||||||
{
|
{
|
||||||
/* Invalid yield kind */
|
/* Invalid yield kind */
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
P_Panic(StringFormat(scratch.arena, Lit("Invalid fiber yield kind \"%F\""), FmtSint(yield.kind)));
|
//P_Panic(StringFormat(scratch.arena, Lit("Invalid fiber yield kind \"%F\""), FmtSint(yield.kind)));
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -1133,11 +1132,11 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LockTicketMutex(&g->wait_lists_arena_lock);
|
LockTicketMutex(&g->wait_lists_arena_tm);
|
||||||
{
|
{
|
||||||
wait_addr_list = PushStructNoZero(g->wait_lists_arena, W32_WaitList);
|
wait_addr_list = PushStructNoZero(g->wait_lists_arena, W32_WaitList);
|
||||||
}
|
}
|
||||||
UnlockTicketMutex(&g->wait_lists_arena_lock);
|
UnlockTicketMutex(&g->wait_lists_arena_tm);
|
||||||
}
|
}
|
||||||
ZeroStruct(wait_addr_list);
|
ZeroStruct(wait_addr_list);
|
||||||
wait_addr_list->value = (u64)wait_addr;
|
wait_addr_list->value = (u64)wait_addr;
|
||||||
@ -1187,11 +1186,11 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LockTicketMutex(&g->wait_lists_arena_lock);
|
LockTicketMutex(&g->wait_lists_arena_tm);
|
||||||
{
|
{
|
||||||
wait_time_list = PushStructNoZero(g->wait_lists_arena, W32_WaitList);
|
wait_time_list = PushStructNoZero(g->wait_lists_arena, W32_WaitList);
|
||||||
}
|
}
|
||||||
UnlockTicketMutex(&g->wait_lists_arena_lock);
|
UnlockTicketMutex(&g->wait_lists_arena_tm);
|
||||||
}
|
}
|
||||||
ZeroStruct(wait_time_list);
|
ZeroStruct(wait_time_list);
|
||||||
wait_time_list->value = wait_time;
|
wait_time_list->value = wait_time;
|
||||||
@ -1291,7 +1290,7 @@ W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg)
|
|||||||
HANDLE timer = CreateWaitableTimerExW(0, 0, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
HANDLE timer = CreateWaitableTimerExW(0, 0, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
||||||
if (!timer)
|
if (!timer)
|
||||||
{
|
{
|
||||||
P_Panic(Lit("Failed to create high resolution timer"));
|
//P_Panic(Lit("Failed to create high resolution timer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create rolling buffer of scheduler cycles initialized to default value */
|
/* Create rolling buffer of scheduler cycles initialized to default value */
|
||||||
@ -1319,7 +1318,7 @@ W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate mean period */
|
/* Calculate mean period */
|
||||||
i64 now_ns = P_TimeNs();
|
i64 now_ns = TimeNs();
|
||||||
i64 period_ns = last_cycle_ns == 0 ? W32_DefaultSchedulerPeriodNs : now_ns - last_cycle_ns;
|
i64 period_ns = last_cycle_ns == 0 ? W32_DefaultSchedulerPeriodNs : now_ns - last_cycle_ns;
|
||||||
last_cycle_ns = now_ns;
|
last_cycle_ns = now_ns;
|
||||||
|
|
||||||
@ -1348,9 +1347,9 @@ W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Wait / wake
|
//~ @hookdef Futex
|
||||||
|
|
||||||
void P_Wait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns)
|
void FutexWait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns)
|
||||||
{
|
{
|
||||||
W32_Fiber *fiber = W32_FiberFromId(FiberId());
|
W32_Fiber *fiber = W32_FiberFromId(FiberId());
|
||||||
i16 parent_id = fiber->parent_id;
|
i16 parent_id = fiber->parent_id;
|
||||||
@ -1390,31 +1389,46 @@ void P_Wait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_Wake(void *addr, i32 count)
|
void FutexWake(void *addr, i32 count)
|
||||||
{
|
{
|
||||||
W32_WakeByAddress(addr, count);
|
W32_WakeByAddress(addr, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Fiber
|
//~ @hoodef Job
|
||||||
|
|
||||||
i16 FiberId(void)
|
GenericJobDesc *PushJobDesc_(u64 sig_size, u64 sig_align, GenericJobFunc *func, JobDescParams params)
|
||||||
{
|
{
|
||||||
return (i16)(i64)GetFiberData();
|
GenericJobDesc *result = 0;
|
||||||
|
/* FIXME: Pool arenas */
|
||||||
|
Arena *arena = AllocArena(Mebi(1));
|
||||||
|
result = PushStruct(arena, GenericJobDesc);
|
||||||
|
result->arena = arena;
|
||||||
|
result->sig = PushBytes(arena, sig_size, sig_align);
|
||||||
|
result->func = func;
|
||||||
|
result->count = params.count;
|
||||||
|
result->pool = params.pool;
|
||||||
|
result->priority = params.priority;
|
||||||
|
result->counter = params.counter;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
#if 1
|
||||||
//~ Job
|
void RunJobEx(GenericJobDesc *desc)
|
||||||
|
|
||||||
void P_Run(i32 count, P_JobFunc *func, void *sig, PoolKind pool_kind, PriorityKind priority, Counter *counter)
|
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct W32_SharedCtx *g = &W32_shared_ctx;
|
struct W32_SharedCtx *g = &W32_shared_ctx;
|
||||||
|
i32 count = desc->count;
|
||||||
|
Counter *counter = desc->counter;
|
||||||
|
PoolKind pool_kind = desc->pool;
|
||||||
|
PriorityKind priority = desc->priority;
|
||||||
|
GenericJobFunc *func = desc->func;
|
||||||
|
void *sig = desc->sig;
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
if (counter)
|
if (counter)
|
||||||
{
|
{
|
||||||
P_CounterAdd(counter, count);
|
AddCounter(counter, count);
|
||||||
}
|
}
|
||||||
W32_Fiber *fiber = W32_FiberFromId(FiberId());
|
W32_Fiber *fiber = W32_FiberFromId(FiberId());
|
||||||
priority = ClampI32(priority, fiber->job_priority, PriorityKind_Count - 1); /* A job cannot create a job with a higher priority than itself */
|
priority = ClampI32(priority, fiber->job_priority, PriorityKind_Count - 1); /* A job cannot create a job with a higher priority than itself */
|
||||||
@ -1474,3 +1488,101 @@ void P_Run(i32 count, P_JobFunc *func, void *sig, PoolKind pool_kind, PriorityKi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void RunJob(i32 count, GenericJobFunc *func, void *sig, PoolKind pool_kind, PriorityKind priority, Counter *counter)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
struct W32_SharedCtx *g = &W32_shared_ctx;
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
if (counter)
|
||||||
|
{
|
||||||
|
AddCounter(counter, count);
|
||||||
|
}
|
||||||
|
W32_Fiber *fiber = W32_FiberFromId(FiberId());
|
||||||
|
priority = ClampI32(priority, fiber->job_priority, PriorityKind_Count - 1); /* A job cannot create a job with a higher priority than itself */
|
||||||
|
if (pool_kind == PoolKind_Inherit)
|
||||||
|
{
|
||||||
|
pool_kind = fiber->job_pool;
|
||||||
|
}
|
||||||
|
W32_JobPool *pool = &g->job_pools[pool_kind];
|
||||||
|
W32_JobQueue *queue = &pool->job_queues[priority];
|
||||||
|
LockTicketMutex(&queue->lock);
|
||||||
|
{
|
||||||
|
W32_JobInfo *info = 0;
|
||||||
|
if (queue->first_free)
|
||||||
|
{
|
||||||
|
info = queue->first_free;
|
||||||
|
queue->first_free = info->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info = PushStructNoZero(queue->arena, W32_JobInfo);
|
||||||
|
}
|
||||||
|
ZeroStruct(info);
|
||||||
|
info->count = count;
|
||||||
|
info->func = func;
|
||||||
|
info->sig = sig;
|
||||||
|
info->counter = counter;
|
||||||
|
if (queue->last)
|
||||||
|
{
|
||||||
|
queue->last->next = info;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queue->first = info;
|
||||||
|
}
|
||||||
|
queue->last = info;
|
||||||
|
}
|
||||||
|
UnlockTicketMutex(&queue->lock);
|
||||||
|
|
||||||
|
/* Wake workers */
|
||||||
|
{
|
||||||
|
LockTicketMutex(&pool->workers_wake_tm);
|
||||||
|
{
|
||||||
|
Atomic64FetchAdd(&pool->num_jobs_in_queue.v, count);
|
||||||
|
if (count >= W32_WakeAllThreshold)
|
||||||
|
{
|
||||||
|
WakeByAddressAll(&pool->num_jobs_in_queue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i32 i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
WakeByAddressSingle(&pool->num_jobs_in_queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnlockTicketMutex(&pool->workers_wake_tm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ @hookdef Helpers
|
||||||
|
|
||||||
|
i64 TimeNs(void)
|
||||||
|
{
|
||||||
|
struct W32_SharedCtx *g = &W32_shared_ctx;
|
||||||
|
LARGE_INTEGER qpc;
|
||||||
|
QueryPerformanceCounter(&qpc);
|
||||||
|
i64 result = (qpc.QuadPart - g->timer_start_qpc) * g->ns_per_qpc;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetLogicalProcessorCount(void)
|
||||||
|
{
|
||||||
|
return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ThreadId(void)
|
||||||
|
{
|
||||||
|
return GetCurrentThreadId();
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 GetCurrentSchedulerPeriodNs(void)
|
||||||
|
{
|
||||||
|
W32_SharedCtx *g = &W32_shared_ctx;
|
||||||
|
return Atomic64Fetch(&g->current_scheduler_cycle_period_ns.v);
|
||||||
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
# define UNICODE
|
# define UNICODE
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
# include <Windows.h>
|
# include <Windows.h>
|
||||||
#if 0
|
|
||||||
# include <WinSock2.h>
|
# include <WinSock2.h>
|
||||||
# include <TlHelp32.h>
|
# include <TlHelp32.h>
|
||||||
# include <WS2tcpip.h>
|
# include <WS2tcpip.h>
|
||||||
@ -16,7 +15,6 @@
|
|||||||
# include <bcrypt.h>
|
# include <bcrypt.h>
|
||||||
# include <avrt.h>
|
# include <avrt.h>
|
||||||
# include <shellapi.h>
|
# include <shellapi.h>
|
||||||
#endif
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -123,7 +121,7 @@ AlignedStruct(W32_Fiber, 64)
|
|||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
/* -------------------- Cache line -------------------- */
|
/* -------------------- Cache line -------------------- */
|
||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
void *job_func; /* 08 bytes */
|
GenericJobFunc *job_func; /* 08 bytes */
|
||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
void *job_sig; /* 08 bytes */
|
void *job_sig; /* 08 bytes */
|
||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
@ -158,7 +156,7 @@ Struct(W32_JobInfo)
|
|||||||
i32 num_dispatched;
|
i32 num_dispatched;
|
||||||
|
|
||||||
i32 count;
|
i32 count;
|
||||||
void *func;
|
GenericJobFunc *func;
|
||||||
void *sig;
|
void *sig;
|
||||||
struct Counter *counter;
|
struct Counter *counter;
|
||||||
|
|
||||||
@ -217,6 +215,8 @@ AlignedStruct(W32_JobPool, 64)
|
|||||||
|
|
||||||
Struct(W32_SharedCtx)
|
Struct(W32_SharedCtx)
|
||||||
{
|
{
|
||||||
|
i64 timer_start_qpc;
|
||||||
|
i64 ns_per_qpc;
|
||||||
Atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
|
|
||||||
//- Worker thread pool
|
//- Worker thread pool
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Load job
|
//~ Load job
|
||||||
|
|
||||||
JobDef(F_LoadAssetJob, job)
|
JobDef(F_LoadJob, sig, _)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
@ -25,13 +25,12 @@ JobDef(F_LoadAssetJob, job)
|
|||||||
0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
|
0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
F_LoadJobSig *params = job.sig;
|
String path = sig->path;
|
||||||
String path = STRING(params->path_len, (u8 *)params->path_cstr);
|
f32 point_size = sig->point_size;
|
||||||
f32 point_size = params->point_size;
|
AC_Asset *asset = sig->asset;
|
||||||
AC_Asset *asset = params->asset;
|
|
||||||
|
|
||||||
P_LogInfoF("Loading font \"%F\" (point size %F)", FmtString(path), FmtFloat((f64)point_size));
|
P_LogInfoF("Loading font \"%F\" (point size %F)", FmtString(path), FmtFloat((f64)point_size));
|
||||||
i64 start_ns = P_TimeNs();
|
i64 start_ns = TimeNs();
|
||||||
|
|
||||||
Assert(StringEndsWith(path, Lit(".ttf")));
|
Assert(StringEndsWith(path, Lit(".ttf")));
|
||||||
Assert(countof(font_codes) < F_LookupTableSize);
|
Assert(countof(font_codes) < F_LookupTableSize);
|
||||||
@ -87,7 +86,7 @@ JobDef(F_LoadAssetJob, job)
|
|||||||
font->lookup[codepoint] = result.cache_indices[i];
|
font->lookup[codepoint] = result.cache_indices[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
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(TimeNs() - start_ns)));
|
||||||
AC_MarkReady(asset, font);
|
AC_MarkReady(asset, font);
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
@ -113,22 +112,12 @@ AC_Asset *F_LoadAsset(String path, f32 point_size, b32 wait)
|
|||||||
|
|
||||||
if (is_first_touch)
|
if (is_first_touch)
|
||||||
{
|
{
|
||||||
/* Assemble task params */
|
|
||||||
F_LoadJobSig *params = F_AllocJobSig();
|
|
||||||
if (path.len > (sizeof(params->path_cstr) - 1))
|
|
||||||
{
|
|
||||||
P_Panic(StringFormat(scratch.arena,
|
|
||||||
Lit("Font path \"%F\" too long!"),
|
|
||||||
FmtString(path)));
|
|
||||||
}
|
|
||||||
CstrBuffFromStringToBuff(StringFromArray(params->path_cstr), path);
|
|
||||||
params->path_len = path.len;
|
|
||||||
params->asset = asset;
|
|
||||||
params->point_size = point_size;
|
|
||||||
|
|
||||||
/* PushStruct task */
|
|
||||||
AC_MarkLoading(asset);
|
AC_MarkLoading(asset);
|
||||||
P_Run(1, F_LoadAssetJob, params, PoolKind_Background, PriorityKind_Low, 0);
|
F_LoadJob_Desc *desc = PushJobDesc(F_LoadJob, .pool = PoolKind_Background, .priority = PriorityKind_Low);
|
||||||
|
desc->sig->asset = asset;
|
||||||
|
desc->sig->path = PushString(desc->arena, path);
|
||||||
|
desc->sig->point_size = point_size;
|
||||||
|
RunJobEx((GenericJobDesc *)desc);
|
||||||
if (wait)
|
if (wait)
|
||||||
{
|
{
|
||||||
AC_WaitOnAssetReady(asset);
|
AC_WaitOnAssetReady(asset);
|
||||||
|
|||||||
@ -27,7 +27,7 @@ Struct(F_Font)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Font load job
|
//~ Font load job
|
||||||
|
|
||||||
JobDecl(F_LoadAssetJob, { AC_Asset *asset; f32 point_size; String path; });
|
JobDecl(F_LoadJob, { AC_Asset *asset; f32 point_size; String path; });
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Font load operations
|
//~ Font load operations
|
||||||
|
|||||||
@ -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, PoolKind_Background, PriorityKind_Low, &g->evictor_job_counter);
|
RunJob(1, GPU_D12_EvictorJob, PoolKind_Background, PriorityKind_Low, &g->evictor_job_counter, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
P_ExitFuncDef(GPU_D12_Shutdown)
|
P_ExitFuncDef(GPU_D12_Shutdown)
|
||||||
@ -92,12 +92,12 @@ P_ExitFuncDef(GPU_D12_Shutdown)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->evictor_wake_mutex);
|
Lock lock = LockE(&g->evictor_wake_mutex);
|
||||||
g->evictor_shutdown = 1;
|
g->evictor_shutdown = 1;
|
||||||
P_SignalCv(&g->evictor_wake_cv, I32Max);
|
SignalCv(&g->evictor_wake_cv, I32Max);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
P_WaitOnCounter(&g->evictor_job_counter);
|
WaitOnCounter(&g->evictor_job_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -322,13 +322,10 @@ void GPU_D12_InitObjects(void)
|
|||||||
{.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_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;
|
|
||||||
sig.descs_in = params;
|
|
||||||
sig.cqs_out = g->command_queues;
|
|
||||||
{
|
{
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
P_Run(DX12_NUM_QUEUES, GPU_D12_AllocCommandQueueJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
|
RunJob(DX12_NUM_QUEUES, GPU_D12_AllocCommandQueueJob, PoolKind_Inherit, PriorityKind_Low, &counter, .descs_in = params, .cqs_out = g->command_queues);
|
||||||
P_WaitOnCounter(&counter);
|
WaitOnCounter(&counter);
|
||||||
}
|
}
|
||||||
#if ProfilingIsEnabled
|
#if ProfilingIsEnabled
|
||||||
{
|
{
|
||||||
@ -418,12 +415,9 @@ void GPU_InitPipelines(void)
|
|||||||
GPU_D12_Pipeline **pipelines = PushStructs(scratch.arena, GPU_D12_Pipeline *, num_pipelines);
|
GPU_D12_Pipeline **pipelines = PushStructs(scratch.arena, GPU_D12_Pipeline *, num_pipelines);
|
||||||
{
|
{
|
||||||
__profn("Allocate pipelines");
|
__profn("Allocate pipelines");
|
||||||
GPU_D12_AllocPipelineJobSig sig = ZI;
|
|
||||||
sig.descs_in = descs;
|
|
||||||
sig.pipelines_out = pipelines;
|
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
P_Run(num_pipelines, GPU_D12_AllocPipelineJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
|
RunJob(num_pipelines, GPU_D12_AllocPipelineJob, PoolKind_Inherit, PriorityKind_Inherit, &counter, .descs_in = descs, .pipelines_out = pipelines);
|
||||||
P_WaitOnCounter(&counter);
|
WaitOnCounter(&counter);
|
||||||
}
|
}
|
||||||
for (u32 i = 0; i < num_pipelines; ++i)
|
for (u32 i = 0; i < num_pipelines; ++i)
|
||||||
{
|
{
|
||||||
@ -502,11 +496,8 @@ void GPU_D12_InitNoise(void)
|
|||||||
/* Upload texture */
|
/* Upload texture */
|
||||||
{
|
{
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
GPU_D12_UploadJobSig sig = ZI;
|
RunJob(1, GPU_D12_UploadJob, PoolKind_Inherit, PriorityKind_Low, &counter, .resource = r, .data = data.text);
|
||||||
sig.resource = r;
|
WaitOnCounter(&counter);
|
||||||
sig.data = data.text;
|
|
||||||
P_Run(1, GPU_D12_UploadJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
|
|
||||||
P_WaitOnCounter(&counter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,17 +517,16 @@ void GPU_D12_InitNoise(void)
|
|||||||
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
|
|
||||||
JobDef(GPU_D12_CompileShaderJob, job)
|
JobDef(GPU_D12_CompileShaderJob, sig, id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
GPU_D12_CompileShaderJobSig *sig = job.sig;
|
|
||||||
Arena *arena = sig->arena;
|
Arena *arena = sig->arena;
|
||||||
GPU_D12_ShaderDesc *desc = &sig->descs[job.id];
|
GPU_D12_ShaderDesc *desc = &sig->descs[id];
|
||||||
GPU_D12_CompiledShaderResult *result = &sig->results[job.id];
|
GPU_D12_CompiledShaderResult *result = &sig->results[id];
|
||||||
|
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
{
|
{
|
||||||
i64 start_ns = P_TimeNs();
|
i64 start_ns = TimeNs();
|
||||||
DXC_Result dxc_result = ZI;
|
DXC_Result dxc_result = ZI;
|
||||||
{
|
{
|
||||||
__profn("Compile shader");
|
__profn("Compile shader");
|
||||||
@ -565,7 +555,7 @@ JobDef(GPU_D12_CompileShaderJob, job)
|
|||||||
result->success = dxc_result.success;
|
result->success = dxc_result.success;
|
||||||
result->dxc = dxc_result.dxc;
|
result->dxc = dxc_result.dxc;
|
||||||
result->errors = dxc_result.errors;
|
result->errors = dxc_result.errors;
|
||||||
result->elapsed_ns = P_TimeNs() - start_ns;
|
result->elapsed_ns = TimeNs() - start_ns;
|
||||||
|
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
@ -577,17 +567,16 @@ JobDef(GPU_D12_CompileShaderJob, job)
|
|||||||
* Pipeline
|
* Pipeline
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
JobDef(GPU_D12_AllocPipelineJob, job)
|
JobDef(GPU_D12_AllocPipelineJob, sig, id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||||
GPU_D12_AllocPipelineJobSig *sig = job.sig;
|
GPU_D12_PipelineDesc *desc = &sig->descs_in[id];
|
||||||
GPU_D12_PipelineDesc *desc = &sig->descs_in[job.id];
|
|
||||||
GPU_D12_Pipeline **pipelines_out = sig->pipelines_out;
|
GPU_D12_Pipeline **pipelines_out = sig->pipelines_out;
|
||||||
|
|
||||||
GPU_D12_Pipeline *pipeline = 0;
|
GPU_D12_Pipeline *pipeline = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->pipelines_mutex);
|
Lock lock = LockE(&g->pipelines_mutex);
|
||||||
if (g->first_free_pipeline)
|
if (g->first_free_pipeline)
|
||||||
{
|
{
|
||||||
pipeline = g->first_free_pipeline;
|
pipeline = g->first_free_pipeline;
|
||||||
@ -597,17 +586,17 @@ JobDef(GPU_D12_AllocPipelineJob, job)
|
|||||||
{
|
{
|
||||||
pipeline = PushStructNoZero(g->pipelines_arena, GPU_D12_Pipeline);
|
pipeline = PushStructNoZero(g->pipelines_arena, GPU_D12_Pipeline);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(pipeline);
|
ZeroStruct(pipeline);
|
||||||
pipelines_out[job.id] = pipeline;
|
pipelines_out[id] = pipeline;
|
||||||
pipeline->desc = *desc;
|
pipeline->desc = *desc;
|
||||||
pipeline->name = desc->name;
|
pipeline->name = desc->name;
|
||||||
pipeline->hash = HashFnv64(Fnv64Basis, pipeline->name);
|
pipeline->hash = HashFnv64(Fnv64Basis, pipeline->name);
|
||||||
|
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
{
|
{
|
||||||
i64 start_ns = P_TimeNs();
|
i64 start_ns = TimeNs();
|
||||||
String pipeline_name = pipeline->name;
|
String pipeline_name = pipeline->name;
|
||||||
P_LogInfoF("Loading pipeline \"%F\"", FmtString(pipeline_name));
|
P_LogInfoF("Loading pipeline \"%F\"", FmtString(pipeline_name));
|
||||||
b32 success = 1;
|
b32 success = 1;
|
||||||
@ -880,7 +869,7 @@ JobDef(GPU_D12_AllocPipelineJob, job)
|
|||||||
|
|
||||||
pipeline->pso = pso;
|
pipeline->pso = pso;
|
||||||
pipeline->rootsig = rootsig;
|
pipeline->rootsig = rootsig;
|
||||||
pipeline->compilation_time_ns = P_TimeNs() - start_ns;
|
pipeline->compilation_time_ns = TimeNs() - start_ns;
|
||||||
pipeline->success = success;
|
pipeline->success = success;
|
||||||
pipeline->is_gfx = cs_dxc.len == 0;
|
pipeline->is_gfx = cs_dxc.len == 0;
|
||||||
pipeline->error = error_str;
|
pipeline->error = error_str;
|
||||||
@ -913,12 +902,12 @@ void GPU_D12_ReleasePipelineNow(GPU_D12_Pipeline *pipeline)
|
|||||||
{
|
{
|
||||||
ID3D12PipelineState_Release(pipeline->pso);
|
ID3D12PipelineState_Release(pipeline->pso);
|
||||||
}
|
}
|
||||||
P_Lock lock = P_LockE(&g->pipelines_mutex);
|
Lock lock = LockE(&g->pipelines_mutex);
|
||||||
{
|
{
|
||||||
pipeline->next = g->first_free_pipeline;
|
pipeline->next = g->first_free_pipeline;
|
||||||
g->first_free_pipeline = pipeline;
|
g->first_free_pipeline = pipeline;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -931,13 +920,13 @@ GPU_D12_PipelineScope *GPU_D12_BeginPipelineScope(void)
|
|||||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||||
GPU_D12_PipelineScope *scope = 0;
|
GPU_D12_PipelineScope *scope = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->pipelines_mutex);
|
Lock lock = LockE(&g->pipelines_mutex);
|
||||||
if (g->first_free_pipeline_scope)
|
if (g->first_free_pipeline_scope)
|
||||||
{
|
{
|
||||||
scope = g->first_free_pipeline_scope;
|
scope = g->first_free_pipeline_scope;
|
||||||
g->first_free_pipeline_scope = scope->next_free;
|
g->first_free_pipeline_scope = scope->next_free;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
Arena *arena = 0;
|
Arena *arena = 0;
|
||||||
if (scope)
|
if (scope)
|
||||||
@ -959,7 +948,7 @@ void GPU_D12_EndPipelineScope(GPU_D12_PipelineScope *scope)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||||
P_Lock lock = P_LockE(&g->pipelines_mutex);
|
Lock lock = LockE(&g->pipelines_mutex);
|
||||||
{
|
{
|
||||||
for (DictEntry *entry = scope->refs->first; entry; entry = entry->next)
|
for (DictEntry *entry = scope->refs->first; entry; entry = entry->next)
|
||||||
{
|
{
|
||||||
@ -972,7 +961,7 @@ void GPU_D12_EndPipelineScope(GPU_D12_PipelineScope *scope)
|
|||||||
scope->next_free = g->first_free_pipeline_scope;
|
scope->next_free = g->first_free_pipeline_scope;
|
||||||
g->first_free_pipeline_scope = scope;
|
g->first_free_pipeline_scope = scope;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
Readonly GPU_D12_Pipeline GPU_D12_nil_pipeline = ZI;
|
Readonly GPU_D12_Pipeline GPU_D12_nil_pipeline = ZI;
|
||||||
@ -991,13 +980,13 @@ GPU_D12_Pipeline *GPU_D12_PipelineFromName(GPU_D12_PipelineScope *scope, String
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->pipelines_mutex);
|
Lock lock = LockE(&g->pipelines_mutex);
|
||||||
tmp = (GPU_D12_Pipeline *)DictValueFromHash(g->top_successful_pipelines, hash);
|
tmp = (GPU_D12_Pipeline *)DictValueFromHash(g->top_successful_pipelines, hash);
|
||||||
if (tmp)
|
if (tmp)
|
||||||
{
|
{
|
||||||
++tmp->refcount;
|
++tmp->refcount;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
if (tmp)
|
if (tmp)
|
||||||
{
|
{
|
||||||
@ -1013,7 +1002,7 @@ void GPU_D12_RegisterPipeline(u64 num_pipelines, GPU_D12_Pipeline **pipelines)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||||
P_Lock lock = P_LockE(&g->pipelines_mutex);
|
Lock lock = LockE(&g->pipelines_mutex);
|
||||||
{
|
{
|
||||||
for (u64 i = 0; i < num_pipelines; ++i)
|
for (u64 i = 0; i < num_pipelines; ++i)
|
||||||
{
|
{
|
||||||
@ -1042,7 +1031,7 @@ void GPU_D12_RegisterPipeline(u64 num_pipelines, GPU_D12_Pipeline **pipelines)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
@ -1085,40 +1074,42 @@ W_CallbackFuncDef(GPU_D12_WatchPipelineCallback, name)
|
|||||||
pipeline_name = split.count > 1 ? split.strings[split.count - 2] : pipeline_name;
|
pipeline_name = split.count > 1 ? split.strings[split.count - 2] : pipeline_name;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
GPU_D12_CompileShaderJobSig sig = ZI;
|
GPU_D12_CompileShaderJob_Desc *job_desc = PushJobDesc(GPU_D12_CompileShaderJob, .count = 0);
|
||||||
sig.arena = scratch.arena;
|
job_desc->sig->arena = scratch.arena;
|
||||||
if (is_rs)
|
if (is_rs)
|
||||||
{
|
{
|
||||||
num_shaders = 2;
|
num_shaders = 2;
|
||||||
shader_descs = PushStructs(scratch.arena, GPU_D12_ShaderDesc, num_shaders);
|
shader_descs = PushStructs(scratch.arena, GPU_D12_ShaderDesc, num_shaders);
|
||||||
shader_results = PushStructs(scratch.arena, GPU_D12_CompiledShaderResult, num_shaders);
|
shader_results = PushStructs(scratch.arena, GPU_D12_CompiledShaderResult, num_shaders);
|
||||||
sig.descs = shader_descs;
|
job_desc->sig->descs = shader_descs;
|
||||||
sig.results = shader_results;
|
job_desc->sig->results = shader_results;
|
||||||
sig.descs[0].src = data;
|
job_desc->sig->descs[0].src = data;
|
||||||
sig.descs[0].friendly_name = friendly_name;
|
job_desc->sig->descs[0].friendly_name = friendly_name;
|
||||||
sig.descs[0].entry = Lit("vs");
|
job_desc->sig->descs[0].entry = Lit("vs");
|
||||||
sig.descs[0].target = Lit("vs_6_6");
|
job_desc->sig->descs[0].target = Lit("vs_6_6");
|
||||||
sig.descs[1].src = data;
|
job_desc->sig->descs[1].src = data;
|
||||||
sig.descs[1].friendly_name = friendly_name;
|
job_desc->sig->descs[1].friendly_name = friendly_name;
|
||||||
sig.descs[1].entry = Lit("ps");
|
job_desc->sig->descs[1].entry = Lit("ps");
|
||||||
sig.descs[1].target = Lit("ps_6_6");
|
job_desc->sig->descs[1].target = Lit("ps_6_6");
|
||||||
}
|
}
|
||||||
else if (is_cs)
|
else if (is_cs)
|
||||||
{
|
{
|
||||||
num_shaders = 1;
|
num_shaders = 1;
|
||||||
shader_descs = PushStructs(scratch.arena, GPU_D12_ShaderDesc, num_shaders);
|
shader_descs = PushStructs(scratch.arena, GPU_D12_ShaderDesc, num_shaders);
|
||||||
shader_results = PushStructs(scratch.arena, GPU_D12_CompiledShaderResult, num_shaders);
|
shader_results = PushStructs(scratch.arena, GPU_D12_CompiledShaderResult, num_shaders);
|
||||||
sig.descs = shader_descs;
|
job_desc->sig->descs = shader_descs;
|
||||||
sig.results = shader_results;
|
job_desc->sig->results = shader_results;
|
||||||
sig.descs[0].src = data;
|
job_desc->sig->descs[0].src = data;
|
||||||
sig.descs[0].friendly_name = friendly_name;
|
job_desc->sig->descs[0].friendly_name = friendly_name;
|
||||||
sig.descs[0].entry = Lit("cs");
|
job_desc->sig->descs[0].entry = Lit("cs");
|
||||||
sig.descs[0].target = Lit("cs_6_6");
|
job_desc->sig->descs[0].target = Lit("cs_6_6");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
P_Run(num_shaders, GPU_D12_CompileShaderJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
|
job_desc->count = num_shaders;
|
||||||
P_WaitOnCounter(&counter);
|
job_desc->counter = &counter;
|
||||||
|
RunJobEx((GenericJobDesc *)job_desc);
|
||||||
|
WaitOnCounter(&counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_CloseFIle(file);
|
P_CloseFIle(file);
|
||||||
@ -1177,15 +1168,12 @@ W_CallbackFuncDef(GPU_D12_WatchPipelineCallback, name)
|
|||||||
__profn("Compile dirty pipelines");
|
__profn("Compile dirty pipelines");
|
||||||
GPU_D12_Pipeline **pipelines = PushStructs(scratch.arena, GPU_D12_Pipeline *, num_pipelines);
|
GPU_D12_Pipeline **pipelines = PushStructs(scratch.arena, GPU_D12_Pipeline *, num_pipelines);
|
||||||
{
|
{
|
||||||
GPU_D12_AllocPipelineJobSig sig = ZI;
|
|
||||||
sig.descs_in = pipeline_descs;
|
|
||||||
sig.pipelines_out = pipelines;
|
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
P_Run(num_pipelines, GPU_D12_AllocPipelineJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
|
RunJob(num_pipelines, GPU_D12_AllocPipelineJob, PoolKind_Inherit, PriorityKind_Low, &counter, .descs_in = pipeline_descs, .pipelines_out = pipelines);
|
||||||
P_WaitOnCounter(&counter);
|
WaitOnCounter(&counter);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockS(&g->pipelines_mutex);
|
Lock lock = LockS(&g->pipelines_mutex);
|
||||||
for (u32 i = 0; i < num_pipelines; ++i)
|
for (u32 i = 0; i < num_pipelines; ++i)
|
||||||
{
|
{
|
||||||
GPU_D12_Pipeline *pipeline = pipelines[i];
|
GPU_D12_Pipeline *pipeline = pipelines[i];
|
||||||
@ -1216,7 +1204,7 @@ W_CallbackFuncDef(GPU_D12_WatchPipelineCallback, name)
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
GPU_D12_RegisterPipeline(num_pipelines, pipelines);
|
GPU_D12_RegisterPipeline(num_pipelines, pipelines);
|
||||||
}
|
}
|
||||||
@ -1237,7 +1225,7 @@ GPU_D12_Descriptor *GPU_D12_AllocDescriptor(GPU_D12_CpuDescriptorHeap *dh)
|
|||||||
u32 index = 0;
|
u32 index = 0;
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = ZI;
|
D3D12_CPU_DESCRIPTOR_HANDLE handle = ZI;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&dh->mutex);
|
Lock lock = LockE(&dh->mutex);
|
||||||
if (dh->first_free_descriptor)
|
if (dh->first_free_descriptor)
|
||||||
{
|
{
|
||||||
d = dh->first_free_descriptor;
|
d = dh->first_free_descriptor;
|
||||||
@ -1255,7 +1243,7 @@ GPU_D12_Descriptor *GPU_D12_AllocDescriptor(GPU_D12_CpuDescriptorHeap *dh)
|
|||||||
index = dh->num_descriptors_reserved++;
|
index = dh->num_descriptors_reserved++;
|
||||||
handle.ptr = dh->handle.ptr + (index * dh->descriptor_size);
|
handle.ptr = dh->handle.ptr + (index * dh->descriptor_size);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(d);
|
ZeroStruct(d);
|
||||||
d->heap = dh;
|
d->heap = dh;
|
||||||
@ -1267,12 +1255,12 @@ GPU_D12_Descriptor *GPU_D12_AllocDescriptor(GPU_D12_CpuDescriptorHeap *dh)
|
|||||||
void GPU_D12_ReleaseDescriptor(GPU_D12_Descriptor *descriptor)
|
void GPU_D12_ReleaseDescriptor(GPU_D12_Descriptor *descriptor)
|
||||||
{
|
{
|
||||||
GPU_D12_CpuDescriptorHeap *dh = descriptor->heap;
|
GPU_D12_CpuDescriptorHeap *dh = descriptor->heap;
|
||||||
P_Lock lock = P_LockE(&dh->mutex);
|
Lock lock = LockE(&dh->mutex);
|
||||||
{
|
{
|
||||||
descriptor->next_free = dh->first_free_descriptor;
|
descriptor->next_free = dh->first_free_descriptor;
|
||||||
dh->first_free_descriptor = descriptor;
|
dh->first_free_descriptor = descriptor;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -1342,31 +1330,31 @@ void GPU_D12_ReleaseDataFenced(void *data, GPU_D12_FencedReleaseKind kind)
|
|||||||
for (u32 i = 0; i < countof(g->command_queues); ++i)
|
for (u32 i = 0; i < countof(g->command_queues); ++i)
|
||||||
{
|
{
|
||||||
GPU_D12_CommandQueue *cq = g->command_queues[i];
|
GPU_D12_CommandQueue *cq = g->command_queues[i];
|
||||||
P_Lock lock = P_LockS(&cq->submit_fence_mutex);
|
Lock lock = LockS(&cq->submit_fence_mutex);
|
||||||
{
|
{
|
||||||
fr_targets[i] = cq->submit_fence_target;
|
fr_targets[i] = cq->submit_fence_target;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PushStruct data to release queue */
|
/* Push data to release queue */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->fenced_releases_mutex);
|
Lock lock = LockE(&g->fenced_releases_mutex);
|
||||||
{
|
{
|
||||||
*PushStruct(g->fenced_releases_arena, GPU_D12_FencedReleaseData) = fr;
|
*PushStruct(g->fenced_releases_arena, GPU_D12_FencedReleaseData) = fr;
|
||||||
CopyBytes(g->fenced_release_targets, fr_targets, sizeof(fr_targets));
|
CopyBytes(g->fenced_release_targets, fr_targets, sizeof(fr_targets));
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wake evictor */
|
/* Wake evictor */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->evictor_wake_mutex);
|
Lock lock = LockE(&g->evictor_wake_mutex);
|
||||||
{
|
{
|
||||||
++g->evictor_wake_gen;
|
++g->evictor_wake_gen;
|
||||||
P_SignalCv(&g->evictor_wake_cv, I32Max);
|
SignalCv(&g->evictor_wake_cv, I32Max);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1380,7 +1368,7 @@ GPU_D12_Resource *GPU_D12_AllocResource(D3D12_HEAP_PROPERTIES heap_props, D3D12_
|
|||||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||||
GPU_D12_Resource *r = 0;
|
GPU_D12_Resource *r = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->resources_mutex);
|
Lock lock = LockE(&g->resources_mutex);
|
||||||
if (g->first_free_resource)
|
if (g->first_free_resource)
|
||||||
{
|
{
|
||||||
r = g->first_free_resource;
|
r = g->first_free_resource;
|
||||||
@ -1390,7 +1378,7 @@ GPU_D12_Resource *GPU_D12_AllocResource(D3D12_HEAP_PROPERTIES heap_props, D3D12_
|
|||||||
{
|
{
|
||||||
r = PushStructNoZero(g->resources_arena, GPU_D12_Resource);
|
r = PushStructNoZero(g->resources_arena, GPU_D12_Resource);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(r);
|
ZeroStruct(r);
|
||||||
|
|
||||||
@ -1441,10 +1429,10 @@ void GPU_D12_ReleaseResourceNow(GPU_D12_Resource *t)
|
|||||||
ID3D12Resource_Release(t->resource);
|
ID3D12Resource_Release(t->resource);
|
||||||
|
|
||||||
/* Add to free list */
|
/* Add to free list */
|
||||||
P_Lock lock = P_LockE(&g->resources_mutex);
|
Lock lock = LockE(&g->resources_mutex);
|
||||||
t->next_free = g->first_free_resource;
|
t->next_free = g->first_free_resource;
|
||||||
g->first_free_resource = t;
|
g->first_free_resource = t;
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_ReleaseResourceFenced(GPU_Resource *resource)
|
void GPU_ReleaseResourceFenced(GPU_Resource *resource)
|
||||||
@ -1515,12 +1503,11 @@ 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);
|
||||||
|
|
||||||
JobDef(GPU_D12_AllocCommandQueueJob, job)
|
JobDef(GPU_D12_AllocCommandQueueJob, sig, id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||||
GPU_D12_AllocCommandQueueJobSig *sig = job.sig;
|
GPU_D12_CommandQueueDesc *desc = &sig->descs_in[id];
|
||||||
GPU_D12_CommandQueueDesc *desc = &sig->descs_in[job.id];
|
|
||||||
{
|
{
|
||||||
GPU_D12_CommandQueue *cq = 0;
|
GPU_D12_CommandQueue *cq = 0;
|
||||||
{
|
{
|
||||||
@ -1548,7 +1535,7 @@ JobDef(GPU_D12_AllocCommandQueueJob, job)
|
|||||||
|
|
||||||
cq->cl_pool = GPU_D12_AllocCommandListPool(cq);
|
cq->cl_pool = GPU_D12_AllocCommandListPool(cq);
|
||||||
|
|
||||||
sig->cqs_out[job.id] = cq;
|
sig->cqs_out[id] = cq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1587,7 +1574,7 @@ GPU_D12_CommandList *GPU_D12_BeginCommandList(GPU_D12_CommandListPool *pool)
|
|||||||
struct ID3D12GraphicsCommandList *old_cl = 0;
|
struct ID3D12GraphicsCommandList *old_cl = 0;
|
||||||
struct ID3D12CommandAllocator *old_ca = 0;
|
struct ID3D12CommandAllocator *old_ca = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&pool->mutex);
|
Lock lock = LockE(&pool->mutex);
|
||||||
/* Find first command list ready for reuse */
|
/* Find first command list ready for reuse */
|
||||||
for (GPU_D12_CommandList *tmp = pool->first_submitted_command_list; tmp; tmp = tmp->next_submitted)
|
for (GPU_D12_CommandList *tmp = pool->first_submitted_command_list; tmp; tmp = tmp->next_submitted)
|
||||||
{
|
{
|
||||||
@ -1625,12 +1612,12 @@ GPU_D12_CommandList *GPU_D12_BeginCommandList(GPU_D12_CommandListPool *pool)
|
|||||||
{
|
{
|
||||||
cl = PushStructNoZero(pool->arena, GPU_D12_CommandList);
|
cl = PushStructNoZero(pool->arena, GPU_D12_CommandList);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(cl);
|
ZeroStruct(cl);
|
||||||
cl->cq = cq;
|
cl->cq = cq;
|
||||||
cl->pool = pool;
|
cl->pool = pool;
|
||||||
cl->global_record_lock = P_LockS(&g->global_command_list_record_mutex);
|
cl->global_record_lock = LockS(&g->global_command_list_record_mutex);
|
||||||
|
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
if (old_cl)
|
if (old_cl)
|
||||||
@ -1698,20 +1685,20 @@ u64 GPU_D12_EndCommandList(GPU_D12_CommandList *cl)
|
|||||||
u64 submit_fence_target = 0;
|
u64 submit_fence_target = 0;
|
||||||
{
|
{
|
||||||
__profn("Execute");
|
__profn("Execute");
|
||||||
P_Lock submit_lock = P_LockS(&g->global_submit_mutex);
|
Lock submit_lock = LockS(&g->global_submit_mutex);
|
||||||
P_Lock fence_lock = P_LockE(&cq->submit_fence_mutex);
|
Lock fence_lock = LockE(&cq->submit_fence_mutex);
|
||||||
{
|
{
|
||||||
submit_fence_target = ++cq->submit_fence_target;
|
submit_fence_target = ++cq->submit_fence_target;
|
||||||
ID3D12CommandQueue_ExecuteCommandLists(cq->cq, 1, (ID3D12CommandList **)&cl->cl);
|
ID3D12CommandQueue_ExecuteCommandLists(cq->cq, 1, (ID3D12CommandList **)&cl->cl);
|
||||||
ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, submit_fence_target);
|
ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, submit_fence_target);
|
||||||
}
|
}
|
||||||
P_Unlock(&fence_lock);
|
Unlock(&fence_lock);
|
||||||
P_Unlock(&submit_lock);
|
Unlock(&submit_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add descriptor heaps to submitted list */
|
/* Add descriptor heaps to submitted list */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->command_descriptor_heaps_mutex);
|
Lock lock = LockE(&g->command_descriptor_heaps_mutex);
|
||||||
for (GPU_D12_CommandDescriptorHeap *cdh = cl->first_command_descriptor_heap; cdh; cdh = cdh->next_in_command_list)
|
for (GPU_D12_CommandDescriptorHeap *cdh = cl->first_command_descriptor_heap; cdh; cdh = cdh->next_in_command_list)
|
||||||
{
|
{
|
||||||
cdh->submitted_cq = cq;
|
cdh->submitted_cq = cq;
|
||||||
@ -1726,12 +1713,12 @@ u64 GPU_D12_EndCommandList(GPU_D12_CommandList *cl)
|
|||||||
}
|
}
|
||||||
g->last_submitted_command_descriptor_heap = cdh;
|
g->last_submitted_command_descriptor_heap = cdh;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add command buffers to submitted list */
|
/* Add command buffers to submitted list */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->command_buffers_mutex);
|
Lock lock = LockE(&g->command_buffers_mutex);
|
||||||
for (GPU_D12_CommandBuffer *cb = cl->first_command_buffer; cb; cb = cb->next_in_command_list)
|
for (GPU_D12_CommandBuffer *cb = cl->first_command_buffer; cb; cb = cb->next_in_command_list)
|
||||||
{
|
{
|
||||||
GPU_D12_CommandBufferGroup *group = cb->group;
|
GPU_D12_CommandBufferGroup *group = cb->group;
|
||||||
@ -1747,14 +1734,14 @@ u64 GPU_D12_EndCommandList(GPU_D12_CommandList *cl)
|
|||||||
}
|
}
|
||||||
group->last_submitted = cb;
|
group->last_submitted = cb;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add command list to pool submitted list */
|
/* Add command list to pool submitted list */
|
||||||
P_Unlock(&cl->global_record_lock);
|
Unlock(&cl->global_record_lock);
|
||||||
cl->submitted_fence_target = submit_fence_target;
|
cl->submitted_fence_target = submit_fence_target;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&pool->mutex);
|
Lock lock = LockE(&pool->mutex);
|
||||||
if (pool->last_submitted_command_list)
|
if (pool->last_submitted_command_list)
|
||||||
{
|
{
|
||||||
pool->last_submitted_command_list->next_submitted = cl;
|
pool->last_submitted_command_list->next_submitted = cl;
|
||||||
@ -1764,7 +1751,7 @@ u64 GPU_D12_EndCommandList(GPU_D12_CommandList *cl)
|
|||||||
pool->first_submitted_command_list = cl;
|
pool->first_submitted_command_list = cl;
|
||||||
}
|
}
|
||||||
pool->last_submitted_command_list = cl;
|
pool->last_submitted_command_list = cl;
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return submit_fence_target;
|
return submit_fence_target;
|
||||||
@ -1786,7 +1773,7 @@ GPU_D12_CommandDescriptorHeap *GPU_D12_PushDescriptorHeap(GPU_D12_CommandList *c
|
|||||||
D3D12_CPU_DESCRIPTOR_HANDLE old_start_cpu_handle = ZI;
|
D3D12_CPU_DESCRIPTOR_HANDLE old_start_cpu_handle = ZI;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE old_start_gpu_handle = ZI;
|
D3D12_GPU_DESCRIPTOR_HANDLE old_start_gpu_handle = ZI;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->command_descriptor_heaps_mutex);
|
Lock lock = LockE(&g->command_descriptor_heaps_mutex);
|
||||||
/* Find first heap ready for reuse */
|
/* Find first heap ready for reuse */
|
||||||
for (GPU_D12_CommandDescriptorHeap *tmp = g->first_submitted_command_descriptor_heap; tmp; tmp = tmp->next_submitted)
|
for (GPU_D12_CommandDescriptorHeap *tmp = g->first_submitted_command_descriptor_heap; tmp; tmp = tmp->next_submitted)
|
||||||
{
|
{
|
||||||
@ -1828,7 +1815,7 @@ GPU_D12_CommandDescriptorHeap *GPU_D12_PushDescriptorHeap(GPU_D12_CommandList *c
|
|||||||
/* No available heap available for reuse, allocate new */
|
/* No available heap available for reuse, allocate new */
|
||||||
cdh = PushStructNoZero(g->command_descriptor_heaps_arena, GPU_D12_CommandDescriptorHeap);
|
cdh = PushStructNoZero(g->command_descriptor_heaps_arena, GPU_D12_CommandDescriptorHeap);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(cdh);
|
ZeroStruct(cdh);
|
||||||
|
|
||||||
@ -1855,9 +1842,9 @@ GPU_D12_CommandDescriptorHeap *GPU_D12_PushDescriptorHeap(GPU_D12_CommandList *c
|
|||||||
|
|
||||||
/* Copy CPU heap */
|
/* Copy CPU heap */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockS(&dh_cpu->mutex);
|
Lock lock = 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);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert into command list */
|
/* Insert into command list */
|
||||||
@ -1894,7 +1881,7 @@ GPU_D12_CommandBuffer *GPU_D12__PushCommandBuffer(GPU_D12_CommandList *cl, u64 d
|
|||||||
GPU_D12_CommandBuffer *cb = 0;
|
GPU_D12_CommandBuffer *cb = 0;
|
||||||
GPU_D12_Resource *r = 0;
|
GPU_D12_Resource *r = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->command_buffers_mutex);
|
Lock lock = LockE(&g->command_buffers_mutex);
|
||||||
|
|
||||||
{
|
{
|
||||||
u64 group_hash = GPU_D12_CommandBufferHashFromSize(size);
|
u64 group_hash = GPU_D12_CommandBufferHashFromSize(size);
|
||||||
@ -1946,7 +1933,7 @@ GPU_D12_CommandBuffer *GPU_D12__PushCommandBuffer(GPU_D12_CommandList *cl, u64 d
|
|||||||
/* Allocate new */
|
/* Allocate new */
|
||||||
cb = PushStructNoZero(g->command_buffers_arena, GPU_D12_CommandBuffer);
|
cb = PushStructNoZero(g->command_buffers_arena, GPU_D12_CommandBuffer);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(cb);
|
ZeroStruct(cb);
|
||||||
cb->group = cb_group;
|
cb->group = cb_group;
|
||||||
@ -2017,10 +2004,9 @@ GPU_D12_CommandBuffer *GPU_D12__PushCommandBuffer(GPU_D12_CommandList *cl, u64 d
|
|||||||
* Wait job
|
* Wait job
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
JobDef(GPU_D12_WaitOnFenceJob, job)
|
JobDef(GPU_D12_WaitOnFenceJob, sig, UNUSED id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
GPU_D12_WaitOnFenceJobSig *sig = job.sig;
|
|
||||||
ID3D12Fence *fence = sig->fence;
|
ID3D12Fence *fence = sig->fence;
|
||||||
u64 target = sig->target;
|
u64 target = sig->target;
|
||||||
if (ID3D12Fence_GetCompletedValue(fence) < target)
|
if (ID3D12Fence_GetCompletedValue(fence) < target)
|
||||||
@ -2100,11 +2086,8 @@ GPU_Resource *GPU_AllocTexture(GPU_TextureFormat format, u32 flags, Vec2I32 size
|
|||||||
{
|
{
|
||||||
/* TODO: Make wait optional */
|
/* TODO: Make wait optional */
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
GPU_D12_UploadJobSig sig = ZI;
|
RunJob(1, GPU_D12_UploadJob, PoolKind_Inherit, PriorityKind_Inherit, &counter, .resource = r, .data = initial_data);
|
||||||
sig.resource = r;
|
WaitOnCounter(&counter);
|
||||||
sig.data = initial_data;
|
|
||||||
P_Run(1, GPU_D12_UploadJob, &sig, PoolKind_Inherit, PriorityKind_Inherit, &counter);
|
|
||||||
P_WaitOnCounter(&counter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (GPU_Resource *)r;
|
return (GPU_Resource *)r;
|
||||||
@ -2120,10 +2103,9 @@ Vec2I32 GPU_GetTextureSize(GPU_Resource *resource)
|
|||||||
* Upload
|
* Upload
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
JobDef(GPU_D12_UploadJob, job)
|
JobDef(GPU_D12_UploadJob, sig, UNUSED id)
|
||||||
{
|
{
|
||||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||||
GPU_D12_UploadJobSig *sig = job.sig;
|
|
||||||
GPU_D12_Resource *r = sig->resource;
|
GPU_D12_Resource *r = sig->resource;
|
||||||
void *data = sig->data;
|
void *data = sig->data;
|
||||||
|
|
||||||
@ -2216,12 +2198,9 @@ JobDef(GPU_D12_UploadJob, job)
|
|||||||
/* Wait on fence so we know it's safe to release upload heap */
|
/* Wait on fence so we know it's safe to release upload heap */
|
||||||
if (ID3D12Fence_GetCompletedValue(cq->submit_fence) < fence_target)
|
if (ID3D12Fence_GetCompletedValue(cq->submit_fence) < fence_target)
|
||||||
{
|
{
|
||||||
GPU_D12_WaitOnFenceJobSig wait_sig = ZI;
|
|
||||||
wait_sig.fence = cq->submit_fence;
|
|
||||||
wait_sig.target = fence_target;
|
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
P_Run(1, GPU_D12_WaitOnFenceJob, &wait_sig, PoolKind_Floating, PriorityKind_Low, &counter);
|
RunJob(1, GPU_D12_WaitOnFenceJob, PoolKind_Floating, PriorityKind_Inherit, &counter, .fence = cq->submit_fence, .target = fence_target);
|
||||||
P_WaitOnCounter(&counter);
|
WaitOnCounter(&counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release upload heap now */
|
/* Release upload heap now */
|
||||||
@ -3040,7 +3019,7 @@ GPU_Swapchain *GPU_AllocSwapchain(P_Window *window, Vec2I32 resolution)
|
|||||||
|
|
||||||
GPU_D12_Swapchain *swapchain = 0;
|
GPU_D12_Swapchain *swapchain = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->swapchains_mutex);
|
Lock lock = LockE(&g->swapchains_mutex);
|
||||||
if (g->first_free_swapchain)
|
if (g->first_free_swapchain)
|
||||||
{
|
{
|
||||||
swapchain = g->first_free_swapchain;
|
swapchain = g->first_free_swapchain;
|
||||||
@ -3050,7 +3029,7 @@ GPU_Swapchain *GPU_AllocSwapchain(P_Window *window, Vec2I32 resolution)
|
|||||||
{
|
{
|
||||||
swapchain = PushStruct(g->swapchains_arena, GPU_D12_Swapchain);
|
swapchain = PushStruct(g->swapchains_arena, GPU_D12_Swapchain);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create swapchain1 */
|
/* Create swapchain1 */
|
||||||
@ -3132,9 +3111,9 @@ GPU_D12_SwapchainBuffer *GPU_D12_UpdateSwapchain(GPU_D12_Swapchain *swapchain, V
|
|||||||
GPU_D12_CommandQueue *cq = g->command_queues[DX12_QUEUE_DIRECT];
|
GPU_D12_CommandQueue *cq = g->command_queues[DX12_QUEUE_DIRECT];
|
||||||
/* Lock direct queue submissions (in case any write to backbuffer) */
|
/* Lock direct queue submissions (in case any write to backbuffer) */
|
||||||
/* TODO: Less overkill approach - Only flush GPU_D12_BlitToSwapchain since we know it's the only operation targeting backbuffer */
|
/* TODO: Less overkill approach - Only flush GPU_D12_BlitToSwapchain since we know it's the only operation targeting backbuffer */
|
||||||
P_Lock lock = P_LockE(&cq->submit_fence_mutex);
|
Lock lock = LockE(&cq->submit_fence_mutex);
|
||||||
//DEBUGBREAKABLE;
|
//DEBUGBREAKABLE;
|
||||||
//P_Lock lock = P_LockE(&g->global_command_list_record_mutex);
|
//Lock lock = LockE(&g->global_command_list_record_mutex);
|
||||||
{
|
{
|
||||||
/* Flush direct queue */
|
/* Flush direct queue */
|
||||||
//ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, ++cq->submit_fence_target);
|
//ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, ++cq->submit_fence_target);
|
||||||
@ -3161,7 +3140,7 @@ GPU_D12_SwapchainBuffer *GPU_D12_UpdateSwapchain(GPU_D12_Swapchain *swapchain, V
|
|||||||
P_Panic(Lit("Failed to resize swapchain"));
|
P_Panic(Lit("Failed to resize swapchain"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
|
|
||||||
GPU_D12_InitSwapchainResources(swapchain);
|
GPU_D12_InitSwapchainResources(swapchain);
|
||||||
|
|
||||||
@ -3309,7 +3288,7 @@ void GPU_PresentSwapchain(GPU_Swapchain *gp_swapchain, Vec2I32 backbuffer_resolu
|
|||||||
|
|
||||||
__profn("Mark queue frames");
|
__profn("Mark queue frames");
|
||||||
/* Lock because frame marks shouldn't occur while command lists are recording */
|
/* Lock because frame marks shouldn't occur while command lists are recording */
|
||||||
P_Lock lock = P_LockE(&g->global_command_list_record_mutex);
|
Lock lock = LockE(&g->global_command_list_record_mutex);
|
||||||
for (u32 i = 0; i < countof(g->command_queues); ++i)
|
for (u32 i = 0; i < countof(g->command_queues); ++i)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -3317,7 +3296,7 @@ void GPU_PresentSwapchain(GPU_Swapchain *gp_swapchain, Vec2I32 backbuffer_resolu
|
|||||||
__prof_dx12_new_frame(cq->prof);
|
__prof_dx12_new_frame(cq->prof);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
__profn("Collect queues");
|
__profn("Collect queues");
|
||||||
@ -3334,7 +3313,7 @@ void GPU_PresentSwapchain(GPU_Swapchain *gp_swapchain, Vec2I32 backbuffer_resolu
|
|||||||
* Evictor job
|
* Evictor job
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
JobDef(GPU_D12_EvictorJob, _)
|
JobDef(GPU_D12_EvictorJob, UNUSED sig, UNUSED id)
|
||||||
{
|
{
|
||||||
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;
|
||||||
@ -3352,13 +3331,13 @@ JobDef(GPU_D12_EvictorJob, _)
|
|||||||
GPU_D12_FencedReleaseData *fenced_releases = 0;
|
GPU_D12_FencedReleaseData *fenced_releases = 0;
|
||||||
{
|
{
|
||||||
__profn("Copy queued releases");
|
__profn("Copy queued releases");
|
||||||
P_Lock lock = P_LockE(&g->fenced_releases_mutex);
|
Lock lock = 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);
|
||||||
CopyBytes(fenced_releases, ArenaBase(g->fenced_releases_arena), g->fenced_releases_arena->pos);
|
CopyBytes(fenced_releases, ArenaBase(g->fenced_releases_arena), g->fenced_releases_arena->pos);
|
||||||
ResetArena(g->fenced_releases_arena);
|
ResetArena(g->fenced_releases_arena);
|
||||||
CopyBytes(targets, g->fenced_release_targets, sizeof(targets));
|
CopyBytes(targets, g->fenced_release_targets, sizeof(targets));
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until fences reach target */
|
/* Wait until fences reach target */
|
||||||
@ -3374,14 +3353,9 @@ JobDef(GPU_D12_EvictorJob, _)
|
|||||||
{
|
{
|
||||||
__profn("Wait on fence");
|
__profn("Wait on fence");
|
||||||
{
|
{
|
||||||
GPU_D12_WaitOnFenceJobSig sig = ZI;
|
Counter counter = ZI;
|
||||||
sig.fence = cq->submit_fence;
|
RunJob(1, GPU_D12_WaitOnFenceJob, PoolKind_Floating, PriorityKind_Inherit, &counter, .fence = cq->submit_fence, .target = targets[i]);
|
||||||
sig.target = targets[i];
|
WaitOnCounter(&counter);
|
||||||
{
|
|
||||||
Counter counter = ZI;
|
|
||||||
P_Run(1, GPU_D12_WaitOnFenceJob, &sig, PoolKind_Floating, PriorityKind_Low, &counter);
|
|
||||||
P_WaitOnCounter(&counter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3415,15 +3389,15 @@ JobDef(GPU_D12_EvictorJob, _)
|
|||||||
}
|
}
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
P_Lock lock = P_LockE(&g->evictor_wake_mutex);
|
Lock lock = LockE(&g->evictor_wake_mutex);
|
||||||
{
|
{
|
||||||
while (!g->evictor_shutdown && g->evictor_wake_gen == 0)
|
while (!g->evictor_shutdown && g->evictor_wake_gen == 0)
|
||||||
{
|
{
|
||||||
P_WaitOnCv(&g->evictor_wake_cv, &lock);
|
WaitOnCv(&g->evictor_wake_cv, &lock);
|
||||||
}
|
}
|
||||||
shutdown = g->evictor_shutdown;
|
shutdown = g->evictor_shutdown;
|
||||||
g->evictor_wake_gen = 0;
|
g->evictor_wake_gen = 0;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -133,7 +133,7 @@ Struct(GPU_D12_CommandQueue)
|
|||||||
ID3D12CommandQueue *cq;
|
ID3D12CommandQueue *cq;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
P_Mutex submit_fence_mutex;
|
Mutex submit_fence_mutex;
|
||||||
u64 submit_fence_target;
|
u64 submit_fence_target;
|
||||||
ID3D12Fence *submit_fence;
|
ID3D12Fence *submit_fence;
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ Struct(GPU_D12_CommandListPool)
|
|||||||
{
|
{
|
||||||
GPU_D12_CommandQueue *cq;
|
GPU_D12_CommandQueue *cq;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
P_Mutex mutex;
|
Mutex mutex;
|
||||||
struct GPU_D12_CommandList *first_submitted_command_list;
|
struct GPU_D12_CommandList *first_submitted_command_list;
|
||||||
struct GPU_D12_CommandList *last_submitted_command_list;
|
struct GPU_D12_CommandList *last_submitted_command_list;
|
||||||
};
|
};
|
||||||
@ -197,7 +197,7 @@ Struct(GPU_D12_CommandList)
|
|||||||
GPU_D12_CommandListPool *pool;
|
GPU_D12_CommandListPool *pool;
|
||||||
struct ID3D12CommandAllocator *ca;
|
struct ID3D12CommandAllocator *ca;
|
||||||
struct ID3D12GraphicsCommandList *cl;
|
struct ID3D12GraphicsCommandList *cl;
|
||||||
P_Lock global_record_lock;
|
Lock global_record_lock;
|
||||||
|
|
||||||
GPU_D12_Pipeline *cur_pipeline;
|
GPU_D12_Pipeline *cur_pipeline;
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ Struct(GPU_D12_CpuDescriptorHeap)
|
|||||||
{
|
{
|
||||||
enum D3D12_DESCRIPTOR_HEAP_TYPE type;
|
enum D3D12_DESCRIPTOR_HEAP_TYPE type;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
P_Mutex mutex;
|
Mutex mutex;
|
||||||
|
|
||||||
u32 descriptor_size;
|
u32 descriptor_size;
|
||||||
u32 num_descriptors_reserved;
|
u32 num_descriptors_reserved;
|
||||||
@ -352,23 +352,23 @@ Struct(GPU_D12_SharedState)
|
|||||||
Atomic32 initialized;
|
Atomic32 initialized;
|
||||||
|
|
||||||
/* Descriptor heaps pool */
|
/* Descriptor heaps pool */
|
||||||
P_Mutex command_descriptor_heaps_mutex;
|
Mutex command_descriptor_heaps_mutex;
|
||||||
Arena *command_descriptor_heaps_arena;
|
Arena *command_descriptor_heaps_arena;
|
||||||
GPU_D12_CommandDescriptorHeap *first_submitted_command_descriptor_heap;
|
GPU_D12_CommandDescriptorHeap *first_submitted_command_descriptor_heap;
|
||||||
GPU_D12_CommandDescriptorHeap *last_submitted_command_descriptor_heap;
|
GPU_D12_CommandDescriptorHeap *last_submitted_command_descriptor_heap;
|
||||||
|
|
||||||
/* Command buffers pool */
|
/* Command buffers pool */
|
||||||
P_Mutex command_buffers_mutex;
|
Mutex command_buffers_mutex;
|
||||||
Arena *command_buffers_arena;
|
Arena *command_buffers_arena;
|
||||||
Dict *command_buffers_dict;
|
Dict *command_buffers_dict;
|
||||||
|
|
||||||
/* Resources pool */
|
/* Resources pool */
|
||||||
P_Mutex resources_mutex;
|
Mutex resources_mutex;
|
||||||
Arena *resources_arena;
|
Arena *resources_arena;
|
||||||
GPU_D12_Resource *first_free_resource;
|
GPU_D12_Resource *first_free_resource;
|
||||||
|
|
||||||
/* Swapchains pool */
|
/* Swapchains pool */
|
||||||
P_Mutex swapchains_mutex;
|
Mutex swapchains_mutex;
|
||||||
Arena *swapchains_arena;
|
Arena *swapchains_arena;
|
||||||
GPU_D12_Swapchain *first_free_swapchain;
|
GPU_D12_Swapchain *first_free_swapchain;
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ Struct(GPU_D12_SharedState)
|
|||||||
TAR_Archive dxc_archive;
|
TAR_Archive dxc_archive;
|
||||||
|
|
||||||
/* Pipeline cache */
|
/* Pipeline cache */
|
||||||
P_Mutex pipelines_mutex;
|
Mutex pipelines_mutex;
|
||||||
Arena *pipelines_arena;
|
Arena *pipelines_arena;
|
||||||
GPU_D12_Pipeline *first_free_pipeline;
|
GPU_D12_Pipeline *first_free_pipeline;
|
||||||
Dict *pipeline_descs;
|
Dict *pipeline_descs;
|
||||||
@ -385,7 +385,7 @@ Struct(GPU_D12_SharedState)
|
|||||||
GPU_D12_PipelineScope *first_free_pipeline_scope;
|
GPU_D12_PipelineScope *first_free_pipeline_scope;
|
||||||
|
|
||||||
/* Fenced release queue */
|
/* Fenced release queue */
|
||||||
P_Mutex fenced_releases_mutex;
|
Mutex fenced_releases_mutex;
|
||||||
Arena *fenced_releases_arena;
|
Arena *fenced_releases_arena;
|
||||||
u64 fenced_release_targets[DX12_NUM_QUEUES];
|
u64 fenced_release_targets[DX12_NUM_QUEUES];
|
||||||
|
|
||||||
@ -407,14 +407,14 @@ Struct(GPU_D12_SharedState)
|
|||||||
GPU_D12_CpuDescriptorHeap *rtv_heap;
|
GPU_D12_CpuDescriptorHeap *rtv_heap;
|
||||||
|
|
||||||
/* Command queues */
|
/* Command queues */
|
||||||
P_Mutex global_command_list_record_mutex;
|
Mutex global_command_list_record_mutex;
|
||||||
P_Mutex global_submit_mutex;
|
Mutex global_submit_mutex;
|
||||||
GPU_D12_CommandQueue *command_queues[DX12_NUM_QUEUES];
|
GPU_D12_CommandQueue *command_queues[DX12_NUM_QUEUES];
|
||||||
|
|
||||||
/* Evictor job */
|
/* Evictor job */
|
||||||
Counter evictor_job_counter;
|
Counter evictor_job_counter;
|
||||||
P_Cv evictor_wake_cv;
|
Cv evictor_wake_cv;
|
||||||
P_Mutex evictor_wake_mutex;
|
Mutex evictor_wake_mutex;
|
||||||
i64 evictor_wake_gen;
|
i64 evictor_wake_gen;
|
||||||
b32 evictor_shutdown;
|
b32 evictor_shutdown;
|
||||||
};
|
};
|
||||||
@ -457,7 +457,7 @@ void GPU_D12_InitNoise(void);
|
|||||||
* Shader compilation
|
* Shader compilation
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
JobDecl(GPU_D12_CompileShaderJob, { Arena *arena; GPU_D12_ShaderDesc *decs; GPU_D12_CompiledShaderResult results; });
|
JobDecl(GPU_D12_CompileShaderJob, { Arena *arena; GPU_D12_ShaderDesc *descs; GPU_D12_CompiledShaderResult *results; });
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Pipeline
|
* Pipeline
|
||||||
|
|||||||
@ -873,7 +873,7 @@ void JSON_Parse(Arena *arena, JSON_Parser *p)
|
|||||||
|
|
||||||
if (is_new_parent)
|
if (is_new_parent)
|
||||||
{
|
{
|
||||||
/* PushStruct self back to stack to re-check for closing brace later */
|
/* Push self back to stack to re-check for closing brace later */
|
||||||
*PushStructNoZero(scratch.arena, JSON_Blob *) = json;
|
*PushStructNoZero(scratch.arena, JSON_Blob *) = json;
|
||||||
++stack_count;
|
++stack_count;
|
||||||
|
|
||||||
|
|||||||
@ -53,10 +53,10 @@ MIX_Track *MIX_TrackFromHandle(MIX_Handle handle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MIX_Track *MIX_AllocTrackLocked(P_Lock *lock, SND_Sound *sound)
|
MIX_Track *MIX_AllocTrackLocked(Lock *lock, SND_Sound *sound)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
P_AssertLockedE(lock, &g->mutex);
|
AssertLockedE(lock, &g->mutex);
|
||||||
LAX lock;
|
LAX lock;
|
||||||
|
|
||||||
MIX_Track *track = 0;
|
MIX_Track *track = 0;
|
||||||
@ -100,10 +100,10 @@ MIX_Track *MIX_AllocTrackLocked(P_Lock *lock, SND_Sound *sound)
|
|||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIX_ReleaseTrackLocked(P_Lock *lock, MIX_Track *track)
|
void MIX_ReleaseTrackLocked(Lock *lock, MIX_Track *track)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
P_AssertLockedE(lock, &g->mutex);
|
AssertLockedE(lock, &g->mutex);
|
||||||
LAX lock;
|
LAX lock;
|
||||||
|
|
||||||
/* Remove from playing list */
|
/* Remove from playing list */
|
||||||
@ -155,12 +155,12 @@ MIX_Handle MIX_PlaySoundEx(SND_Sound *sound, MIX_TrackDesc desc)
|
|||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
MIX_Track *track;
|
MIX_Track *track;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->mutex);
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
track = MIX_AllocTrackLocked(&lock, sound);
|
track = MIX_AllocTrackLocked(&lock, sound);
|
||||||
track->desc = desc;
|
track->desc = desc;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
return MIX_HandleFromTrack(track);
|
return MIX_HandleFromTrack(track);
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ MIX_TrackDesc MIX_TrackDescFromHandle(MIX_Handle handle)
|
|||||||
if (track)
|
if (track)
|
||||||
{
|
{
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
P_Lock lock = P_LockE(&g->mutex);
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
/* Confirm handle is still valid now that we're locked */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
track = MIX_TrackFromHandle(handle);
|
track = MIX_TrackFromHandle(handle);
|
||||||
@ -184,7 +184,7 @@ MIX_TrackDesc MIX_TrackDescFromHandle(MIX_Handle handle)
|
|||||||
result = track->desc;
|
result = track->desc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -198,7 +198,7 @@ void MIX_UpdateTrack(MIX_Handle handle, MIX_TrackDesc desc)
|
|||||||
if (track)
|
if (track)
|
||||||
{
|
{
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
P_Lock lock = P_LockE(&g->mutex);
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
/* Confirm handle is still valid now that we're locked */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
track = MIX_TrackFromHandle(handle);
|
track = MIX_TrackFromHandle(handle);
|
||||||
@ -207,19 +207,19 @@ void MIX_UpdateTrack(MIX_Handle handle, MIX_TrackDesc desc)
|
|||||||
track->desc = desc;
|
track->desc = desc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIX_UpdateListener(Vec2 pos, Vec2 dir)
|
void MIX_UpdateListener(Vec2 pos, Vec2 dir)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
P_Lock lock = P_LockE(&g->mutex);
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
g->listener_pos = pos;
|
g->listener_pos = pos;
|
||||||
g->listener_dir = NormVec2(dir);
|
g->listener_dir = NormVec2(dir);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -260,7 +260,7 @@ MIX_PcmF32 MIX_MixAllTracks(Arena *arena, u64 frame_count)
|
|||||||
MIX_MixData **mixes = 0;
|
MIX_MixData **mixes = 0;
|
||||||
u64 mixes_count = 0;
|
u64 mixes_count = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->mutex);
|
Lock lock = LockE(&g->mutex);
|
||||||
|
|
||||||
/* Read listener info */
|
/* Read listener info */
|
||||||
listener_pos = g->listener_pos;
|
listener_pos = g->listener_pos;
|
||||||
@ -276,7 +276,7 @@ MIX_PcmF32 MIX_MixAllTracks(Arena *arena, u64 frame_count)
|
|||||||
mixes[mixes_count++] = mix;
|
mixes[mixes_count++] = mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Process mix data
|
//- Process mix data
|
||||||
@ -461,7 +461,7 @@ MIX_PcmF32 MIX_MixAllTracks(Arena *arena, u64 frame_count)
|
|||||||
//- Update track effect data
|
//- Update track effect data
|
||||||
{
|
{
|
||||||
__profn("Update track effect data");
|
__profn("Update track effect data");
|
||||||
P_Lock lock = P_LockE(&g->mutex);
|
Lock lock = LockE(&g->mutex);
|
||||||
for (u64 i = 0; i < mixes_count; ++i)
|
for (u64 i = 0; i < mixes_count; ++i)
|
||||||
{
|
{
|
||||||
MIX_MixData *mix = mixes[i];
|
MIX_MixData *mix = mixes[i];
|
||||||
@ -475,7 +475,7 @@ MIX_PcmF32 MIX_MixAllTracks(Arena *arena, u64 frame_count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
|
|||||||
@ -79,7 +79,7 @@ Struct(MIX_Track){
|
|||||||
|
|
||||||
Struct(MIX_SharedState)
|
Struct(MIX_SharedState)
|
||||||
{
|
{
|
||||||
P_Mutex mutex;
|
Mutex mutex;
|
||||||
|
|
||||||
/* Listener */
|
/* Listener */
|
||||||
Vec2 listener_pos;
|
Vec2 listener_pos;
|
||||||
@ -106,8 +106,8 @@ MIX_StartupReceipt MIX_Startup(void);
|
|||||||
|
|
||||||
MIX_Handle MIX_HandleFromTrack(MIX_Track *track);
|
MIX_Handle MIX_HandleFromTrack(MIX_Track *track);
|
||||||
MIX_Track *MIX_TrackFromHandle(MIX_Handle handle);
|
MIX_Track *MIX_TrackFromHandle(MIX_Handle handle);
|
||||||
MIX_Track *MIX_AllocTrackLocked(P_Lock *lock, SND_Sound *sound);
|
MIX_Track *MIX_AllocTrackLocked(Lock *lock, SND_Sound *sound);
|
||||||
void MIX_ReleaseTrackLocked(P_Lock *lock, MIX_Track *track);
|
void MIX_ReleaseTrackLocked(Lock *lock, MIX_Track *track);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Mixer state operations
|
//~ Mixer state operations
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
# include <mfidl.h>
|
# include <mfidl.h>
|
||||||
# include <mfreadwrite.h>
|
# include <mfreadwrite.h>
|
||||||
# include <Shlwapi.h>
|
# include <Shlwapi.h>
|
||||||
|
# include <objidl.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#pragma comment(lib, "mfplat")
|
#pragma comment(lib, "mfplat")
|
||||||
@ -121,7 +122,8 @@ MP3_Result MP3_Decode(Arena *arena, String encoded, u32 sample_rate, MP3_DecodeF
|
|||||||
|
|
||||||
IMFSourceReader_Release(reader);
|
IMFSourceReader_Release(reader);
|
||||||
IMFByteStream_Close(byte_stream);
|
IMFByteStream_Close(byte_stream);
|
||||||
IStream_Release(i_stream);
|
/* FIXME: Enable this */
|
||||||
|
//IStream_Release(i_stream);
|
||||||
MFShutdown();
|
MFShutdown();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -542,7 +542,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host)
|
|||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
|
|
||||||
N_EventList events = ZI;
|
N_EventList events = ZI;
|
||||||
i64 now_ns = P_TimeNs();
|
i64 now_ns = TimeNs();
|
||||||
{
|
{
|
||||||
__profn("Read packets");
|
__profn("Read packets");
|
||||||
|
|
||||||
|
|||||||
@ -246,7 +246,7 @@ Struct(N_Host)
|
|||||||
u64 num_msg_assembler_lookup_bins;
|
u64 num_msg_assembler_lookup_bins;
|
||||||
|
|
||||||
/* Double buffer for incoming data */
|
/* Double buffer for incoming data */
|
||||||
P_Mutex rcv_buffer_write_mutex;
|
Mutex rcv_buffer_write_mutex;
|
||||||
N_RcvBuffer *rcv_buffer_read;
|
N_RcvBuffer *rcv_buffer_read;
|
||||||
N_RcvBuffer *rcv_buffer_write;
|
N_RcvBuffer *rcv_buffer_write;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include "platform_snc.c"
|
|
||||||
#include "platform_log.c"
|
#include "platform_log.c"
|
||||||
|
|
||||||
#if PlatformIsWindows
|
#if PlatformIsWindows
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
|
|
||||||
#include "platform_snc.h"
|
|
||||||
#include "platform_core.h"
|
#include "platform_core.h"
|
||||||
#include "platform_log.h"
|
#include "platform_log.h"
|
||||||
|
|
||||||
|
|||||||
@ -311,7 +311,6 @@ typedef P_ExitFuncDef(P_ExitFunc);
|
|||||||
//~ @hookdecl Time helper operations
|
//~ @hookdecl Time helper operations
|
||||||
|
|
||||||
P_DateTime P_LocalTime(void);
|
P_DateTime P_LocalTime(void);
|
||||||
i64 P_TimeNs(void);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl File system operations
|
//~ @hookdecl File system operations
|
||||||
@ -403,9 +402,6 @@ void P_WriteSock(P_Sock *sock, P_Address address, String data);
|
|||||||
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);
|
||||||
String P_GetClipboardText(Arena *arena);
|
String P_GetClipboardText(Arena *arena);
|
||||||
u32 P_GetLogicalProcessorCount(void);
|
|
||||||
u32 P_GetThreadId(void);
|
|
||||||
i64 P_GetCurrentSchedulerPeriodNs(void);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl Sleep
|
//~ @hookdecl Sleep
|
||||||
|
|||||||
@ -32,7 +32,7 @@ void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level)
|
|||||||
{
|
{
|
||||||
P_SharedLogState *ctx = &P_shared_log_state;
|
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);
|
Lock lock = LockE(&ctx->callbacks_mutex);
|
||||||
{
|
{
|
||||||
LogEventCallback *callback = PushStruct(ctx->callbacks_arena, LogEventCallback);
|
LogEventCallback *callback = PushStruct(ctx->callbacks_arena, LogEventCallback);
|
||||||
callback->func = func;
|
callback->func = func;
|
||||||
@ -47,7 +47,7 @@ void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level)
|
|||||||
}
|
}
|
||||||
ctx->last_callback = callback;
|
ctx->last_callback = callback;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -149,12 +149,12 @@ void P_Log_(i32 level, String msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u32 tid = P_GetThreadId();
|
u32 tid = ThreadId();
|
||||||
|
|
||||||
|
|
||||||
//- Format message
|
//- Format message
|
||||||
P_DateTime datetime = P_LocalTime();
|
P_DateTime datetime = P_LocalTime();
|
||||||
i64 time_ns = P_TimeNs();
|
i64 time_ns = TimeNs();
|
||||||
String shorthand = settings.shorthand;
|
String shorthand = settings.shorthand;
|
||||||
|
|
||||||
#if P_IncludeLogSourceLocation
|
#if P_IncludeLogSourceLocation
|
||||||
@ -217,7 +217,7 @@ void P_Log_(i32 level, String msg)
|
|||||||
event.line = line;
|
event.line = line;
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockS(&ctx->callbacks_mutex);
|
Lock lock = LockS(&ctx->callbacks_mutex);
|
||||||
for (LogEventCallback *callback = ctx->first_callback; callback; callback = callback->next)
|
for (LogEventCallback *callback = ctx->first_callback; callback; callback = callback->next)
|
||||||
{
|
{
|
||||||
if (level <= callback->level)
|
if (level <= callback->level)
|
||||||
@ -226,7 +226,7 @@ void P_Log_(i32 level, String msg)
|
|||||||
callback->func(event);
|
callback->func(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
|
|||||||
@ -63,7 +63,7 @@ Struct(P_SharedLogState)
|
|||||||
{
|
{
|
||||||
Atomic32 initialized;
|
Atomic32 initialized;
|
||||||
|
|
||||||
P_Mutex callbacks_mutex;
|
Mutex callbacks_mutex;
|
||||||
Arena *callbacks_arena;
|
Arena *callbacks_arena;
|
||||||
LogEventCallback *first_callback;
|
LogEventCallback *first_callback;
|
||||||
LogEventCallback *last_callback;
|
LogEventCallback *last_callback;
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
////////////////////////////////
|
|
||||||
//~ Mutex types
|
|
||||||
|
|
||||||
#define P_DefaultMutexSpin 4000
|
|
||||||
|
|
||||||
AlignedStruct(P_Mutex, 64)
|
|
||||||
{
|
|
||||||
/* Bit 31 = Exclusive lock is held
|
|
||||||
* Bit 30 = Exclusive lock is pending
|
|
||||||
* Bit 0-30 = Shared locks count
|
|
||||||
*/
|
|
||||||
Atomic32 v;
|
|
||||||
|
|
||||||
#if RtcIsEnabled
|
|
||||||
Atomic32 exclusive_fiber_id;
|
|
||||||
u8 _pad[56];
|
|
||||||
#else
|
|
||||||
u8 _pad[60];
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
StaticAssert(sizeof(P_Mutex) == 64); /* Padding validation */
|
|
||||||
StaticAssert(alignof(P_Mutex) == 64); /* Prevent false sharing */
|
|
||||||
|
|
||||||
Struct(P_Lock)
|
|
||||||
{
|
|
||||||
P_Mutex *mutex;
|
|
||||||
b32 exclusive;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Condition variable types
|
|
||||||
|
|
||||||
AlignedStruct(P_Cv, 64)
|
|
||||||
{
|
|
||||||
Atomic64 wake_gen;
|
|
||||||
u8 _pad[56];
|
|
||||||
};
|
|
||||||
StaticAssert(sizeof(P_Cv) == 64); /* Padding validation */
|
|
||||||
StaticAssert(alignof(P_Cv) == 64); /* Prevent false sharing */
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Counter types
|
|
||||||
|
|
||||||
AlignedStruct(Counter, 64)
|
|
||||||
{
|
|
||||||
Atomic64 v;
|
|
||||||
u8 _pad[56];
|
|
||||||
};
|
|
||||||
StaticAssert(sizeof(Counter) == 64); /* Padding validation */
|
|
||||||
StaticAssert(alignof(Counter) == 64); /* Prevent false sharing */
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Mutex operations
|
|
||||||
|
|
||||||
P_Lock P_LockSpinE(P_Mutex *m, i32 spin);
|
|
||||||
P_Lock P_LockSpinS(P_Mutex *m, i32 spin);
|
|
||||||
|
|
||||||
P_Lock P_LockE(P_Mutex *m);
|
|
||||||
P_Lock P_LockS(P_Mutex *m);
|
|
||||||
|
|
||||||
void P_Unlock(P_Lock *lock);
|
|
||||||
|
|
||||||
//- Lock assertion
|
|
||||||
#if RtcIsEnabled
|
|
||||||
# define P_AssertLockedE(l, m) Assert((l)->mutex == (m) && (l)->exclusive == 1)
|
|
||||||
# define P_AssertLockedES(l, m) Assert((l)->mutex == (m))
|
|
||||||
#else
|
|
||||||
# define P_AssertLockedE(l, m) LAX l
|
|
||||||
# define P_AssertLockedES(l, m) LAX l
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Condition variable operations
|
|
||||||
|
|
||||||
void P_WaitOnCv(P_Cv *cv, P_Lock *lock);
|
|
||||||
void P_WaitOnCvTime(P_Cv *cv, P_Lock *l, i64 timeout_ns);
|
|
||||||
void P_SignalCv(P_Cv *cv, i32 count);
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Counter operations
|
|
||||||
|
|
||||||
void P_CounterAdd(Counter *counter, i64 x);
|
|
||||||
void P_WaitOnCounter(Counter *counter);
|
|
||||||
@ -72,7 +72,7 @@ P_W32_Window *P_W32_AllocWindow(void)
|
|||||||
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
||||||
P_W32_Window *window = 0;
|
P_W32_Window *window = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->windows_mutex);
|
Lock lock = LockE(&g->windows_mutex);
|
||||||
if (g->first_free_window)
|
if (g->first_free_window)
|
||||||
{
|
{
|
||||||
window = g->first_free_window;
|
window = g->first_free_window;
|
||||||
@ -82,7 +82,7 @@ P_W32_Window *P_W32_AllocWindow(void)
|
|||||||
{
|
{
|
||||||
window = PushStructNoZero(g->windows_arena, P_W32_Window);
|
window = PushStructNoZero(g->windows_arena, P_W32_Window);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(window);
|
ZeroStruct(window);
|
||||||
|
|
||||||
@ -93,9 +93,9 @@ P_W32_Window *P_W32_AllocWindow(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. */
|
||||||
P_CounterAdd(&window->ready_fence, 1);
|
AddCounter(&window->ready_fence, 1);
|
||||||
window->window_thread = P_W32_AllocThread(&W32_WindowThreadEntryFunc, window, Lit("Window thread"), PROF_THREAD_GROUP_WINDOW);
|
window->window_thread = W32_AllocThread(&P_W32_WindowThreadEntryFunc, window, Lit("Window thread"), PROF_THREAD_GROUP_WINDOW);
|
||||||
P_WaitOnCounter(&window->ready_fence);
|
WaitOnCounter(&window->ready_fence);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
@ -106,14 +106,14 @@ void P_W32_ReleaseWindow(P_W32_Window *window)
|
|||||||
Atomic32FetchSet(&window->shutdown, 1);
|
Atomic32FetchSet(&window->shutdown, 1);
|
||||||
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
||||||
P_W32_WakeWindow(window);
|
P_W32_WakeWindow(window);
|
||||||
P_W32_WaitReleaseThread(window->window_thread);
|
W32_WaitReleaseThread(window->window_thread);
|
||||||
|
|
||||||
P_Lock lock = P_LockE(&g->windows_mutex);
|
Lock lock = LockE(&g->windows_mutex);
|
||||||
{
|
{
|
||||||
window->next_free = g->first_free_window;
|
window->next_free = g->first_free_window;
|
||||||
g->first_free_window = window;
|
g->first_free_window = window;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND P_W32_InitWindow(P_W32_Window *window)
|
HWND P_W32_InitWindow(P_W32_Window *window)
|
||||||
@ -302,7 +302,7 @@ void P_W32_UpdateWindowFromSettings(P_W32_Window *window, P_WindowSettings *sett
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Win32 window thread
|
//~ Win32 window thread
|
||||||
|
|
||||||
W32_ThreadDef(W32_WindowThreadEntryFunc, arg)
|
W32_ThreadDef(P_W32_WindowThreadEntryFunc, arg)
|
||||||
{
|
{
|
||||||
P_W32_Window *window = (P_W32_Window *)arg;
|
P_W32_Window *window = (P_W32_Window *)arg;
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ W32_ThreadDef(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);
|
||||||
P_CounterAdd(&window->ready_fence, -1);
|
AddCounter(&window->ready_fence, -1);
|
||||||
|
|
||||||
while (!Atomic32Fetch(&window->shutdown))
|
while (!Atomic32Fetch(&window->shutdown))
|
||||||
{
|
{
|
||||||
@ -335,11 +335,11 @@ W32_ThreadDef(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)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
P_Lock lock = P_LockE(&window->event_arena_swp_mutex);
|
Lock lock = LockE(&window->event_arena_swp_mutex);
|
||||||
{
|
{
|
||||||
*PushStruct(window->event_arenas[window->current_event_arena_index], P_WindowEvent) = event;
|
*PushStruct(window->event_arenas[window->current_event_arena_index], P_WindowEvent) = event;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_W32_WakeWindow(P_W32_Window *window)
|
void P_W32_WakeWindow(P_W32_Window *window)
|
||||||
@ -785,15 +785,6 @@ P_DateTime P_LocalTime(void)
|
|||||||
return P_W32_DateTimeFromWin32SystemTime(lt);
|
return P_W32_DateTimeFromWin32SystemTime(lt);
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 P_TimeNs(void)
|
|
||||||
{
|
|
||||||
struct P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
|
||||||
LARGE_INTEGER qpc;
|
|
||||||
QueryPerformanceCounter(&qpc);
|
|
||||||
i64 result = (qpc.QuadPart - g->timer_start_qpc) * g->ns_per_qpc;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdef File system hooks
|
//~ @hookdef File system hooks
|
||||||
|
|
||||||
@ -1166,7 +1157,7 @@ P_Watch *P_AllocWatch(String dir_path)
|
|||||||
|
|
||||||
P_W32_Watch *w32_watch = 0;
|
P_W32_Watch *w32_watch = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->watches_mutex);
|
Lock lock = LockE(&g->watches_mutex);
|
||||||
{
|
{
|
||||||
if (g->watches_first_free)
|
if (g->watches_first_free)
|
||||||
{
|
{
|
||||||
@ -1178,7 +1169,7 @@ P_Watch *P_AllocWatch(String dir_path)
|
|||||||
w32_watch = PushStructNoZero(g->watches_arena, P_W32_Watch);
|
w32_watch = PushStructNoZero(g->watches_arena, P_W32_Watch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(w32_watch);
|
ZeroStruct(w32_watch);
|
||||||
|
|
||||||
@ -1206,12 +1197,12 @@ void P_ReleaseWatch(P_Watch *dw)
|
|||||||
CloseHandle(w32_watch->dir_handle);
|
CloseHandle(w32_watch->dir_handle);
|
||||||
CloseHandle(w32_watch->wake_handle);
|
CloseHandle(w32_watch->wake_handle);
|
||||||
|
|
||||||
P_Lock lock = P_LockE(&g->watches_mutex);
|
Lock lock = LockE(&g->watches_mutex);
|
||||||
{
|
{
|
||||||
w32_watch->next_free = g->watches_first_free;
|
w32_watch->next_free = g->watches_first_free;
|
||||||
g->watches_first_free = w32_watch;
|
g->watches_first_free = w32_watch;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
P_WatchInfoList P_ReadWatchWait(Arena *arena, P_Watch *dw)
|
P_WatchInfoList P_ReadWatchWait(Arena *arena, P_Watch *dw)
|
||||||
@ -1369,10 +1360,10 @@ P_WindowEventArray P_PopWindowEvents(Arena *arena, P_Window *p_window)
|
|||||||
i32 event_arena_index = 0;
|
i32 event_arena_index = 0;
|
||||||
{
|
{
|
||||||
/* Swap event buffers */
|
/* Swap event buffers */
|
||||||
P_Lock lock = P_LockE(&window->event_arena_swp_mutex);
|
Lock lock = LockE(&window->event_arena_swp_mutex);
|
||||||
event_arena_index = window->current_event_arena_index;
|
event_arena_index = window->current_event_arena_index;
|
||||||
window->current_event_arena_index = 1 - window->current_event_arena_index;
|
window->current_event_arena_index = 1 - window->current_event_arena_index;
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
Arena *events_arena = window->event_arenas[event_arena_index];
|
Arena *events_arena = window->event_arenas[event_arena_index];
|
||||||
P_WindowEventArray events = ZI;
|
P_WindowEventArray events = ZI;
|
||||||
@ -1388,11 +1379,11 @@ void P_UpdateWindowSettings(P_Window *p_window, P_WindowSettings *settings)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
P_W32_Window *window = (P_W32_Window *)p_window;
|
P_W32_Window *window = (P_W32_Window *)p_window;
|
||||||
P_Lock lock = P_LockE(&window->settings_mutex);
|
Lock lock = LockE(&window->settings_mutex);
|
||||||
{
|
{
|
||||||
P_W32_UpdateWindowFromSettings(window, settings);
|
P_W32_UpdateWindowFromSettings(window, settings);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Lock settings mutex for these functions */
|
/* FIXME: Lock settings mutex for these functions */
|
||||||
@ -1407,7 +1398,7 @@ void P_ShowWindow(P_Window *p_window)
|
|||||||
{
|
{
|
||||||
P_W32_Window *window = (P_W32_Window *)p_window;
|
P_W32_Window *window = (P_W32_Window *)p_window;
|
||||||
HWND hwnd = window->hwnd;
|
HWND hwnd = window->hwnd;
|
||||||
P_Lock lock = P_LockE(&window->settings_mutex);
|
Lock lock = LockE(&window->settings_mutex);
|
||||||
{
|
{
|
||||||
i32 show_cmd = SW_NORMAL;
|
i32 show_cmd = SW_NORMAL;
|
||||||
P_WindowSettings *settings = &window->settings;
|
P_WindowSettings *settings = &window->settings;
|
||||||
@ -1423,7 +1414,7 @@ void P_ShowWindow(P_Window *p_window)
|
|||||||
ShowWindow(hwnd, show_cmd);
|
ShowWindow(hwnd, show_cmd);
|
||||||
BringWindowToTop(hwnd);
|
BringWindowToTop(hwnd);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_SetWindowCursorPos(P_Window *p_window, Vec2 pos)
|
void P_SetWindowCursorPos(P_Window *p_window, Vec2 pos)
|
||||||
@ -1699,7 +1690,7 @@ P_Sock *P_AllocSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size)
|
|||||||
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
||||||
P_W32_Sock *ws = 0;
|
P_W32_Sock *ws = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->socks_mutex);
|
Lock lock = LockE(&g->socks_mutex);
|
||||||
if (g->first_free_sock)
|
if (g->first_free_sock)
|
||||||
{
|
{
|
||||||
ws = g->first_free_sock;
|
ws = g->first_free_sock;
|
||||||
@ -1709,7 +1700,7 @@ P_Sock *P_AllocSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size)
|
|||||||
{
|
{
|
||||||
ws = PushStructNoZero(g->socks_arena, P_W32_Sock);
|
ws = PushStructNoZero(g->socks_arena, P_W32_Sock);
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(ws);
|
ZeroStruct(ws);
|
||||||
|
|
||||||
@ -1734,12 +1725,12 @@ void P_ReleaseSock(P_Sock *sock)
|
|||||||
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
||||||
P_W32_Sock *ws = (P_W32_Sock *)sock;
|
P_W32_Sock *ws = (P_W32_Sock *)sock;
|
||||||
closesocket(ws->sock);
|
closesocket(ws->sock);
|
||||||
P_Lock lock = P_LockE(&g->socks_mutex);
|
Lock lock = LockE(&g->socks_mutex);
|
||||||
{
|
{
|
||||||
ws->next_free = g->first_free_sock;
|
ws->next_free = g->first_free_sock;
|
||||||
g->first_free_sock = ws;
|
g->first_free_sock = ws;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock)
|
P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock)
|
||||||
@ -1885,22 +1876,6 @@ String P_GetClipboardText(Arena *arena)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 P_GetLogicalProcessorCount(void)
|
|
||||||
{
|
|
||||||
return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 P_GetThreadId(void)
|
|
||||||
{
|
|
||||||
return GetCurrentThreadId();
|
|
||||||
}
|
|
||||||
|
|
||||||
i64 P_GetCurrentSchedulerPeriodNs(void)
|
|
||||||
{
|
|
||||||
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
|
||||||
return Atomic64Fetch(&g->current_scheduler_cycle_period_ns.v);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdef Sleep hooks
|
//~ @hookdef Sleep hooks
|
||||||
|
|
||||||
@ -1908,19 +1883,19 @@ void P_SleepPrecise(i64 sleep_time_ns)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
i64 big_sleep = P_GetCurrentSchedulerPeriodNs();
|
i64 big_sleep = GetCurrentSchedulerPeriodNs();
|
||||||
i64 tolerance = (f64)big_sleep * 0.5;
|
i64 tolerance = (f64)big_sleep * 0.5;
|
||||||
//i64 tolerance = 1000000000;
|
//i64 tolerance = 1000000000;
|
||||||
|
|
||||||
i64 now_ns = P_TimeNs();
|
i64 now_ns = TimeNs();
|
||||||
i64 target_ns = now_ns + sleep_time_ns;
|
i64 target_ns = now_ns + sleep_time_ns;
|
||||||
|
|
||||||
/* Sleep */
|
/* Sleep */
|
||||||
while (now_ns < target_ns - big_sleep - tolerance)
|
while (now_ns < target_ns - big_sleep - tolerance)
|
||||||
{
|
{
|
||||||
__profn("Sleep part");
|
__profn("Sleep part");
|
||||||
P_Wait(0, 0, 0, big_sleep);
|
FutexWait(0, 0, 0, big_sleep);
|
||||||
now_ns = P_TimeNs();
|
now_ns = TimeNs();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spin */
|
/* Spin */
|
||||||
@ -1929,7 +1904,7 @@ void P_SleepPrecise(i64 sleep_time_ns)
|
|||||||
while (now_ns < target_ns)
|
while (now_ns < target_ns)
|
||||||
{
|
{
|
||||||
_mm_pause();
|
_mm_pause();
|
||||||
now_ns = P_TimeNs();
|
now_ns = TimeNs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1938,7 +1913,7 @@ void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns)
|
|||||||
{
|
{
|
||||||
if (last_frame_time_ns != 0 && target_dt_ns > 0)
|
if (last_frame_time_ns != 0 && target_dt_ns > 0)
|
||||||
{
|
{
|
||||||
i64 now_ns = P_TimeNs();
|
i64 now_ns = TimeNs();
|
||||||
i64 last_frame_dt_ns = now_ns - last_frame_time_ns;
|
i64 last_frame_dt_ns = now_ns - last_frame_time_ns;
|
||||||
i64 sleep_time_ns = target_dt_ns - last_frame_dt_ns;
|
i64 sleep_time_ns = target_dt_ns - last_frame_dt_ns;
|
||||||
if (sleep_time_ns > 0)
|
if (sleep_time_ns > 0)
|
||||||
@ -2073,7 +2048,7 @@ void P_W32_InitBtnTable(void)
|
|||||||
g->vk_btn_table[VK_OEM_1] = P_Btn_Semicolon;
|
g->vk_btn_table[VK_OEM_1] = P_Btn_Semicolon;
|
||||||
}
|
}
|
||||||
|
|
||||||
JobDef(P_W32_AppStartupJob, UNUSED job)
|
JobDef(P_W32_AppStartupJob, UNUSED sig, UNUSED id)
|
||||||
{
|
{
|
||||||
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
@ -2085,7 +2060,7 @@ JobDef(P_W32_AppStartupJob, UNUSED job)
|
|||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
JobDef(P_W32_AppShutdownJob, _)
|
JobDef(P_W32_AppShutdownJob, UNUSED sig, UNUSED id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
P_W32_SharedCtx *g = &P_W32_shared_ctx;
|
||||||
@ -2188,18 +2163,6 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
g->exit_begin_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->exit_end_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
|
||||||
/* Init timer */
|
|
||||||
{
|
|
||||||
LARGE_INTEGER qpf;
|
|
||||||
QueryPerformanceFrequency(&qpf);
|
|
||||||
g->ns_per_qpc = 1000000000 / qpf.QuadPart;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
LARGE_INTEGER qpc;
|
|
||||||
QueryPerformanceCounter(&qpc);
|
|
||||||
g->timer_start_qpc = qpc.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert main thread to fiber */
|
/* Convert main thread to fiber */
|
||||||
W32_AllocFiber(0);
|
W32_AllocFiber(0);
|
||||||
|
|
||||||
@ -2253,9 +2216,6 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
LAX success;
|
LAX success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init threads pool */
|
|
||||||
g->threads_arena = AllocArena(Gibi(64));
|
|
||||||
|
|
||||||
/* Init watches pool */
|
/* Init watches pool */
|
||||||
g->watches_arena = AllocArena(Gibi(64));
|
g->watches_arena = AllocArena(Gibi(64));
|
||||||
|
|
||||||
@ -2271,7 +2231,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
/* Run app start job */
|
/* Run app start job */
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
{
|
{
|
||||||
P_Run(1, P_W32_AppStartupJob, 0, PoolKind_Floating, PriorityKind_High, 0);
|
RunJob(1, P_W32_AppStartupJob, 0, PoolKind_Floating, PriorityKind_High, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for startup end or panic */
|
/* Wait for startup end or panic */
|
||||||
@ -2299,7 +2259,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
/* Run exit callbacks job */
|
/* Run exit callbacks job */
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
{
|
{
|
||||||
P_Run(1, P_W32_AppShutdownJob, 0, PoolKind_Floating, PriorityKind_High, 0);
|
RunJob(1, P_W32_AppShutdownJob, 0, PoolKind_Floating, PriorityKind_High, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for exit end or panic */
|
/* Wait for exit end or panic */
|
||||||
|
|||||||
@ -39,7 +39,7 @@ Struct(P_W32_Window)
|
|||||||
|
|
||||||
u16 utf16_high_surrogate_last_input;
|
u16 utf16_high_surrogate_last_input;
|
||||||
|
|
||||||
P_Mutex settings_mutex;
|
Mutex settings_mutex;
|
||||||
P_WindowSettings settings;
|
P_WindowSettings settings;
|
||||||
|
|
||||||
i32 monitor_width;
|
i32 monitor_width;
|
||||||
@ -57,7 +57,7 @@ Struct(P_W32_Window)
|
|||||||
Atomic32 topmost_toggles;
|
Atomic32 topmost_toggles;
|
||||||
b32 is_topmost;
|
b32 is_topmost;
|
||||||
|
|
||||||
P_Mutex event_arena_swp_mutex;
|
Mutex event_arena_swp_mutex;
|
||||||
i32 current_event_arena_index;
|
i32 current_event_arena_index;
|
||||||
Arena *event_arenas[2];
|
Arena *event_arenas[2];
|
||||||
|
|
||||||
@ -113,8 +113,6 @@ Struct(P_W32_Sock)
|
|||||||
Struct(P_W32_SharedCtx)
|
Struct(P_W32_SharedCtx)
|
||||||
{
|
{
|
||||||
SYSTEM_INFO info;
|
SYSTEM_INFO info;
|
||||||
i64 timer_start_qpc;
|
|
||||||
i64 ns_per_qpc;
|
|
||||||
u32 main_thread_id;
|
u32 main_thread_id;
|
||||||
Atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
|
|
||||||
@ -132,20 +130,20 @@ Struct(P_W32_SharedCtx)
|
|||||||
P_Btn vk_btn_table[256];
|
P_Btn vk_btn_table[256];
|
||||||
|
|
||||||
//- Watches pool
|
//- Watches pool
|
||||||
P_Mutex watches_mutex;
|
Mutex watches_mutex;
|
||||||
Arena *watches_arena;
|
Arena *watches_arena;
|
||||||
P_W32_Watch *watches_first_free;
|
P_W32_Watch *watches_first_free;
|
||||||
|
|
||||||
//- Windows pool
|
//- Windows pool
|
||||||
WNDCLASSEXW window_class;
|
WNDCLASSEXW window_class;
|
||||||
P_Mutex windows_mutex;
|
Mutex windows_mutex;
|
||||||
Arena *windows_arena;
|
Arena *windows_arena;
|
||||||
P_W32_Window *first_free_window;
|
P_W32_Window *first_free_window;
|
||||||
|
|
||||||
//- Socket pool
|
//- Socket pool
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
Arena *socks_arena;
|
Arena *socks_arena;
|
||||||
P_Mutex socks_mutex;
|
Mutex socks_mutex;
|
||||||
P_W32_Sock *first_free_sock;
|
P_W32_Sock *first_free_sock;
|
||||||
|
|
||||||
//- Exit funcs
|
//- Exit funcs
|
||||||
|
|||||||
@ -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, PoolKind_Audio, PriorityKind_High, &g->PB_WSP_PlaybackJob_counter);
|
RunJob(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 };
|
||||||
@ -27,7 +27,7 @@ P_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);
|
Atomic32FetchSet(&g->shutdown, 1);
|
||||||
P_WaitOnCounter(&g->PB_WSP_PlaybackJob_counter);
|
WaitOnCounter(&g->PB_WSP_PlaybackJob_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PB_WSP_InitializeWasapi(void)
|
void PB_WSP_InitializeWasapi(void)
|
||||||
@ -184,7 +184,7 @@ void PB_WSP_EndUpdate(PB_WSP_Buff *wspbuf, MIX_PcmF32 src)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Playback job
|
//~ Playback job
|
||||||
|
|
||||||
JobDef(PB_WSP_PlaybackJob, _)
|
JobDef(PB_WSP_PlaybackJob, UNUSED sig, UNUSED id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||||
|
|||||||
@ -11,11 +11,9 @@ UserStartupReceipt StartupUser(S_StartupReceipt *sprite_sr,
|
|||||||
String connect_address_str)
|
String connect_address_str)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
LAX font_sr;
|
|
||||||
LAX sprite_sr;
|
LAX sprite_sr;
|
||||||
LAX draw_sr;
|
LAX draw_sr;
|
||||||
LAX asset_cache_sr;
|
LAX asset_cache_sr;
|
||||||
LAX sound_sr;
|
|
||||||
LAX mixer_sr;
|
LAX mixer_sr;
|
||||||
LAX sim_sr;
|
LAX sim_sr;
|
||||||
SharedUserState *g = &shared_user_state;
|
SharedUserState *g = &shared_user_state;
|
||||||
@ -23,7 +21,7 @@ UserStartupReceipt StartupUser(S_StartupReceipt *sprite_sr,
|
|||||||
SetGstat(GSTAT_DEBUG_STEPS, U64Max);
|
SetGstat(GSTAT_DEBUG_STEPS, U64Max);
|
||||||
|
|
||||||
g->arena = AllocArena(Gibi(64));
|
g->arena = AllocArena(Gibi(64));
|
||||||
g->real_time_ns = P_TimeNs();
|
g->real_time_ns = TimeNs();
|
||||||
|
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
g->connect_address_str = PushString(g->arena, connect_address_str);
|
g->connect_address_str = PushString(g->arena, connect_address_str);
|
||||||
@ -55,8 +53,8 @@ UserStartupReceipt StartupUser(S_StartupReceipt *sprite_sr,
|
|||||||
P_ShowWindow(g->window);
|
P_ShowWindow(g->window);
|
||||||
|
|
||||||
/* Start jobs */
|
/* Start jobs */
|
||||||
P_Run(1, UpdateUserJob, 0, PoolKind_User, PriorityKind_High, &g->shutdown_job_counters);
|
RunJob(1, UpdateUserJob, 0, PoolKind_User, PriorityKind_High, &g->shutdown_job_counters);
|
||||||
P_Run(1, SimJob, 0, PoolKind_Sim, PriorityKind_High, &g->shutdown_job_counters);
|
RunJob(1, SimJob, 0, PoolKind_Sim, PriorityKind_High, &g->shutdown_job_counters);
|
||||||
P_OnExit(&ShutdownUser);
|
P_OnExit(&ShutdownUser);
|
||||||
|
|
||||||
return (UserStartupReceipt) { 0 };
|
return (UserStartupReceipt) { 0 };
|
||||||
@ -70,7 +68,7 @@ P_ExitFuncDef(ShutdownUser)
|
|||||||
__prof;
|
__prof;
|
||||||
SharedUserState *g = &shared_user_state;
|
SharedUserState *g = &shared_user_state;
|
||||||
Atomic32FetchSet(&g->shutdown, 1);
|
Atomic32FetchSet(&g->shutdown, 1);
|
||||||
P_WaitOnCounter(&g->shutdown_job_counters);
|
WaitOnCounter(&g->shutdown_job_counters);
|
||||||
P_ReleaseWindow(g->window);
|
P_ReleaseWindow(g->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +232,7 @@ P_LogEventCallbackFuncDef(ConsoleLogCallback, log)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
SharedUserState *g = &shared_user_state;
|
SharedUserState *g = &shared_user_state;
|
||||||
P_Lock lock = P_LockE(&g->console_logs_mutex);
|
Lock lock = LockE(&g->console_logs_mutex);
|
||||||
{
|
{
|
||||||
ConsoleLog *clog = PushStruct(g->console_logs_arena, ConsoleLog);
|
ConsoleLog *clog = PushStruct(g->console_logs_arena, ConsoleLog);
|
||||||
clog->level = log.level;
|
clog->level = log.level;
|
||||||
@ -257,7 +255,7 @@ P_LogEventCallbackFuncDef(ConsoleLogCallback, log)
|
|||||||
}
|
}
|
||||||
g->last_console_log = clog;
|
g->last_console_log = clog;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Draw console
|
//- Draw console
|
||||||
@ -298,11 +296,11 @@ void DrawDebugConsole(i32 level, b32 minimized)
|
|||||||
}
|
}
|
||||||
g->console_logs_height = 0;
|
g->console_logs_height = 0;
|
||||||
|
|
||||||
i64 now_ns = P_TimeNs();
|
i64 now_ns = TimeNs();
|
||||||
F_Font *font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f);
|
F_Font *font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f);
|
||||||
if (font)
|
if (font)
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->console_logs_mutex);
|
Lock lock = LockE(&g->console_logs_mutex);
|
||||||
{
|
{
|
||||||
for (ConsoleLog *log = g->last_console_log; log; log = log->prev)
|
for (ConsoleLog *log = g->last_console_log; log; log = log->prev)
|
||||||
{
|
{
|
||||||
@ -356,7 +354,7 @@ void DrawDebugConsole(i32 level, b32 minimized)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
if (bounds_top < F32Infinity && bounds_bottom > -F32Infinity)
|
if (bounds_top < F32Infinity && bounds_bottom > -F32Infinity)
|
||||||
{
|
{
|
||||||
@ -417,7 +415,7 @@ void UpdateUser(P_Window *window)
|
|||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
|
||||||
//- Begin frame
|
//- Begin frame
|
||||||
g->real_dt_ns = P_TimeNs() - g->real_time_ns;
|
g->real_dt_ns = TimeNs() - g->real_time_ns;
|
||||||
g->real_time_ns += g->real_dt_ns;
|
g->real_time_ns += g->real_dt_ns;
|
||||||
g->screen_size = P_GetWindowSize(window);
|
g->screen_size = P_GetWindowSize(window);
|
||||||
S_Scope *sprite_frame_scope = S_BeginScope();
|
S_Scope *sprite_frame_scope = S_BeginScope();
|
||||||
@ -426,7 +424,7 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
{
|
{
|
||||||
__profn("Pull snapshot");
|
__profn("Pull snapshot");
|
||||||
P_Lock lock = P_LockE(&g->local_to_user_client_mutex);
|
Lock lock = LockE(&g->local_to_user_client_mutex);
|
||||||
u64 old_last_tick = g->user_unblended_client->last_tick;
|
u64 old_last_tick = g->user_unblended_client->last_tick;
|
||||||
u64 last_tick = g->local_to_user_client->last_tick;
|
u64 last_tick = g->local_to_user_client->last_tick;
|
||||||
if (last_tick > old_last_tick)
|
if (last_tick > old_last_tick)
|
||||||
@ -437,7 +435,7 @@ void UpdateUser(P_Window *window)
|
|||||||
g->average_local_to_user_snapshot_publish_dt_ns -= g->average_local_to_user_snapshot_publish_dt_ns / 50;
|
g->average_local_to_user_snapshot_publish_dt_ns -= g->average_local_to_user_snapshot_publish_dt_ns / 50;
|
||||||
g->average_local_to_user_snapshot_publish_dt_ns += g->local_to_user_client_publish_dt_ns / 50;
|
g->average_local_to_user_snapshot_publish_dt_ns += g->local_to_user_client_publish_dt_ns / 50;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Create user world from blended snapshots
|
//- Create user world from blended snapshots
|
||||||
@ -1832,7 +1830,7 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
/* Set user sim control */
|
/* Set user sim control */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->user_sim_cmd_mutex);
|
Lock lock = LockE(&g->user_sim_cmd_mutex);
|
||||||
|
|
||||||
/* Reset flags */
|
/* Reset flags */
|
||||||
if (g->user_sim_cmd_gen != g->last_user_sim_cmd_gen)
|
if (g->user_sim_cmd_gen != g->last_user_sim_cmd_gen)
|
||||||
@ -1845,7 +1843,7 @@ void UpdateUser(P_Window *window)
|
|||||||
g->user_sim_cmd_control = control;
|
g->user_sim_cmd_control = control;
|
||||||
g->user_sim_cmd_control.flags |= old_flags;
|
g->user_sim_cmd_control.flags |= old_flags;
|
||||||
g->user_hovered_ent = hovered_ent->id;
|
g->user_hovered_ent = hovered_ent->id;
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1869,7 +1867,7 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
{
|
{
|
||||||
/* Update network usage stats */
|
/* Update network usage stats */
|
||||||
i64 stat_now_ns = P_TimeNs();
|
i64 stat_now_ns = TimeNs();
|
||||||
g->net_bytes_read.last_second_end = GetGstat(GSTAT_SOCK_BYTES_RECEIVED);
|
g->net_bytes_read.last_second_end = GetGstat(GSTAT_SOCK_BYTES_RECEIVED);
|
||||||
g->net_bytes_sent.last_second_end = GetGstat(GSTAT_SOCK_BYTES_SENT);
|
g->net_bytes_sent.last_second_end = GetGstat(GSTAT_SOCK_BYTES_SENT);
|
||||||
if (stat_now_ns - g->last_second_reset_ns > NsFromSeconds(1))
|
if (stat_now_ns - g->last_second_reset_ns > NsFromSeconds(1))
|
||||||
@ -2066,10 +2064,10 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
//- User update job
|
//- User update job
|
||||||
|
|
||||||
JobDef(UpdateUserJob, _)
|
JobDef(UpdateUserJob, UNUSED sig, UNUSED id)
|
||||||
{
|
{
|
||||||
SharedUserState *g = &shared_user_state;
|
SharedUserState *g = &shared_user_state;
|
||||||
i64 time_ns = P_TimeNs();
|
i64 time_ns = TimeNs();
|
||||||
while (!Atomic32Fetch(&g->shutdown))
|
while (!Atomic32Fetch(&g->shutdown))
|
||||||
{
|
{
|
||||||
P_Window *window = g->window;
|
P_Window *window = g->window;
|
||||||
@ -2082,7 +2080,7 @@ JobDef(UpdateUserJob, _)
|
|||||||
{
|
{
|
||||||
__profn("Frame limiter wait");
|
__profn("Frame limiter wait");
|
||||||
P_SleepFrame(time_ns, 1000000000 / FPS_LIMIT);
|
P_SleepFrame(time_ns, 1000000000 / FPS_LIMIT);
|
||||||
time_ns = P_TimeNs();
|
time_ns = TimeNs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateUser(window);
|
UpdateUser(window);
|
||||||
@ -2109,7 +2107,7 @@ void GenerateuserInputCmds(Client *user_input_client, u64 tick)
|
|||||||
sim_ent_activate(control_cmd, user_input_ss->tick);
|
sim_ent_activate(control_cmd, user_input_ss->tick);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->user_sim_cmd_mutex);
|
Lock lock = LockE(&g->user_sim_cmd_mutex);
|
||||||
/* Update control cmd */
|
/* Update control cmd */
|
||||||
{
|
{
|
||||||
control_cmd->cmd_control = g->user_sim_cmd_control;
|
control_cmd->cmd_control = g->user_sim_cmd_control;
|
||||||
@ -2125,14 +2123,14 @@ void GenerateuserInputCmds(Client *user_input_client, u64 tick)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
++g->user_sim_cmd_gen;
|
++g->user_sim_cmd_gen;
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Sim update
|
//~ Sim update
|
||||||
|
|
||||||
JobDef(SimJob, UNUSED job)
|
JobDef(SimJob, UNUSED sig, UNUSED id)
|
||||||
{
|
{
|
||||||
SharedUserState *g = &shared_user_state;
|
SharedUserState *g = &shared_user_state;
|
||||||
#if 0
|
#if 0
|
||||||
@ -2221,7 +2219,7 @@ JobDef(SimJob, UNUSED job)
|
|||||||
{
|
{
|
||||||
__profn("Sim update");
|
__profn("Sim update");
|
||||||
|
|
||||||
real_dt_ns = P_TimeNs() - real_time_ns;
|
real_dt_ns = TimeNs() - real_time_ns;
|
||||||
real_time_ns += real_dt_ns;
|
real_time_ns += real_dt_ns;
|
||||||
|
|
||||||
N_EventList host_events = N_BeginUpdate(scratch.arena, host);
|
N_EventList host_events = N_BeginUpdate(scratch.arena, host);
|
||||||
@ -2798,9 +2796,9 @@ JobDef(SimJob, UNUSED job)
|
|||||||
if (local_ss->valid)
|
if (local_ss->valid)
|
||||||
{
|
{
|
||||||
/* TODO: Double buffer */
|
/* TODO: Double buffer */
|
||||||
P_Lock lock = P_LockE(&g->local_to_user_client_mutex);
|
Lock lock = LockE(&g->local_to_user_client_mutex);
|
||||||
sim_snapshot_alloc(g->local_to_user_client, local_ss, local_ss->tick);
|
sim_snapshot_alloc(g->local_to_user_client, local_ss, local_ss->tick);
|
||||||
i64 publish_ns = P_TimeNs();
|
i64 publish_ns = TimeNs();
|
||||||
if (last_publish_to_user_ns == 0)
|
if (last_publish_to_user_ns == 0)
|
||||||
{
|
{
|
||||||
last_publish_to_user_ns = publish_ns - g->average_local_to_user_snapshot_publish_dt_ns;
|
last_publish_to_user_ns = publish_ns - g->average_local_to_user_snapshot_publish_dt_ns;
|
||||||
@ -2809,7 +2807,7 @@ JobDef(SimJob, UNUSED job)
|
|||||||
g->local_to_user_client_publish_time_ns = publish_ns;
|
g->local_to_user_client_publish_time_ns = publish_ns;
|
||||||
last_publish_to_user_ns = publish_ns;
|
last_publish_to_user_ns = publish_ns;
|
||||||
sim_snapshot_release_ticks_in_range(g->local_to_user_client, 0, local_ss->tick - 1);
|
sim_snapshot_release_ticks_in_range(g->local_to_user_client, 0, local_ss->tick - 1);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -185,7 +185,7 @@ Struct(SharedUserState)
|
|||||||
b32 debug_draw;
|
b32 debug_draw;
|
||||||
|
|
||||||
//- Debug console
|
//- Debug console
|
||||||
P_Mutex console_logs_mutex;
|
Mutex console_logs_mutex;
|
||||||
Arena *console_logs_arena;
|
Arena *console_logs_arena;
|
||||||
ConsoleLog *first_console_log;
|
ConsoleLog *first_console_log;
|
||||||
ConsoleLog *last_console_log;
|
ConsoleLog *last_console_log;
|
||||||
@ -194,11 +194,11 @@ Struct(SharedUserState)
|
|||||||
b32 debug_console;
|
b32 debug_console;
|
||||||
|
|
||||||
//- Window -> user
|
//- Window -> user
|
||||||
P_Mutex sys_window_events_mutex;
|
Mutex sys_window_events_mutex;
|
||||||
Arena *sys_window_events_arena;
|
Arena *sys_window_events_arena;
|
||||||
|
|
||||||
//- User -> sim
|
//- User -> sim
|
||||||
P_Mutex user_sim_cmd_mutex;
|
Mutex user_sim_cmd_mutex;
|
||||||
ControlData user_sim_cmd_control;
|
ControlData user_sim_cmd_control;
|
||||||
EntityId user_hovered_ent;
|
EntityId user_hovered_ent;
|
||||||
u64 last_user_sim_cmd_gen;
|
u64 last_user_sim_cmd_gen;
|
||||||
@ -208,7 +208,7 @@ Struct(SharedUserState)
|
|||||||
Atomic32 user_paused_steps;
|
Atomic32 user_paused_steps;
|
||||||
|
|
||||||
//- Sim -> user
|
//- Sim -> user
|
||||||
P_Mutex local_to_user_client_mutex;
|
Mutex local_to_user_client_mutex;
|
||||||
ClientStore *local_to_user_client_store;
|
ClientStore *local_to_user_client_store;
|
||||||
Client *local_to_user_client;
|
Client *local_to_user_client;
|
||||||
i64 local_to_user_client_publish_dt_ns;
|
i64 local_to_user_client_publish_dt_ns;
|
||||||
|
|||||||
@ -329,14 +329,14 @@ Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick)
|
|||||||
if (ss->num_ents_reserved == 0) {
|
if (ss->num_ents_reserved == 0) {
|
||||||
/* Copying from nil snapshot, need to create blank & root entity */
|
/* Copying from nil snapshot, need to create blank & root entity */
|
||||||
|
|
||||||
/* PushStruct blank ent at index 0 (because index 0 is never valid anyway since it maps to sim_ent_nil()) */
|
/* Push blank ent at index 0 (because index 0 is never valid anyway since it maps to sim_ent_nil()) */
|
||||||
{
|
{
|
||||||
PushStruct(ss->ents_arena, Entity);
|
PushStruct(ss->ents_arena, Entity);
|
||||||
++ss->num_ents_allocated;
|
++ss->num_ents_allocated;
|
||||||
++ss->num_ents_reserved;
|
++ss->num_ents_reserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PushStruct root ent with constant id */
|
/* Push root ent with constant id */
|
||||||
{
|
{
|
||||||
Entity *root = PushStructNoZero(ss->ents_arena, Entity);
|
Entity *root = PushStructNoZero(ss->ents_arena, Entity);
|
||||||
*root = *sim_ent_nil();
|
*root = *sim_ent_nil();
|
||||||
|
|||||||
@ -1,17 +1,16 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Load job
|
//~ Load job
|
||||||
|
|
||||||
JobDef(SND_LoadAssetJob, job)
|
JobDef(SND_LoadJob, sig, UNUSED id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
SND_LoadAssetJobSig *params = job.sig;
|
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
String path = STRING(params->path_len, (u8 *)params->path_cstr);
|
String path = sig->path;
|
||||||
AC_Asset *asset = params->asset;
|
AC_Asset *asset = sig->asset;
|
||||||
SND_SoundFlag flags = params->flags;
|
SND_SoundFlag flags = sig->flags;
|
||||||
|
|
||||||
P_LogInfoF("Loading sound \"%F\"", FmtString(path));
|
P_LogInfoF("Loading sound \"%F\"", FmtString(path));
|
||||||
i64 start_ns = P_TimeNs();
|
i64 start_ns = TimeNs();
|
||||||
|
|
||||||
String error_msg = Lit("Unknown error");
|
String error_msg = Lit("Unknown error");
|
||||||
|
|
||||||
@ -61,7 +60,7 @@ JobDef(SND_LoadAssetJob, job)
|
|||||||
sound->samples = samples;
|
sound->samples = samples;
|
||||||
CopyBytes(sound->samples, decoded.samples, decoded.samples_count * sizeof(*decoded.samples));
|
CopyBytes(sound->samples, decoded.samples, decoded.samples_count * sizeof(*decoded.samples));
|
||||||
|
|
||||||
P_LogSuccessF("Loaded sound \"%F\" in %F seconds", FmtString(path), FmtFloat(SecondsFromNs(P_TimeNs() - start_ns)));
|
P_LogSuccessF("Loaded sound \"%F\" in %F seconds", FmtString(path), FmtFloat(SecondsFromNs(TimeNs() - start_ns)));
|
||||||
AC_MarkReady(asset, sound);
|
AC_MarkReady(asset, sound);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -101,22 +100,12 @@ AC_Asset *SND_LoadAsset(String path, SND_SoundFlag flags, b32 wait)
|
|||||||
|
|
||||||
if (is_first_touch)
|
if (is_first_touch)
|
||||||
{
|
{
|
||||||
/* Assemble task params */
|
|
||||||
SND_LoadAssetJobSig *params = SND_AllocJobSig();
|
|
||||||
if (path.len > (sizeof(params->path_cstr) - 1))
|
|
||||||
{
|
|
||||||
P_Panic(StringFormat(scratch.arena,
|
|
||||||
Lit("Sound path \"%F\" too long!"),
|
|
||||||
FmtString(path)));
|
|
||||||
}
|
|
||||||
CstrBuffFromStringToBuff(StringFromArray(params->path_cstr), path);
|
|
||||||
params->path_len = path.len;
|
|
||||||
params->asset = asset;
|
|
||||||
params->flags = flags;
|
|
||||||
|
|
||||||
/* PushStruct task */
|
|
||||||
AC_MarkLoading(asset);
|
AC_MarkLoading(asset);
|
||||||
P_Run(1, SND_LoadAssetJob, params, PoolKind_Background, PriorityKind_Low, &asset->counter);
|
SND_LoadJob_Desc *desc = PushJobDesc(SND_LoadJob, .pool = PoolKind_Background, .priority = PriorityKind_Low, .counter = &asset->counter);
|
||||||
|
desc->sig->path = PushString(desc->arena, path);
|
||||||
|
desc->sig->asset = asset;
|
||||||
|
desc->sig->flags = flags;
|
||||||
|
RunJobEx((GenericJobDesc *)desc);
|
||||||
if (wait)
|
if (wait)
|
||||||
{
|
{
|
||||||
AC_WaitOnAssetReady(asset);
|
AC_WaitOnAssetReady(asset);
|
||||||
|
|||||||
@ -19,7 +19,7 @@ Struct(SND_Sound)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Sound load operations
|
//~ Sound load operations
|
||||||
|
|
||||||
JobDecl(SND_LoadAssetJob, { SND_SoundFlag flags; AC_Asset *asset; String path; });
|
JobDecl(SND_LoadJob, { SND_SoundFlag flags; AC_Asset *asset; String path; });
|
||||||
AC_Asset *SND_LoadAsset(String path, SND_SoundFlag flags, b32 wait);
|
AC_Asset *SND_LoadAsset(String path, SND_SoundFlag flags, b32 wait);
|
||||||
SND_Sound *SND_LoadSoundAsync(String path, SND_SoundFlag flags);
|
SND_Sound *SND_LoadSoundAsync(String path, SND_SoundFlag flags);
|
||||||
SND_Sound *SND_LoadSoundWait(String path, SND_SoundFlag flags);
|
SND_Sound *SND_LoadSoundWait(String path, SND_SoundFlag flags);
|
||||||
|
|||||||
@ -40,11 +40,9 @@ S_StartupReceipt S_Startup(void)
|
|||||||
g->cache.arena = AllocArena(Gibi(64));
|
g->cache.arena = AllocArena(Gibi(64));
|
||||||
g->cache.bins = PushStructs(g->cache.arena, S_CacheEntryBin, S_CacheBinsCount);
|
g->cache.bins = PushStructs(g->cache.arena, S_CacheEntryBin, S_CacheBinsCount);
|
||||||
|
|
||||||
g->cmds_arena = AllocArena(Gibi(64));
|
|
||||||
|
|
||||||
g->scopes_arena = AllocArena(Gibi(64));
|
g->scopes_arena = AllocArena(Gibi(64));
|
||||||
|
|
||||||
P_Run(1, S_EvictorJob, 0, PoolKind_Background, PriorityKind_Low, &g->shutdown_counter);
|
RunJob(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
|
||||||
@ -63,13 +61,13 @@ P_ExitFuncDef(S_Shutdown)
|
|||||||
S_SharedState *g = &S_shared_state;
|
S_SharedState *g = &S_shared_state;
|
||||||
/* Signal evictor shutdown */
|
/* Signal evictor shutdown */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->evictor_scheduler_mutex);
|
Lock lock = LockE(&g->evictor_scheduler_mutex);
|
||||||
g->evictor_scheduler_shutdown = 1;
|
g->evictor_scheduler_shutdown = 1;
|
||||||
P_SignalCv(&g->evictor_scheduler_shutdown_cv, I32Max);
|
SignalCv(&g->evictor_scheduler_shutdown_cv, I32Max);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
/* Wait for evictor shutdown */
|
/* Wait for evictor shutdown */
|
||||||
P_WaitOnCounter(&g->shutdown_counter);
|
WaitOnCounter(&g->shutdown_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -421,69 +419,35 @@ S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Load job
|
//~ Load job
|
||||||
|
|
||||||
//- Job def
|
JobDef(S_LoadSpriteJob, sig, UNUSED id)
|
||||||
JobDef(S_LoadSpriteJob, job)
|
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
S_SharedState *g = &S_shared_state;
|
S_CacheEntryRef ref = sig->ref;
|
||||||
S_Cmd *cmd = job.sig;
|
S_Tag tag = sig->tag;
|
||||||
S_CacheEntryRef ref = cmd->ref;
|
S_Scope *scope = sig->scope;
|
||||||
|
|
||||||
switch (ref.e->kind)
|
switch (ref.e->kind)
|
||||||
{
|
{
|
||||||
case S_CacheEntryKind_Texture:
|
case S_CacheEntryKind_Texture:
|
||||||
{
|
{
|
||||||
S_LoadCacheEntryTexture(ref, cmd->tag);
|
S_LoadCacheEntryTexture(ref, tag);
|
||||||
} break;
|
} break;
|
||||||
case S_CacheEntryKind_Sheet:
|
case S_CacheEntryKind_Sheet:
|
||||||
{
|
{
|
||||||
S_LoadCacheEntrySheet(ref, cmd->tag);
|
S_LoadCacheEntrySheet(ref, tag);
|
||||||
} break;
|
} break;
|
||||||
default: { P_Panic(Lit("Unknown sprite cache node kind")); } break;
|
default: { P_Panic(Lit("Unknown sprite cache node kind")); } break;
|
||||||
}
|
}
|
||||||
|
S_EndScope(scope);
|
||||||
/* Free cmd */
|
|
||||||
P_Lock lock = P_LockE(&g->cmds_mutex);
|
|
||||||
{
|
|
||||||
S_EndScope(cmd->scope);
|
|
||||||
cmd->next_free = g->first_free_cmd;
|
|
||||||
g->first_free_cmd = cmd;
|
|
||||||
}
|
|
||||||
P_Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Push
|
|
||||||
void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag)
|
void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag)
|
||||||
{
|
{
|
||||||
S_SharedState *g = &S_shared_state;
|
S_LoadSpriteJob_Desc *desc = PushJobDesc(S_LoadSpriteJob, .pool = PoolKind_Background, .priority = PriorityKind_Inherit);
|
||||||
S_Cmd *cmd = 0;
|
desc->sig->scope = S_BeginScope(); /* Scope ended by job */
|
||||||
{
|
desc->sig->ref = S_EnsureRefFromRef(desc->sig->scope, ref)->ref;
|
||||||
P_Lock lock = P_LockE(&g->cmds_mutex);
|
desc->sig->tag = tag;
|
||||||
if (g->first_free_cmd)
|
tag.path = PushString(desc->arena, tag.path);
|
||||||
{
|
RunJobEx((GenericJobDesc *)desc);
|
||||||
cmd = g->first_free_cmd;
|
|
||||||
g->first_free_cmd = cmd->next_free;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd = PushStructNoZero(g->cmds_arena, S_Cmd);
|
|
||||||
}
|
|
||||||
P_Unlock(&lock);
|
|
||||||
}
|
|
||||||
ZeroStruct(cmd);
|
|
||||||
|
|
||||||
/* Initialize cmd */
|
|
||||||
cmd->scope = S_BeginScope();
|
|
||||||
cmd->ref = S_EnsureRefFromRef(cmd->scope, ref)->ref;
|
|
||||||
cmd->tag = tag;
|
|
||||||
{
|
|
||||||
u64 copy_len = MinU64(tag.path.len, countof(cmd->tag_path_buff));
|
|
||||||
cmd->tag.path.text = cmd->tag_path_buff;
|
|
||||||
CopyBytes(cmd->tag.path.text, tag.path.text, copy_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PushStruct work */
|
|
||||||
P_Run(1, S_LoadSpriteJob, cmd, PoolKind_Background, PriorityKind_Inherit, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -501,7 +465,7 @@ void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
|
|
||||||
P_LogInfoF("Loading sprite texture [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path));
|
P_LogInfoF("Loading sprite texture [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path));
|
||||||
b32 success = 0;
|
b32 success = 0;
|
||||||
i64 start_ns = P_TimeNs();
|
i64 start_ns = TimeNs();
|
||||||
|
|
||||||
Assert(StringEndsWith(path, Lit(".ase")));
|
Assert(StringEndsWith(path, Lit(".ase")));
|
||||||
Assert(e->kind == S_CacheEntryKind_Texture);
|
Assert(e->kind == S_CacheEntryKind_Texture);
|
||||||
@ -549,7 +513,7 @@ void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
P_LogSuccessF("Loaded sprite texture [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
P_LogSuccessF("Loaded sprite texture [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||||
FmtHex(e->hash.v),
|
FmtHex(e->hash.v),
|
||||||
FmtString(path),
|
FmtString(path),
|
||||||
FmtFloat(SecondsFromNs(P_TimeNs() - start_ns)),
|
FmtFloat(SecondsFromNs(TimeNs() - start_ns)),
|
||||||
FmtUint(e->memory_usage));
|
FmtUint(e->memory_usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,7 +521,7 @@ void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
S_CacheEntryBin *bin = &g->cache.bins[e->hash.v % S_CacheBinsCount];
|
S_CacheEntryBin *bin = &g->cache.bins[e->hash.v % S_CacheBinsCount];
|
||||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
Lock bin_lock = LockE(&bin->mutex);
|
||||||
{
|
{
|
||||||
for (S_CacheEntry *old_entry = bin->first; old_entry; old_entry = old_entry->next_in_bin)
|
for (S_CacheEntry *old_entry = bin->first; old_entry; old_entry = old_entry->next_in_bin)
|
||||||
{
|
{
|
||||||
@ -566,9 +530,9 @@ void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
Atomic32FetchSet(&old_entry->out_of_date, 1);
|
Atomic32FetchSet(&old_entry->out_of_date, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e->load_time_ns = P_TimeNs();
|
e->load_time_ns = TimeNs();
|
||||||
}
|
}
|
||||||
P_Unlock(&bin_lock);
|
Unlock(&bin_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
@ -586,7 +550,7 @@ void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
|
|
||||||
P_LogInfoF("Loading sprite sheet [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path));
|
P_LogInfoF("Loading sprite sheet [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path));
|
||||||
b32 success = 0;
|
b32 success = 0;
|
||||||
i64 start_ns = P_TimeNs();
|
i64 start_ns = TimeNs();
|
||||||
|
|
||||||
Assert(e->kind == S_CacheEntryKind_Sheet);
|
Assert(e->kind == S_CacheEntryKind_Sheet);
|
||||||
|
|
||||||
@ -632,7 +596,7 @@ void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
P_LogSuccessF("Loaded sprite sheet [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
P_LogSuccessF("Loaded sprite sheet [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||||
FmtHex(e->hash.v),
|
FmtHex(e->hash.v),
|
||||||
FmtString(path),
|
FmtString(path),
|
||||||
FmtFloat(SecondsFromNs(P_TimeNs() - start_ns)),
|
FmtFloat(SecondsFromNs(TimeNs() - start_ns)),
|
||||||
FmtUint(e->memory_usage));
|
FmtUint(e->memory_usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,7 +604,7 @@ void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
S_CacheEntryBin *bin = &g->cache.bins[e->hash.v % S_CacheBinsCount];
|
S_CacheEntryBin *bin = &g->cache.bins[e->hash.v % S_CacheBinsCount];
|
||||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
Lock bin_lock = LockE(&bin->mutex);
|
||||||
{
|
{
|
||||||
for (S_CacheEntry *old_entry = bin->first; old_entry; old_entry = old_entry->next_in_bin)
|
for (S_CacheEntry *old_entry = bin->first; old_entry; old_entry = old_entry->next_in_bin)
|
||||||
{
|
{
|
||||||
@ -649,9 +613,9 @@ void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag)
|
|||||||
Atomic32FetchSet(&old_entry->out_of_date, 1);
|
Atomic32FetchSet(&old_entry->out_of_date, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e->load_time_ns = P_TimeNs();
|
e->load_time_ns = TimeNs();
|
||||||
}
|
}
|
||||||
P_Unlock(&bin_lock);
|
Unlock(&bin_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
@ -720,11 +684,11 @@ S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e)
|
|||||||
return *slot;
|
return *slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock)
|
S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, Lock *bin_lock)
|
||||||
{
|
{
|
||||||
S_SharedState *g = &S_shared_state;
|
S_SharedState *g = &S_shared_state;
|
||||||
/* Guaranteed safe if caller has lock on entry's bin, since entry may not have an existing reference and could otherwise be evicted while ensuring this reference */
|
/* Guaranteed safe if caller has lock on entry's bin, since entry may not have an existing reference and could otherwise be evicted while ensuring this reference */
|
||||||
P_AssertLockedES(bin_lock, &g->cache.bins[e->hash.v % S_CacheBinsCount].mutex);
|
AssertLockedES(bin_lock, &g->cache.bins[e->hash.v % S_CacheBinsCount].mutex);
|
||||||
return S_EnsureRefUnsafely(scope, e);
|
return S_EnsureRefUnsafely(scope, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,7 +709,7 @@ S_Scope *S_BeginScope(void)
|
|||||||
S_ScopeCacheEntryRef **bins = 0;
|
S_ScopeCacheEntryRef **bins = 0;
|
||||||
S_ScopeCacheEntryRef *pool = 0;
|
S_ScopeCacheEntryRef *pool = 0;
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->scopes_mutex);
|
Lock lock = LockE(&g->scopes_mutex);
|
||||||
{
|
{
|
||||||
if (g->first_free_scope)
|
if (g->first_free_scope)
|
||||||
{
|
{
|
||||||
@ -761,7 +725,7 @@ S_Scope *S_BeginScope(void)
|
|||||||
pool = PushStructsNoZero(g->scopes_arena, S_ScopeCacheEntryRef, S_MaxScopeReferences);
|
pool = PushStructsNoZero(g->scopes_arena, S_ScopeCacheEntryRef, S_MaxScopeReferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(result);
|
ZeroStruct(result);
|
||||||
ZeroBytes(bins, sizeof(*bins) * S_CacheBinsCount);
|
ZeroBytes(bins, sizeof(*bins) * S_CacheBinsCount);
|
||||||
@ -782,12 +746,12 @@ void S_EndScope(S_Scope *scope)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Release scope */
|
/* Release scope */
|
||||||
P_Lock lock = P_LockE(&g->scopes_mutex);
|
Lock lock = LockE(&g->scopes_mutex);
|
||||||
{
|
{
|
||||||
scope->next_free = g->first_free_scope;
|
scope->next_free = g->first_free_scope;
|
||||||
g->first_free_scope = scope;
|
g->first_free_scope = scope;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -795,13 +759,13 @@ void S_EndScope(S_Scope *scope)
|
|||||||
|
|
||||||
//- Locked lookup
|
//- Locked lookup
|
||||||
|
|
||||||
S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, P_Lock *bin_lock)
|
S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, Lock *bin_lock)
|
||||||
{
|
{
|
||||||
S_SharedState *g = &S_shared_state;
|
S_SharedState *g = &S_shared_state;
|
||||||
S_ScopeCacheEntryRef *scope_ref = 0;
|
S_ScopeCacheEntryRef *scope_ref = 0;
|
||||||
|
|
||||||
S_CacheEntryBin *bin = &g->cache.bins[hash.v % S_CacheBinsCount];
|
S_CacheEntryBin *bin = &g->cache.bins[hash.v % S_CacheBinsCount];
|
||||||
P_AssertLockedES(bin_lock, &bin->mutex); /* Lock required for iterating bin */
|
AssertLockedES(bin_lock, &bin->mutex); /* Lock required for iterating bin */
|
||||||
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
/* If resource reloading is enabled, then we want to find the
|
/* If resource reloading is enabled, then we want to find the
|
||||||
@ -870,17 +834,17 @@ S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind
|
|||||||
/* Search in cache */
|
/* Search in cache */
|
||||||
if (!force_new)
|
if (!force_new)
|
||||||
{
|
{
|
||||||
P_Lock bin_lock = P_LockS(&bin->mutex);
|
Lock bin_lock = LockS(&bin->mutex);
|
||||||
{
|
{
|
||||||
scope_ref = S_EntryFromHashLocked(scope, hash, &bin_lock);
|
scope_ref = S_EntryFromHashLocked(scope, hash, &bin_lock);
|
||||||
}
|
}
|
||||||
P_Unlock(&bin_lock);
|
Unlock(&bin_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If not in cache, allocate new entry */
|
/* If not in cache, allocate new entry */
|
||||||
if (!scope_ref)
|
if (!scope_ref)
|
||||||
{
|
{
|
||||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
Lock bin_lock = LockE(&bin->mutex);
|
||||||
{
|
{
|
||||||
/* Search cache one more time in case an entry was allocated between locks */
|
/* Search cache one more time in case an entry was allocated between locks */
|
||||||
if (!force_new)
|
if (!force_new)
|
||||||
@ -893,7 +857,7 @@ S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind
|
|||||||
/* Cache entry still absent, allocate new entry */
|
/* Cache entry still absent, allocate new entry */
|
||||||
S_CacheEntry *entry = 0;
|
S_CacheEntry *entry = 0;
|
||||||
{
|
{
|
||||||
P_Lock pool_lock = P_LockE(&g->cache.entry_pool_mutex);
|
Lock pool_lock = LockE(&g->cache.entry_pool_mutex);
|
||||||
if (g->cache.entry_pool_first_free)
|
if (g->cache.entry_pool_first_free)
|
||||||
{
|
{
|
||||||
entry = g->cache.entry_pool_first_free;
|
entry = g->cache.entry_pool_first_free;
|
||||||
@ -903,7 +867,7 @@ S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind
|
|||||||
{
|
{
|
||||||
entry = PushStructNoZero(g->cache.arena, S_CacheEntry);
|
entry = PushStructNoZero(g->cache.arena, S_CacheEntry);
|
||||||
}
|
}
|
||||||
P_Unlock(&pool_lock);
|
Unlock(&pool_lock);
|
||||||
}
|
}
|
||||||
ZeroStruct(entry);
|
ZeroStruct(entry);
|
||||||
|
|
||||||
@ -928,7 +892,7 @@ S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind
|
|||||||
scope_ref = S_EnsureRefFromEntryLocked(scope, entry, &bin_lock);
|
scope_ref = S_EnsureRefFromEntryLocked(scope, entry, &bin_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&bin_lock);
|
Unlock(&bin_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1132,11 +1096,11 @@ void S_ReloadSpriteFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind)
|
|||||||
S_Hash hash = S_CacheEntryFromTagHash(tag.hash, kind);
|
S_Hash hash = S_CacheEntryFromTagHash(tag.hash, kind);
|
||||||
S_CacheEntryBin *bin = &g->cache.bins[hash.v % S_CacheBinsCount];
|
S_CacheEntryBin *bin = &g->cache.bins[hash.v % S_CacheBinsCount];
|
||||||
S_ScopeCacheEntryRef *existing_ref = 0;
|
S_ScopeCacheEntryRef *existing_ref = 0;
|
||||||
P_Lock bin_lock = P_LockS(&bin->mutex);
|
Lock bin_lock = LockS(&bin->mutex);
|
||||||
{
|
{
|
||||||
existing_ref = S_EntryFromHashLocked(scope, hash, &bin_lock);
|
existing_ref = S_EntryFromHashLocked(scope, hash, &bin_lock);
|
||||||
}
|
}
|
||||||
P_Unlock(&bin_lock);
|
Unlock(&bin_lock);
|
||||||
|
|
||||||
if (existing_ref)
|
if (existing_ref)
|
||||||
{
|
{
|
||||||
@ -1189,7 +1153,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
|
||||||
*/
|
*/
|
||||||
JobDef(S_EvictorJob, _)
|
JobDef(S_EvictorJob, UNUSED sig, UNUSED job_id)
|
||||||
{
|
{
|
||||||
S_SharedState *g = &S_shared_state;
|
S_SharedState *g = &S_shared_state;
|
||||||
b32 shutdown = 0;
|
b32 shutdown = 0;
|
||||||
@ -1211,7 +1175,7 @@ JobDef(S_EvictorJob, _)
|
|||||||
for (u64 i = 0; i < S_CacheBinsCount; ++i)
|
for (u64 i = 0; i < S_CacheBinsCount; ++i)
|
||||||
{
|
{
|
||||||
S_CacheEntryBin *bin = &g->cache.bins[i];
|
S_CacheEntryBin *bin = &g->cache.bins[i];
|
||||||
P_Lock bin_lock = P_LockS(&bin->mutex);
|
Lock bin_lock = LockS(&bin->mutex);
|
||||||
{
|
{
|
||||||
S_CacheEntry *n = bin->first;
|
S_CacheEntry *n = bin->first;
|
||||||
while (n)
|
while (n)
|
||||||
@ -1244,7 +1208,7 @@ JobDef(S_EvictorJob, _)
|
|||||||
n = n->next_in_bin;
|
n = n->next_in_bin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&bin_lock);
|
Unlock(&bin_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1269,7 +1233,7 @@ JobDef(S_EvictorJob, _)
|
|||||||
S_CacheEntry *entry = en->cache_entry;
|
S_CacheEntry *entry = en->cache_entry;
|
||||||
i32 last_ref_cycle = en->last_ref_cycle;
|
i32 last_ref_cycle = en->last_ref_cycle;
|
||||||
b32 cache_over_budget_target = Atomic64Fetch(&g->cache.memory_usage.v) > (i64)S_CacheMemoryBudgetTarget;
|
b32 cache_over_budget_target = Atomic64Fetch(&g->cache.memory_usage.v) > (i64)S_CacheMemoryBudgetTarget;
|
||||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
Lock bin_lock = LockE(&bin->mutex);
|
||||||
{
|
{
|
||||||
u64 refcount_uncast = Atomic64Fetch(&entry->refcount_struct.v);
|
u64 refcount_uncast = Atomic64Fetch(&entry->refcount_struct.v);
|
||||||
S_Refcount refcount = *(S_Refcount *)&refcount_uncast;
|
S_Refcount refcount = *(S_Refcount *)&refcount_uncast;
|
||||||
@ -1311,7 +1275,7 @@ JobDef(S_EvictorJob, _)
|
|||||||
stop_evicting = 1;
|
stop_evicting = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&bin_lock);
|
Unlock(&bin_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1334,14 +1298,14 @@ JobDef(S_EvictorJob, _)
|
|||||||
/* Add evicted nodes to free list */
|
/* Add evicted nodes to free list */
|
||||||
{
|
{
|
||||||
__profn("Evictor free list append");
|
__profn("Evictor free list append");
|
||||||
P_Lock pool_lock = P_LockE(&g->cache.entry_pool_mutex);
|
Lock pool_lock = LockE(&g->cache.entry_pool_mutex);
|
||||||
for (S_EvictorNode *en = first_evicted; en; en = en->next_evicted)
|
for (S_EvictorNode *en = first_evicted; en; en = en->next_evicted)
|
||||||
{
|
{
|
||||||
S_CacheEntry *n = en->cache_entry;
|
S_CacheEntry *n = en->cache_entry;
|
||||||
n->next_free = g->cache.entry_pool_first_free;
|
n->next_free = g->cache.entry_pool_first_free;
|
||||||
g->cache.entry_pool_first_free = n;
|
g->cache.entry_pool_first_free = n;
|
||||||
}
|
}
|
||||||
P_Unlock(&pool_lock);
|
Unlock(&pool_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1351,15 +1315,15 @@ JobDef(S_EvictorJob, _)
|
|||||||
|
|
||||||
/* Evictor sleep */
|
/* Evictor sleep */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->evictor_scheduler_mutex);
|
Lock lock = LockE(&g->evictor_scheduler_mutex);
|
||||||
{
|
{
|
||||||
if (!g->evictor_scheduler_shutdown)
|
if (!g->evictor_scheduler_shutdown)
|
||||||
{
|
{
|
||||||
P_WaitOnCvTime(&g->evictor_scheduler_shutdown_cv, &lock, S_EvictorCycleIntervalNs);
|
WaitOnCvTime(&g->evictor_scheduler_shutdown_cv, &lock, S_EvictorCycleIntervalNs);
|
||||||
}
|
}
|
||||||
shutdown = g->evictor_scheduler_shutdown;
|
shutdown = g->evictor_scheduler_shutdown;
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,7 +150,7 @@ Struct(S_CacheEntry)
|
|||||||
|
|
||||||
Struct(S_CacheEntryBin)
|
Struct(S_CacheEntryBin)
|
||||||
{
|
{
|
||||||
P_Mutex mutex;
|
Mutex mutex;
|
||||||
S_CacheEntry *first;
|
S_CacheEntry *first;
|
||||||
S_CacheEntry *last;
|
S_CacheEntry *last;
|
||||||
};
|
};
|
||||||
@ -160,7 +160,7 @@ Struct(S_Cache)
|
|||||||
Atomic64Padded memory_usage;
|
Atomic64Padded memory_usage;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
S_CacheEntryBin *bins;
|
S_CacheEntryBin *bins;
|
||||||
P_Mutex entry_pool_mutex;
|
Mutex entry_pool_mutex;
|
||||||
S_CacheEntry *entry_pool_first_free;
|
S_CacheEntry *entry_pool_first_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ Struct(S_SharedState)
|
|||||||
S_Cache cache;
|
S_Cache cache;
|
||||||
|
|
||||||
/* Scopes */
|
/* Scopes */
|
||||||
P_Mutex scopes_mutex;
|
Mutex scopes_mutex;
|
||||||
Arena *scopes_arena;
|
Arena *scopes_arena;
|
||||||
S_Scope *first_free_scope;
|
S_Scope *first_free_scope;
|
||||||
|
|
||||||
@ -246,8 +246,8 @@ Struct(S_SharedState)
|
|||||||
Atomic32Padded evictor_cycle;
|
Atomic32Padded evictor_cycle;
|
||||||
Counter shutdown_counter;
|
Counter shutdown_counter;
|
||||||
b32 evictor_scheduler_shutdown;
|
b32 evictor_scheduler_shutdown;
|
||||||
P_Mutex evictor_scheduler_mutex;
|
Mutex evictor_scheduler_mutex;
|
||||||
P_Cv evictor_scheduler_shutdown_cv;
|
Cv evictor_scheduler_shutdown_cv;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern S_SharedState S_shared_state;
|
extern S_SharedState S_shared_state;
|
||||||
@ -298,7 +298,7 @@ void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag);
|
|||||||
|
|
||||||
void S_AddRef(S_CacheEntry *e, i32 amount);
|
void S_AddRef(S_CacheEntry *e, i32 amount);
|
||||||
S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e);
|
S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e);
|
||||||
S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock);
|
S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, Lock *bin_lock);
|
||||||
S_ScopeCacheEntryRef *S_EnsureRefFromRef(S_Scope *scope, S_CacheEntryRef ref);
|
S_ScopeCacheEntryRef *S_EnsureRefFromRef(S_Scope *scope, S_CacheEntryRef ref);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -310,7 +310,7 @@ void S_EndScope(S_Scope *scope);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Cache lookup operations
|
//~ Cache lookup operations
|
||||||
|
|
||||||
S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, P_Lock *bin_lock);
|
S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, Lock *bin_lock);
|
||||||
S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new);
|
S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new);
|
||||||
void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await);
|
void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await);
|
||||||
|
|
||||||
|
|||||||
@ -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, PoolKind_Floating, PriorityKind_Low, &g->watch_jobs_counter);
|
RunJob(1, W_MonitorJob, 0, PoolKind_Floating, PriorityKind_Low, &g->watch_jobs_counter);
|
||||||
P_Run(1, W_DispatcherJob, 0, PoolKind_Background, PriorityKind_Low, &g->watch_jobs_counter);
|
RunJob(1, W_DispatcherJob, 0, PoolKind_Background, PriorityKind_Low, &g->watch_jobs_counter);
|
||||||
P_OnExit(&W_Shutdown);
|
P_OnExit(&W_Shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,12 +21,12 @@ P_ExitFuncDef(W_Shutdown)
|
|||||||
W_SharedState *g = &W_shared_state;
|
W_SharedState *g = &W_shared_state;
|
||||||
Atomic32FetchSet(&g->W_Shutdown, 1);
|
Atomic32FetchSet(&g->W_Shutdown, 1);
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->watch_dispatcher_mutex);
|
Lock lock = LockE(&g->watch_dispatcher_mutex);
|
||||||
P_SignalCv(&g->watch_dispatcher_cv, I32Max);
|
SignalCv(&g->watch_dispatcher_cv, I32Max);
|
||||||
P_WakeWatch(g->watch);
|
P_WakeWatch(g->watch);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
P_WaitOnCounter(&g->watch_jobs_counter);
|
WaitOnCounter(&g->watch_jobs_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -35,7 +35,7 @@ P_ExitFuncDef(W_Shutdown)
|
|||||||
void W_RegisterCallback(W_CallbackFunc *callback)
|
void W_RegisterCallback(W_CallbackFunc *callback)
|
||||||
{
|
{
|
||||||
W_SharedState *g = &W_shared_state;
|
W_SharedState *g = &W_shared_state;
|
||||||
P_Lock lock = P_LockE(&g->watch_callbacks_mutex);
|
Lock lock = LockE(&g->watch_callbacks_mutex);
|
||||||
{
|
{
|
||||||
if (g->num_watch_callbacks < countof(g->watch_callbacks))
|
if (g->num_watch_callbacks < countof(g->watch_callbacks))
|
||||||
{
|
{
|
||||||
@ -46,15 +46,14 @@ void W_RegisterCallback(W_CallbackFunc *callback)
|
|||||||
P_Panic(Lit("Max resource watch callbacks reached"));
|
P_Panic(Lit("Max resource watch callbacks reached"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
JobDef(W_RunCallbackJob, job)
|
JobDef(W_RunCallbacksJob , sig, id)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
W_RunCallbackJobSig *sig = job.sig;
|
|
||||||
String name = sig->name;
|
String name = sig->name;
|
||||||
W_CallbackFunc *callback = sig->callbacks[job.id];
|
W_CallbackFunc *callback = sig->callbacks[id];
|
||||||
callback(name);
|
callback(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ 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. */
|
||||||
|
|
||||||
JobDef(W_MonitorJob, _)
|
JobDef(W_MonitorJob, UNUSED sig, UNUSED job_id)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
W_SharedState *g = &W_shared_state;
|
W_SharedState *g = &W_shared_state;
|
||||||
@ -81,7 +80,7 @@ JobDef(W_MonitorJob, _)
|
|||||||
P_WatchInfoList info_list = P_ReadWatchWait(temp.arena, g->watch);
|
P_WatchInfoList info_list = P_ReadWatchWait(temp.arena, g->watch);
|
||||||
if (info_list.first && !Atomic32Fetch(&g->W_Shutdown))
|
if (info_list.first && !Atomic32Fetch(&g->W_Shutdown))
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->watch_dispatcher_mutex);
|
Lock lock = LockE(&g->watch_dispatcher_mutex);
|
||||||
{
|
{
|
||||||
for (P_WatchInfo *info = info_list.first; info; info = info->next)
|
for (P_WatchInfo *info = info_list.first; info; info = info->next)
|
||||||
{
|
{
|
||||||
@ -111,8 +110,8 @@ JobDef(W_MonitorJob, _)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_SignalCv(&g->watch_dispatcher_cv, I32Max);
|
SignalCv(&g->watch_dispatcher_cv, I32Max);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
EndTempArena(temp);
|
EndTempArena(temp);
|
||||||
}
|
}
|
||||||
@ -123,7 +122,7 @@ JobDef(W_MonitorJob, _)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Dispatcher job
|
//~ Dispatcher job
|
||||||
|
|
||||||
JobDef(W_DispatcherJob, _)
|
JobDef(W_DispatcherJob, UNUSED sig, UNUSED job_id)
|
||||||
{
|
{
|
||||||
W_SharedState *g = &W_shared_state;
|
W_SharedState *g = &W_shared_state;
|
||||||
|
|
||||||
@ -138,12 +137,12 @@ JobDef(W_DispatcherJob, _)
|
|||||||
/* Delay so that duplicate events pile up */
|
/* Delay so that duplicate events pile up */
|
||||||
{
|
{
|
||||||
__profn("Delay");
|
__profn("Delay");
|
||||||
P_Wait(0, 0, 0, NsFromSeconds(W_DispatcherDelaySeconds));
|
FutexWait(0, 0, 0, NsFromSeconds(W_DispatcherDelaySeconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pull watch events from queue */
|
/* Pull watch events from queue */
|
||||||
{
|
{
|
||||||
P_Lock lock = P_LockE(&g->watch_dispatcher_mutex);
|
Lock lock = LockE(&g->watch_dispatcher_mutex);
|
||||||
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);
|
||||||
@ -161,13 +160,13 @@ JobDef(W_DispatcherJob, _)
|
|||||||
g->first_watch_event = 0;
|
g->first_watch_event = 0;
|
||||||
g->last_watch_event = 0;
|
g->last_watch_event = 0;
|
||||||
ResetArena(g->watch_events_arena);
|
ResetArena(g->watch_events_arena);
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build callbacks array */
|
/* Build callbacks array */
|
||||||
u64 num_callbacks = 0;
|
u64 num_callbacks = 0;
|
||||||
W_CallbackFunc **callbacks = 0;
|
W_CallbackFunc **callbacks = 0;
|
||||||
P_Lock callbacks_lock = P_LockS(&g->watch_callbacks_mutex);
|
Lock callbacks_lock = LockS(&g->watch_callbacks_mutex);
|
||||||
{
|
{
|
||||||
num_callbacks = g->num_watch_callbacks;
|
num_callbacks = g->num_watch_callbacks;
|
||||||
callbacks = PushStructsNoZero(scratch.arena, W_CallbackFunc *, num_callbacks);
|
callbacks = PushStructsNoZero(scratch.arena, W_CallbackFunc *, num_callbacks);
|
||||||
@ -176,7 +175,7 @@ JobDef(W_DispatcherJob, _)
|
|||||||
callbacks[i] = g->watch_callbacks[i];
|
callbacks[i] = g->watch_callbacks[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&callbacks_lock);
|
Unlock(&callbacks_lock);
|
||||||
|
|
||||||
/* Run callbacks */
|
/* Run callbacks */
|
||||||
{
|
{
|
||||||
@ -197,12 +196,9 @@ JobDef(W_DispatcherJob, _)
|
|||||||
}
|
}
|
||||||
if (!skip)
|
if (!skip)
|
||||||
{
|
{
|
||||||
W_RunCallbackJobSig sig = ZI;
|
|
||||||
sig.name = e->name;
|
|
||||||
sig.callbacks = callbacks;
|
|
||||||
Counter counter = ZI;
|
Counter counter = ZI;
|
||||||
P_Run(num_callbacks, W_RunCallbackJob, &sig, PoolKind_Background, PriorityKind_Low, &counter);
|
RunJob(num_callbacks, W_RunCallbacksJob, PoolKind_Background, PriorityKind_Low, &counter, .name = e->name, .callbacks = callbacks);
|
||||||
P_WaitOnCounter(&counter);
|
WaitOnCounter(&counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,15 +207,15 @@ JobDef(W_DispatcherJob, _)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for event */
|
/* Wait for event */
|
||||||
P_Lock lock = P_LockS(&g->watch_dispatcher_mutex);
|
Lock lock = LockS(&g->watch_dispatcher_mutex);
|
||||||
{
|
{
|
||||||
shutdown = Atomic32Fetch(&g->W_Shutdown);
|
shutdown = Atomic32Fetch(&g->W_Shutdown);
|
||||||
while (!shutdown && !g->first_watch_event)
|
while (!shutdown && !g->first_watch_event)
|
||||||
{
|
{
|
||||||
P_WaitOnCv(&g->watch_dispatcher_cv, &lock);
|
WaitOnCv(&g->watch_dispatcher_cv, &lock);
|
||||||
shutdown = Atomic32Fetch(&g->W_Shutdown);
|
shutdown = Atomic32Fetch(&g->W_Shutdown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,6 @@
|
|||||||
#define W_CallbackFuncDef(func_name, arg_name) void func_name(String arg_name)
|
#define W_CallbackFuncDef(func_name, arg_name) void func_name(String arg_name)
|
||||||
typedef W_CallbackFuncDef(W_CallbackFunc, name);
|
typedef W_CallbackFuncDef(W_CallbackFunc, name);
|
||||||
|
|
||||||
Struct(W_RunCallbackJobSig)
|
|
||||||
{
|
|
||||||
String name;
|
|
||||||
W_CallbackFunc **callbacks;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Event types
|
//~ Event types
|
||||||
|
|
||||||
@ -31,13 +25,13 @@ Struct(W_SharedState)
|
|||||||
Atomic32 W_Shutdown;
|
Atomic32 W_Shutdown;
|
||||||
Counter watch_jobs_counter;
|
Counter watch_jobs_counter;
|
||||||
|
|
||||||
P_Mutex watch_dispatcher_mutex;
|
Mutex watch_dispatcher_mutex;
|
||||||
Arena *watch_events_arena;
|
Arena *watch_events_arena;
|
||||||
W_Event *first_watch_event;
|
W_Event *first_watch_event;
|
||||||
W_Event *last_watch_event;
|
W_Event *last_watch_event;
|
||||||
P_Cv watch_dispatcher_cv;
|
Cv watch_dispatcher_cv;
|
||||||
|
|
||||||
P_Mutex watch_callbacks_mutex;
|
Mutex watch_callbacks_mutex;
|
||||||
W_CallbackFunc *watch_callbacks[64];
|
W_CallbackFunc *watch_callbacks[64];
|
||||||
u64 num_watch_callbacks;
|
u64 num_watch_callbacks;
|
||||||
};
|
};
|
||||||
@ -58,7 +52,7 @@ void W_RegisterCallback(W_CallbackFunc *callback);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Callback job
|
//~ Callback job
|
||||||
|
|
||||||
JobDecl(W_RunCallbackJob, EmptySig);
|
JobDecl(W_RunCallbacksJob, { String name; W_CallbackFunc **callbacks; });
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Long running jobs
|
//~ Long running jobs
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user