sprite refactor progress
This commit is contained in:
parent
4cb7006de9
commit
b14ce157b8
21
build.bat
21
build.bat
@ -4,8 +4,9 @@ cd /D "%~dp0"
|
||||
if not exist build mkdir build
|
||||
pushd build
|
||||
|
||||
for %%a in (%*) do set "%%a=1"
|
||||
set program_build_cmd=meta.exe %*
|
||||
set meta_build_cmd=cl.exe ../src/meta/meta.c /Od /Z7 /nologo /diagnostics:column /link /DEBUG:FULL /INCREMENTAL:NO
|
||||
set meta_build_cmd=cl.exe ../src/meta/meta.c /Od /Z7 /nologo /diagnostics:column /WX /link /DEBUG:FULL /INCREMENTAL:NO
|
||||
set meta_rebuild_code=1317212284
|
||||
|
||||
::- Meta build
|
||||
@ -20,13 +21,15 @@ if not exist meta.exe (
|
||||
)
|
||||
|
||||
::- Program build
|
||||
echo ======== Build ========
|
||||
%program_build_cmd%
|
||||
set "rc=!errorlevel!"
|
||||
if !rc! NEQ 0 (
|
||||
if !rc! EQU %meta_rebuild_code% (
|
||||
del meta.exe
|
||||
goto meta_build
|
||||
if not "%norun%"=="1" (
|
||||
echo ======== Build ========
|
||||
%program_build_cmd%
|
||||
set "rc=!errorlevel!"
|
||||
if !rc! NEQ 0 (
|
||||
if !rc! EQU %meta_rebuild_code% (
|
||||
del meta.exe
|
||||
goto meta_build
|
||||
)
|
||||
exit /b !rc!
|
||||
)
|
||||
exit /b !rc!
|
||||
)
|
||||
|
||||
@ -489,7 +489,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
|
||||
TempArena scratch = BeginScratch(arena);
|
||||
ASE_DecodedImage result = ZI;
|
||||
|
||||
BB_Buff bb = BitbuffFromString(encoded);
|
||||
BB_Buff bb = BB_BuffFromString(encoded);
|
||||
BB_Reader br = BB_ReaderFromBuffNoDebug(&bb);
|
||||
ASE_Header ase_header;
|
||||
BB_ReadBytes(&br, StringFromStruct(&ase_header));
|
||||
@ -559,7 +559,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
|
||||
{
|
||||
default:
|
||||
{
|
||||
BB_SeekToByte(&br, chunk_end_pos);
|
||||
BB_ReadSeekToByte(&br, chunk_end_pos);
|
||||
} break;
|
||||
|
||||
//- Decode layer
|
||||
@ -574,7 +574,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
|
||||
layer->child_level = BB_ReadUBits(&br, 16);
|
||||
|
||||
/* Ignoring layer default width & height */
|
||||
BB_SeekBytes(&br, sizeof(u16) * 2);
|
||||
BB_ReadSeekBytes(&br, sizeof(u16) * 2);
|
||||
|
||||
layer->blend_mode = BB_ReadUBits(&br, 16);
|
||||
if (layer->blend_mode != 0)
|
||||
@ -591,7 +591,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
|
||||
layer->opacity = 255;
|
||||
}
|
||||
|
||||
BB_SeekBytes(&br, sizeof(u8) * 3);
|
||||
BB_ReadSeekBytes(&br, sizeof(u8) * 3);
|
||||
|
||||
u16 str_len = BB_ReadUBits(&br, 16);
|
||||
layer->name = (String) { str_len, PushStructsNoZero(scratch.arena, u8, str_len) };
|
||||
@ -625,7 +625,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
|
||||
cel->opacity = BB_ReadUBits(&br, 8);
|
||||
cel->type = BB_ReadUBits(&br, 16);
|
||||
cel->z_index = BB_ReadIBits(&br, 16);
|
||||
BB_SeekBytes(&br, sizeof(u8) * 5);
|
||||
BB_ReadSeekBytes(&br, sizeof(u8) * 5);
|
||||
|
||||
cel->frame_index = num_frames;
|
||||
|
||||
@ -634,7 +634,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
|
||||
case ASE_CelKind_RawImage:
|
||||
{
|
||||
/* Unsupported */
|
||||
BB_SeekToByte(&br, chunk_end_pos);
|
||||
BB_ReadSeekToByte(&br, chunk_end_pos);
|
||||
} break;
|
||||
|
||||
case ASE_CelKind_Linked:
|
||||
@ -783,7 +783,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
||||
|
||||
ASE_DecodedSheet result = ZI;
|
||||
|
||||
BB_Buff bb = BitbuffFromString(encoded);
|
||||
BB_Buff bb = BB_BuffFromString(encoded);
|
||||
BB_Reader br = BB_ReaderFromBuffNoDebug(&bb);
|
||||
ASE_Header ase_header;
|
||||
BB_ReadBytes(&br, StringFromStruct(&ase_header));
|
||||
@ -857,14 +857,14 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
||||
{
|
||||
default:
|
||||
{
|
||||
BB_SeekToByte(&br, chunk_end_pos);
|
||||
BB_ReadSeekToByte(&br, chunk_end_pos);
|
||||
} break;
|
||||
|
||||
//- Decode tags
|
||||
case ASE_ChunkKind_Tags:
|
||||
{
|
||||
u16 frame_span_count = BB_ReadUBits(&br, 16);
|
||||
BB_SeekBytes(&br, 8);
|
||||
BB_ReadSeekBytes(&br, 8);
|
||||
|
||||
for (u16 k = 0; k < frame_span_count; ++k)
|
||||
{
|
||||
@ -874,7 +874,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
||||
|
||||
span->start = BB_ReadUBits(&br, 16);
|
||||
span->end = BB_ReadUBits(&br, 16);
|
||||
BB_SeekBytes(&br, 13);
|
||||
BB_ReadSeekBytes(&br, 13);
|
||||
|
||||
u16 str_len = BB_ReadUBits(&br, 16);
|
||||
span->name = (String) { str_len, PushStructsNoZero(arena, u8, str_len) };
|
||||
@ -896,7 +896,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
||||
slice_key->num_slices = num_slices;
|
||||
|
||||
u32 flags = BB_ReadUBits(&br, 32);
|
||||
BB_SeekBytes(&br, 4);
|
||||
BB_ReadSeekBytes(&br, 4);
|
||||
|
||||
u16 str_len = BB_ReadUBits(&br, 16);
|
||||
slice_key->name = (String) { str_len, PushStructsNoZero(arena, u8, str_len) };
|
||||
@ -916,12 +916,12 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
||||
if (flags & 0x01)
|
||||
{
|
||||
/* Skip 9-patches info */
|
||||
BB_SeekBytes(&br, 128);
|
||||
BB_ReadSeekBytes(&br, 128);
|
||||
}
|
||||
if (flags & 0x02)
|
||||
{
|
||||
/* Skip pivot info */
|
||||
BB_SeekBytes(&br, 64);
|
||||
BB_ReadSeekBytes(&br, 64);
|
||||
}
|
||||
|
||||
slice->start = start;
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
@Layer ase
|
||||
|
||||
//- Dependencies
|
||||
@Dep bitbuff
|
||||
|
||||
//- Api
|
||||
@IncludeC ase.h
|
||||
|
||||
|
||||
118
src/base/base.h
118
src/base/base.h
@ -63,24 +63,35 @@
|
||||
//- Platform system
|
||||
#if defined(_WIN32)
|
||||
# define PlatformIsWindows 1
|
||||
# define PlatformIsMac 0
|
||||
# define PlatformIsLinux 0
|
||||
# define PlatformIsMac 0
|
||||
# define PlatformIsLinux 0
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
# define PlatformIsWindows 0
|
||||
# define PlatformIsMac 1
|
||||
# define PlatformIsLinux 0
|
||||
# define PlatformIsMac 1
|
||||
# define PlatformIsLinux 0
|
||||
#elif defined(__gnu_linux__)
|
||||
# define PlatformIsWindows 0
|
||||
# define PlatformIsMac 0
|
||||
# define PlatformIsLinux 1
|
||||
# define PlatformIsMac 0
|
||||
# define PlatformIsLinux 1
|
||||
#elif LanguageIsGpu
|
||||
# define PlatformIsWindows 0
|
||||
# define PlatformIsMac 0
|
||||
# define PlatformIsLinux 0
|
||||
# define PlatformIsMac 0
|
||||
# define PlatformIsLinux 0
|
||||
#else
|
||||
# error Unknown platform
|
||||
#endif
|
||||
|
||||
//- Architecture
|
||||
# if defined(_M_AMD64) || defined(__amd64__)
|
||||
# define ArchIsX64 1
|
||||
# define ArchIsArm64 0
|
||||
# elif defined(_M_ARM64) || defined(__aarch64__)
|
||||
# define ArchIsX64 0
|
||||
# define ArchIsArm64 1
|
||||
# else
|
||||
# error Unknown architecture
|
||||
# endif
|
||||
|
||||
//- Windows NTDDI version
|
||||
/* TODO: Remove this */
|
||||
#if 0
|
||||
@ -118,8 +129,7 @@
|
||||
//- Debug assert
|
||||
#if RtcIsEnabled
|
||||
# if CompilerIsMsvc
|
||||
// # define Assert(cond) ((cond) ? 1 : (IsRunningInDebugger() ? (*(volatile i32 *)0 = 0) : Panic(Lit("Assert(" #cond ") failed at " __FILE__ ":" Stringize(__LINE__)))))
|
||||
# define Assert(cond) ((cond) ? 1 : (IsRunningInDebugger() ? (*(volatile i32 *)0 = 0) : Panic(Lit(__FILE__ "(" Stringize(__LINE__) "): error Assert("#cond")"))))
|
||||
# define Assert(cond) ((cond) ? 1 : (IsRunningInDebugger() ? (*(volatile i32 *)0 = 0) : Panic(Lit(__FILE__ ":" Stringize(__LINE__) ":0: assertion failed: "#cond""))))
|
||||
# define DEBUGBREAK __debugbreak
|
||||
# else
|
||||
# define Assert(cond) ((cond) ? 1 : (__builtin_trap(), 0))
|
||||
@ -268,44 +278,52 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
||||
#define SetNil(nil,p) ((p) = nil)
|
||||
|
||||
//- Singly linked list stack (first & next pointers)
|
||||
#define SllStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
||||
#define SllStackPop_N(f,next) ((f)=(f)->next)
|
||||
#define SllStackPush(f,n) SllStackPush_N(f,n,next)
|
||||
#define SllStackPop(f) SllStackPop_N(f,next)
|
||||
|
||||
#define StackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
||||
#define StackPop_N(f,next) ((f)=(f)->next)
|
||||
#define StackPush(f,n) StackPush_N(f,n,next)
|
||||
#define StackPop(f) StackPop_N(f,next)
|
||||
|
||||
//- Singly linked list queue (first, last, & next pointers)
|
||||
#define SllQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
||||
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
||||
|
||||
#define QueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f) ? \
|
||||
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
||||
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)))
|
||||
#define SllQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
||||
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
||||
|
||||
#define QueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f) ? \
|
||||
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
||||
((n)->next=(f),(f)=(n)))
|
||||
#define SllQueuePop_NZ(nil,f,l,next) ((f)==(l)?\
|
||||
(SetNil(nil,f),SetNil(nil,l)):\
|
||||
|
||||
#define QueuePop_NZ(nil,f,l,next) ((f)==(l) ? \
|
||||
(SetNil(nil,f),SetNil(nil,l)) : \
|
||||
((f)=(f)->next))
|
||||
#define SllQueuePush_N(f,l,n,next) SllQueuePush_NZ(0,f,l,n,next)
|
||||
#define SllQueuePushFront_N(f,l,n,next) SllQueuePushFront_NZ(0,f,l,n,next)
|
||||
#define SllQueuePop_N(f,l,next) SllQueuePop_NZ(0,f,l,next)
|
||||
#define SllQueuePush(f,l,n) SllQueuePush_NZ(0,f,l,n,next)
|
||||
#define SllQueuePushFront(f,l,n) SllQueuePushFront_NZ(0,f,l,n,next)
|
||||
#define SllQueuePop(f,l) SllQueuePop_NZ(0,f,l,next)
|
||||
|
||||
#define QueuePush_N(f,l,n,next) QueuePush_NZ(0,f,l,n,next)
|
||||
#define QueuePushFront_N(f,l,n,next) QueuePushFront_NZ(0,f,l,n,next)
|
||||
#define QueuePop_N(f,l,next) QueuePop_NZ(0,f,l,next)
|
||||
#define QueuePush(f,l,n) QueuePush_NZ(0,f,l,n,next)
|
||||
#define QueuePushFront(f,l,n) QueuePushFront_NZ(0,f,l,n,next)
|
||||
#define QueuePop(f,l) QueuePop_NZ(0,f,l,next)
|
||||
|
||||
//- Doubly linked list (first, last, next, & prev pointers)
|
||||
#define DllInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
|
||||
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\
|
||||
CheckNil(nil,p) ? \
|
||||
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\
|
||||
((p)==(l)) ? \
|
||||
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\
|
||||
|
||||
#define DllInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
|
||||
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) : \
|
||||
CheckNil(nil,p) ? \
|
||||
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) : \
|
||||
((p)==(l)) ? \
|
||||
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) : \
|
||||
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
|
||||
|
||||
#define DllRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)), \
|
||||
((n) == (l) ? (l) = (l)->prev : (0)), \
|
||||
(CheckNil(nil,(n)->prev) ? (0) : \
|
||||
((n)->prev->next = (n)->next)), \
|
||||
(CheckNil(nil,(n)->next) ? (0) : \
|
||||
((n)->next->prev = (n)->prev)))
|
||||
|
||||
#define DllPushBack_NPZ(nil,f,l,n,next,prev) DllInsert_NPZ(nil,f,l,l,n,next,prev)
|
||||
#define DllPushFront_NPZ(nil,f,l,n,next,prev) DllInsert_NPZ(nil,l,f,f,n,prev,next)
|
||||
#define DllRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\
|
||||
((n) == (l) ? (l) = (l)->prev : (0)),\
|
||||
(CheckNil(nil,(n)->prev) ? (0) :\
|
||||
((n)->prev->next = (n)->next)),\
|
||||
(CheckNil(nil,(n)->next) ? (0) :\
|
||||
((n)->next->prev = (n)->prev)))
|
||||
#define DllInsert_NP(f,l,p,n,next,prev) DllInsert_NPZ(0,f,l,p,n,next,prev)
|
||||
#define DllPushBack_NP(f,l,n,next,prev) DllPushBack_NPZ(0,f,l,n,next,prev)
|
||||
#define DllPushFront_NP(f,l,n,next,prev) DllPushFront_NPZ(0,f,l,n,next,prev)
|
||||
@ -368,8 +386,8 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
||||
* wmmintrin.h AES
|
||||
* immintrin.h AVX, AVX2, FMA
|
||||
*/
|
||||
#include "intrin.h"
|
||||
#include "nmmintrin.h" /* SSE4.2 */
|
||||
#include <intrin.h>
|
||||
#include <nmmintrin.h> /* SSE4.2 */
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
@ -512,27 +530,27 @@ StaticAssert(sizeof(Atomic16Padded) == 64 && alignof(Atomic16Padded) == 64);
|
||||
StaticAssert(sizeof(Atomic32Padded) == 64 && alignof(Atomic32Padded) == 64);
|
||||
StaticAssert(sizeof(Atomic64Padded) == 64 && alignof(Atomic64Padded) == 64);
|
||||
|
||||
#if PlatformIsWindows
|
||||
#if PlatformIsWindows && ArchIsX64
|
||||
//- 8 bit atomic operations
|
||||
ForceInline i8 Atomic8Fetch(Atomic8 *x) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, 0, 0); }
|
||||
ForceInline i8 Atomic8FetchSet(Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((char *)&x->_v, e); }
|
||||
ForceInline i8 Atomic8FetchTestSet(Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, e, c); }
|
||||
ForceInline i8 Atomic8FetchXor(Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((char *)&x->_v, c); }
|
||||
ForceInline i8 Atomic8FetchAdd(Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((char *)&x->_v, a); }
|
||||
ForceInline i8 Atomic8Fetch(Atomic8 *x) { return x->_v; }
|
||||
ForceInline i8 Atomic8FetchSet(Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((volatile char *)&x->_v, e); }
|
||||
ForceInline i8 Atomic8FetchTestSet(Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((volatile char *)&x->_v, e, c); }
|
||||
ForceInline i8 Atomic8FetchXor(Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((volatile char *)&x->_v, c); }
|
||||
ForceInline i8 Atomic8FetchAdd(Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((volatile char *)&x->_v, a); }
|
||||
//- 16 bit atomic operations
|
||||
ForceInline i16 Atomic16Fetch(Atomic16 *x) { return (i16)_InterlockedCompareExchange16(&x->_v, 0, 0); }
|
||||
ForceInline i16 Atomic16Fetch(Atomic16 *x) { return x->_v; }
|
||||
ForceInline i16 Atomic16FetchSet(Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&x->_v, e); }
|
||||
ForceInline i16 Atomic16FetchTestSet(Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&x->_v, e, c); }
|
||||
ForceInline i16 Atomic16FetchTestXor(Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&x->_v, c); }
|
||||
ForceInline i16 Atomic16FetchTestAdd(Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&x->_v, a); }
|
||||
//- 32 bit atomic operations
|
||||
ForceInline i32 Atomic32Fetch(Atomic32 *x) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, 0, 0); }
|
||||
ForceInline i32 Atomic32Fetch(Atomic32 *x) { return x->_v; }
|
||||
ForceInline i32 Atomic32FetchSet(Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&x->_v, e); }
|
||||
ForceInline i32 Atomic32FetchTestSet(Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, e, c); }
|
||||
ForceInline i32 Atomic32FetchXor(Atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&x->_v, c); }
|
||||
ForceInline i32 Atomic32FetchAdd(Atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&x->_v, a); }
|
||||
//- 64 bit atomic operations
|
||||
ForceInline i64 Atomic64Fetch(Atomic64 *x) { return (i64)_InterlockedCompareExchange64(&x->_v, 0, 0); }
|
||||
ForceInline i64 Atomic64Fetch(Atomic64 *x) { return x->_v; }
|
||||
ForceInline i64 Atomic64FetchSet(Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&x->_v, e); }
|
||||
ForceInline i64 Atomic64FetchTestSet(Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&x->_v, e, c); }
|
||||
ForceInline i64 Atomic64FetchXor(Atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&x->_v, c); }
|
||||
@ -627,7 +645,7 @@ Struct(StringList)
|
||||
//~ Fiber id
|
||||
|
||||
#if PlatformIsWindows
|
||||
# define FiberId (*(i16 *)(void *)(volatile u64)__readgsqword(32))
|
||||
# define FiberId() (*(i16 *)(void *)(volatile u64)__readgsqword(32))
|
||||
#else
|
||||
# error FiberId not implemented
|
||||
#endif
|
||||
|
||||
@ -194,7 +194,7 @@ Inline ArenaCtx *ArenaCtxFromFiberId(i16 fiber_id)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
#define PermArena (ArenaCtxFromFiberId(FiberId)->perm_arena)
|
||||
#define PermArena (ArenaCtxFromFiberId(FiberId())->perm_arena)
|
||||
|
||||
////////////////////////////////
|
||||
//~ Scratch helpers
|
||||
@ -215,7 +215,7 @@ Inline TempArena BeginScratch(Arena *potential_conflict)
|
||||
/* Use `BeginScratchNoConflict` if no conflicts are present */
|
||||
Assert(potential_conflict != 0);
|
||||
|
||||
ArenaCtx *ctx = ArenaCtxFromFiberId(FiberId);
|
||||
ArenaCtx *ctx = ArenaCtxFromFiberId(FiberId());
|
||||
Arena *scratch_arena = ctx->scratch_arenas[0];
|
||||
if (scratch_arena == potential_conflict)
|
||||
{
|
||||
@ -239,7 +239,7 @@ Inline TempArena BeginScratch(Arena *potential_conflict)
|
||||
|
||||
Inline TempArena BeginScratchNoConflict_(void)
|
||||
{
|
||||
ArenaCtx *ctx = ArenaCtxFromFiberId(FiberId);
|
||||
ArenaCtx *ctx = ArenaCtxFromFiberId(FiberId());
|
||||
Arena *scratch_arena = ctx->scratch_arenas[0];
|
||||
TempArena temp = BeginTempArena(scratch_arena);
|
||||
return temp;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
////////////////////////////////
|
||||
//~ Buff management
|
||||
|
||||
BB_Buff AcquireBitbuff(u64 arena_reserve)
|
||||
BB_Buff BB_AcquireBuff(u64 arena_reserve)
|
||||
{
|
||||
BB_Buff result = ZI;
|
||||
result.arena = AcquireArena(arena_reserve);
|
||||
@ -11,7 +11,7 @@ BB_Buff AcquireBitbuff(u64 arena_reserve)
|
||||
return result;
|
||||
}
|
||||
|
||||
void ReleaseBitbuff(BB_Buff *bb)
|
||||
void BB_ReleaseBuff(BB_Buff *bb)
|
||||
{
|
||||
/* Only arena bitbuffs need to be released */
|
||||
if (bb->is_backed_by_arena)
|
||||
@ -20,7 +20,7 @@ void ReleaseBitbuff(BB_Buff *bb)
|
||||
}
|
||||
}
|
||||
|
||||
BB_Buff BitbuffFromString(String s)
|
||||
BB_Buff BB_BuffFromString(String s)
|
||||
{
|
||||
BB_Buff result = ZI;
|
||||
result.fixed_buffer = s;
|
||||
@ -112,7 +112,7 @@ b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits)
|
||||
else
|
||||
{
|
||||
u64 max_len = bb->fixed_buffer.len;
|
||||
if (bytes_needed >= max_len)
|
||||
if (bytes_needed > max_len)
|
||||
{
|
||||
/* Writer overflowed fixed buffer */
|
||||
Assert(0);
|
||||
@ -129,17 +129,34 @@ b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits)
|
||||
//~ Align writer
|
||||
|
||||
/* Align the pos to the next byte */
|
||||
void BB_AlignWriter(BB_Writer *bw)
|
||||
void BB_WriteAlignToNextByte(BB_Writer *bw)
|
||||
{
|
||||
#if BITBUFF_DEBUG
|
||||
if ((bw->cur_bit & 7) != 0)
|
||||
{
|
||||
BB_WriteDebugMagic(bw, BB_DebugMagicKind_Align, 0);
|
||||
BB_WriteDebugMagic(bw, BB_DebugMagicKind_AlignNextByte, 0);
|
||||
}
|
||||
#endif
|
||||
bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7;
|
||||
}
|
||||
|
||||
void BB_WriteAlign(BB_Writer *bw, u64 align)
|
||||
{
|
||||
BB_WriteAlignToNextByte(bw);
|
||||
BB_WriteDebugMagic(bw, BB_DebugMagicKind_Align, align);
|
||||
if (align > 0)
|
||||
{
|
||||
u64 new_pos = (bw->cur_bit >> 3);
|
||||
new_pos += (align - 1);
|
||||
new_pos -= new_pos % align;
|
||||
if (BB_CheckWriterOverflowBits(bw, new_pos << 3))
|
||||
{
|
||||
return;
|
||||
}
|
||||
bw->cur_bit = new_pos << 3;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Write bits
|
||||
|
||||
@ -301,7 +318,7 @@ void BB_WriteString(BB_Writer *bw, String s)
|
||||
void BB_WriteBytes(BB_Writer *bw, String bytes)
|
||||
{
|
||||
/* Align start of bytes */
|
||||
BB_AlignWriter(bw);
|
||||
BB_WriteAlignToNextByte(bw);
|
||||
|
||||
u64 num_bits = bytes.len << 3;
|
||||
if (BB_CheckWriterOverflowBits(bw, num_bits))
|
||||
@ -314,6 +331,19 @@ void BB_WriteBytes(BB_Writer *bw, String bytes)
|
||||
bw->cur_bit += num_bits;
|
||||
}
|
||||
|
||||
void BB_WriteSeekBytes(BB_Writer *bw, u64 num_bytes)
|
||||
{
|
||||
BB_WriteAlignToNextByte(bw);
|
||||
|
||||
u64 num_bits = num_bytes << 3;
|
||||
if (BB_CheckWriterOverflowBits(bw, num_bits))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bw->cur_bit += num_bits;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Writer debug
|
||||
|
||||
@ -430,17 +460,34 @@ b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits)
|
||||
//~ Align reader
|
||||
|
||||
/* Align the pos to the next byte */
|
||||
void BB_AlignReader(BB_Reader *br)
|
||||
void BB_ReadAlignToNextByte(BB_Reader *br)
|
||||
{
|
||||
#if BITBUFF_DEBUG
|
||||
if ((br->cur_bit & 7) != 0)
|
||||
{
|
||||
BB_ReadDebugMagic(br, BB_DebugMagicKind_Align, 0);
|
||||
BB_ReadDebugMagic(br, BB_DebugMagicKind_AlignNextByte, 0);
|
||||
}
|
||||
#endif
|
||||
br->cur_bit += (8 - (br->cur_bit & 7)) & 7;
|
||||
}
|
||||
|
||||
void BB_ReadAlign(BB_Reader *br, u64 align)
|
||||
{
|
||||
BB_ReadAlignToNextByte(br);
|
||||
BB_ReadDebugMagic(br, BB_DebugMagicKind_Align, align);
|
||||
if (align > 0)
|
||||
{
|
||||
u64 new_pos = (br->cur_bit >> 3);
|
||||
new_pos += (align - 1);
|
||||
new_pos -= new_pos % align;
|
||||
if (BB_CheckReaderOverflowBits(br, new_pos << 3))
|
||||
{
|
||||
return;
|
||||
}
|
||||
br->cur_bit = new_pos << 3;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Read bits
|
||||
|
||||
@ -629,7 +676,7 @@ void BB_ReadBytes(BB_Reader *br, String out)
|
||||
/* Will return 0 on bitbuff overflow. Result should be checked. */
|
||||
u8 *BB_ReadBytesRaw(BB_Reader *br, u64 num_bytes)
|
||||
{
|
||||
BB_AlignReader(br);
|
||||
BB_ReadAlignToNextByte(br);
|
||||
|
||||
u64 num_bits = num_bytes << 3;
|
||||
if (BB_CheckReaderOverflowBits(br, num_bits))
|
||||
@ -643,9 +690,9 @@ u8 *BB_ReadBytesRaw(BB_Reader *br, u64 num_bytes)
|
||||
return raw;
|
||||
}
|
||||
|
||||
void BB_SeekBytes(BB_Reader *br, u64 num_bytes)
|
||||
void BB_ReadSeekBytes(BB_Reader *br, u64 num_bytes)
|
||||
{
|
||||
BB_AlignReader(br);
|
||||
BB_ReadAlignToNextByte(br);
|
||||
|
||||
u64 num_bits = num_bytes << 3;
|
||||
if (BB_CheckReaderOverflowBits(br, num_bits))
|
||||
@ -656,12 +703,12 @@ void BB_SeekBytes(BB_Reader *br, u64 num_bytes)
|
||||
br->cur_bit += num_bits;
|
||||
}
|
||||
|
||||
void BB_SeekToByte(BB_Reader *br, u64 pos)
|
||||
void BB_ReadSeekToByte(BB_Reader *br, u64 pos)
|
||||
{
|
||||
u64 cur_byte_pos = br->cur_bit >> 3;
|
||||
if (pos >= cur_byte_pos)
|
||||
{
|
||||
BB_SeekBytes(br, pos - cur_byte_pos);
|
||||
BB_ReadSeekBytes(br, pos - cur_byte_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -670,7 +717,6 @@ void BB_SeekToByte(BB_Reader *br, u64 pos)
|
||||
br->overflowed = 1;
|
||||
br->cur_bit = (br->base_len << 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@ -809,7 +855,7 @@ void BB_Test(void)
|
||||
|
||||
String encoded = ZI;
|
||||
{
|
||||
BB_Buff bb = AcquireBitbuff(Gibi(64));
|
||||
BB_Buff bb = BB_AcquireBuff(Gibi(64));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
for (u64 i = 0; i < countof(cases); ++i)
|
||||
{
|
||||
@ -843,7 +889,7 @@ void BB_Test(void)
|
||||
}
|
||||
|
||||
{
|
||||
BB_Buff bb = BitbuffFromString(encoded);
|
||||
BB_Buff bb = BB_BuffFromString(encoded);
|
||||
BB_Reader br = BB_ReaderFromBuff(&bb);
|
||||
for (u64 i = 0; i < countof(cases); ++i)
|
||||
{
|
||||
@ -47,15 +47,16 @@ Struct(BB_Reader)
|
||||
/* Magic numbers inserted to verify read/write type & length */
|
||||
Enum(BB_DebugMagicKind)
|
||||
{
|
||||
BB_DebugMagicKind_Align = 0x20A4,
|
||||
BB_DebugMagicKind_UBits = 0xCB4A,
|
||||
BB_DebugMagicKind_IBits = 0xB30D,
|
||||
BB_DebugMagicKind_UV = 0xE179,
|
||||
BB_DebugMagicKind_IV = 0x981f,
|
||||
BB_DebugMagicKind_F32 = 0x56F9,
|
||||
BB_DebugMagicKind_F64 = 0x7053,
|
||||
BB_DebugMagicKind_Uid = 0xA24E,
|
||||
BB_DebugMagicKind_String = 0x7866
|
||||
BB_DebugMagicKind_Align = 0x20A4,
|
||||
BB_DebugMagicKind_AlignToNextByte = 0x379A,
|
||||
BB_DebugMagicKind_UBits = 0xCB4A,
|
||||
BB_DebugMagicKind_IBits = 0xB30D,
|
||||
BB_DebugMagicKind_UV = 0xE179,
|
||||
BB_DebugMagicKind_IV = 0x981f,
|
||||
BB_DebugMagicKind_F32 = 0x56F9,
|
||||
BB_DebugMagicKind_F64 = 0x7053,
|
||||
BB_DebugMagicKind_Uid = 0xA24E,
|
||||
BB_DebugMagicKind_String = 0x7866
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -63,10 +64,12 @@ Enum(BB_DebugMagicKind)
|
||||
////////////////////////////////
|
||||
//~ Buff management
|
||||
|
||||
BB_Buff AcquireBitbuff(u64 arena_reserve);
|
||||
void ReleaseBitbuff(BB_Buff *bitbuff);
|
||||
//- Growable-arena backed bitbuff
|
||||
BB_Buff BB_AcquireBuff(u64 arena_reserve);
|
||||
void BB_ReleaseBuff(BB_Buff *bitbuff);
|
||||
|
||||
BB_Buff BitbuffFromString(String s);
|
||||
//- Fixed-buffer backed bitbuff
|
||||
BB_Buff BB_BuffFromString(String s);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Writer management
|
||||
@ -86,7 +89,8 @@ b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits);
|
||||
//~ Writer ops
|
||||
|
||||
//- Align
|
||||
void BB_AlignWriter(BB_Writer *bw);
|
||||
void BB_WriteAlignToNextByte(BB_Writer *bw);
|
||||
void BB_WriteAlign(BB_Writer *bw, u64 align);
|
||||
|
||||
//- Bits
|
||||
void BB_WriteUBitsNoMagic(BB_Writer *bw, u64 value, u8 num_bits);
|
||||
@ -108,6 +112,7 @@ void BB_WriteUid(BB_Writer *bw, Uid value);
|
||||
//- Raw data
|
||||
void BB_WriteString(BB_Writer *bw, String s);
|
||||
void BB_WriteBytes(BB_Writer *bw, String bytes);
|
||||
void BB_WriteSeekBytes(BB_Writer *bw, u64 num_bytes);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Writer debug
|
||||
@ -138,7 +143,8 @@ b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits);
|
||||
//~ Reader ops
|
||||
|
||||
//- Align
|
||||
void BB_AlignReader(BB_Reader *br);
|
||||
void BB_ReadAlignToNextByte(BB_Reader *br);
|
||||
void BB_ReadAlign(BB_Reader *br, u64 align);
|
||||
|
||||
//- Bits
|
||||
u64 BB_ReadUBitsNoMagic(BB_Reader *br, u8 num_bits);
|
||||
@ -161,8 +167,8 @@ Uid BB_ReadUid(BB_Reader *br);
|
||||
String BB_ReadString(Arena *arena, BB_Reader *br);
|
||||
void BB_ReadBytes(BB_Reader *br, String dst);
|
||||
u8 *BB_ReadBytesRaw(BB_Reader *br, u64 num_bytes);
|
||||
void BB_SeekBytes(BB_Reader *br, u64 num_bytes);
|
||||
void BB_SeekToByte(BB_Reader *br, u64 pos);
|
||||
void BB_ReadSeekBytes(BB_Reader *br, u64 num_bytes);
|
||||
void BB_ReadSeekToByte(BB_Reader *br, u64 pos);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Reader debug
|
||||
@ -19,6 +19,8 @@
|
||||
# include "base_rand.h"
|
||||
# include "base_util.h"
|
||||
# include "base_entry.h"
|
||||
# include "base_bitbuff.h"
|
||||
# include "base_resource.h"
|
||||
#elif LanguageIsGpu
|
||||
# include "base_math_gpu.h"
|
||||
#endif
|
||||
@ -35,9 +37,11 @@
|
||||
# include "base_buddy.c"
|
||||
# include "base_math.c"
|
||||
# include "base_rand.c"
|
||||
# include "base_bitbuff.c"
|
||||
# include "base_resource.c"
|
||||
#endif
|
||||
|
||||
//- Win32 impl
|
||||
//- Include base_win32
|
||||
#if LanguageIsC && PlatformIsWindows
|
||||
# include "base_win32/base_win32_inc.h"
|
||||
#endif
|
||||
|
||||
@ -55,8 +55,6 @@ void FutexWake(void *addr, i32 count);
|
||||
////////////////////////////////
|
||||
//~ @hookdecl Job operations
|
||||
|
||||
#define EmptySig { i32 _; }
|
||||
|
||||
typedef void GenericJobFunc(void *, i32);
|
||||
|
||||
Struct(GenericJobDesc)
|
||||
@ -82,6 +80,11 @@ Struct(JobDescParams)
|
||||
Counter *counter;
|
||||
};
|
||||
|
||||
#define EmptySig { i32 _; }
|
||||
|
||||
#define PushJobDesc(job, ...) (job##_Desc *)PushJobDesc_(sizeof(job##_Sig), alignof(job##_Sig), job##_Generic, (JobDescParams) { .count = 1, .pool = JobPool_Inherit, .priority = JobPriority_Inherit, .counter = 0, __VA_ARGS__ })
|
||||
GenericJobDesc *PushJobDesc_(u64 sig_size, u64 sig_align, GenericJobFunc *func, JobDescParams params);
|
||||
|
||||
#define JobDecl(job, sigdef) \
|
||||
typedef struct job##_Sig sigdef job##_Sig; \
|
||||
Struct(job##_Desc) { Arena *arena; job##_Sig *sig; GenericJobFunc *func; i32 count; JobPool pool; JobPriority priority; Counter *counter; }; \
|
||||
@ -89,16 +92,28 @@ Struct(JobDescParams)
|
||||
inline void job##_Generic(void *sig, i32 id) { job((job##_Sig *)sig, id); } \
|
||||
StaticAssert(1)
|
||||
|
||||
#define PushJobDesc(job, ...) (job##_Desc *)PushJobDesc_(sizeof(job##_Sig), alignof(job##_Sig), job##_Generic, (JobDescParams) { .count = 1, .pool = JobPool_Inherit, .priority = JobPriority_Inherit, .counter = 0, __VA_ARGS__ })
|
||||
GenericJobDesc *PushJobDesc_(u64 sig_size, u64 sig_align, GenericJobFunc *func, JobDescParams params);
|
||||
|
||||
#define JobDef(job, sig_arg, id_arg) void job(job##_Sig *sig_arg, i32 id_arg)
|
||||
|
||||
#define RunJob(_count, job, _pool, _priority, _counter, ...) do { \
|
||||
/* RunJob example usage:
|
||||
*
|
||||
* This example pushes a single 'LoadTextureJob' onto the background job
|
||||
* pool, copying 'sprite' into the job signature. 'counter' is also passed
|
||||
* and then immediately yielded on in this example, effectively making
|
||||
* the operation synchronous as the caller will block until the job completes:
|
||||
* {
|
||||
* Counter counter = {0};
|
||||
* RunJob(1, LoadTextureJob, JobPool_Background, JobPriority_Low, &counter, .resource = sprite);
|
||||
* YieldOnCounter(&counter);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
#define RunJob(_count, job, _pool, _priority, _counter, ...) \
|
||||
do { \
|
||||
job##_Desc *__job_desc = (job##_Desc *)PushJobDesc_(sizeof(job##_Sig), alignof(job##_Sig), job##_Generic, (JobDescParams) { .count = _count, .pool = _pool, .priority = _priority, .counter = _counter,}); \
|
||||
*__job_desc->sig = (job##_Sig) { __VA_ARGS__ }; \
|
||||
RunJobEx((GenericJobDesc *)__job_desc); \
|
||||
} while (0)
|
||||
|
||||
void RunJobEx(GenericJobDesc *desc);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@ -45,7 +45,7 @@ void SetMemoryReadWrite(void *address, u64 size)
|
||||
#endif /* PlatformIsWindows */
|
||||
|
||||
////////////////////////////////
|
||||
//~ Crtlib memory.h stubs
|
||||
//~ Crtlib mem op stubs
|
||||
|
||||
#if !CrtlibIsEnabled
|
||||
|
||||
|
||||
95
src/base/base_resource.c
Normal file
95
src/base/base_resource.c
Normal file
@ -0,0 +1,95 @@
|
||||
SharedResourceState shared_resource_state = ZI;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
void InitBaseResources(String archive)
|
||||
{
|
||||
SharedResourceState *g = &shared_resource_state;
|
||||
if (archive.len <= 0) return;
|
||||
|
||||
BB_Buff bb = BB_BuffFromString(archive);
|
||||
BB_Reader br = BB_ReaderFromBuff(&bb);
|
||||
|
||||
u64 magic = BB_ReadUBits(&br, 64);
|
||||
Assert(magic == ResourceEmbeddedMagic);
|
||||
|
||||
/* Create & insert entries */
|
||||
u64 num_entries = BB_ReadUBits(&br, 64);
|
||||
for (u64 i = 0; i < num_entries; ++i)
|
||||
{
|
||||
u64 name_start = BB_ReadUBits(&br, 64);
|
||||
u64 name_len = BB_ReadUBits(&br, 64);
|
||||
u64 data_start = BB_ReadUBits(&br, 64);
|
||||
u64 data_len = BB_ReadUBits(&br, 64);
|
||||
|
||||
ResourceEntry *entry = PushStruct(PermArena, ResourceEntry);
|
||||
entry->name = STRING(name_len, archive.text + name_start);
|
||||
entry->data = STRING(data_len, archive.text + data_start);
|
||||
entry->hash = HashFnv64(Fnv64Basis, entry->name);
|
||||
|
||||
ResourceEntryBin *bin = &g->bins[entry->hash % NumResourceEntryBins];
|
||||
QueuePush_N(bin->first, bin->last, entry, next_in_bin);
|
||||
QueuePush_N(g->first_entry, g->last_entry, entry, next);
|
||||
}
|
||||
g->entries_count = num_entries;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource helpers
|
||||
|
||||
b32 IsResourceNil(Resource resource)
|
||||
{
|
||||
return resource.hash == 0;
|
||||
}
|
||||
|
||||
Resource ResourceFromStore(ResourceStore *store, String name)
|
||||
{
|
||||
Resource result = ZI;
|
||||
result.hash = HashFnv64(store->hash, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource cache operations
|
||||
|
||||
ResourceEntry *ResourceEntryFromHash(u64 hash)
|
||||
{
|
||||
ResourceEntry *result = 0;
|
||||
SharedResourceState *g = &shared_resource_state;
|
||||
ResourceEntryBin *bin = &g->bins[hash % NumResourceEntryBins];
|
||||
for (ResourceEntry *e = bin->first; e; e = e->next_in_bin)
|
||||
{
|
||||
if (e->hash == hash)
|
||||
{
|
||||
result = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource operations
|
||||
|
||||
String DataFromResource(Resource resource)
|
||||
{
|
||||
String result = ZI;
|
||||
ResourceEntry *entry = ResourceEntryFromHash(resource.hash);
|
||||
if (entry)
|
||||
{
|
||||
result = entry->data;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String NameFromResource(Resource resource)
|
||||
{
|
||||
String result = ZI;
|
||||
ResourceEntry *entry = ResourceEntryFromHash(resource.hash);
|
||||
if (entry)
|
||||
{
|
||||
result = entry->name;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
72
src/base/base_resource.h
Normal file
72
src/base/base_resource.h
Normal file
@ -0,0 +1,72 @@
|
||||
////////////////////////////////
|
||||
//~ Resource types
|
||||
|
||||
#define ResourceEmbeddedMagic 0xfc060937194f4406
|
||||
|
||||
#define DeclResourceStore(name) extern ResourceStore name
|
||||
|
||||
Struct(ResourceStore)
|
||||
{
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
Struct(Resource)
|
||||
{
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource cache types
|
||||
|
||||
Struct(ResourceEntry)
|
||||
{
|
||||
ResourceEntry *next;
|
||||
ResourceEntry *next_in_bin;
|
||||
|
||||
u64 hash;
|
||||
String name;
|
||||
String data;
|
||||
};
|
||||
|
||||
Struct(ResourceEntryBin)
|
||||
{
|
||||
ResourceEntry *first;
|
||||
ResourceEntry *last;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Shared state
|
||||
|
||||
#define NumResourceEntryBins 4096
|
||||
|
||||
Struct(SharedResourceState)
|
||||
{
|
||||
ResourceEntry *first_entry;
|
||||
ResourceEntry *last_entry;
|
||||
u64 entries_count;
|
||||
ResourceEntryBin bins[NumResourceEntryBins];
|
||||
};
|
||||
|
||||
extern SharedResourceState shared_resource_state;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
void InitBaseResources(String archive);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource operations
|
||||
|
||||
b32 IsResourceNil(Resource resource);
|
||||
Resource ResourceFromStore(ResourceStore *store, String name);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource cache operations
|
||||
|
||||
ResourceEntry *ResourceEntryFromHash(u64 hash);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource data operations
|
||||
|
||||
String DataFromResource(Resource resource);
|
||||
String NameFromResource(Resource resource);
|
||||
@ -56,7 +56,7 @@ Lock LockSpinE(Mutex *m, i32 spin)
|
||||
}
|
||||
|
||||
#if RtcIsEnabled
|
||||
Atomic32FetchSet(&m->exclusive_fiber_id, FiberId);
|
||||
Atomic32FetchSet(&m->exclusive_fiber_id, FiberId());
|
||||
#endif
|
||||
|
||||
Lock lock = ZI;
|
||||
@ -173,6 +173,11 @@ void SignalCv(Cv *cv, i32 count)
|
||||
////////////////////////////////
|
||||
//~ Counter
|
||||
|
||||
u64 ValueFromCounter(Counter *counter)
|
||||
{
|
||||
return Atomic64Fetch(&counter->v);
|
||||
}
|
||||
|
||||
void AddCounter(Counter *counter, i64 x)
|
||||
{
|
||||
i64 old_v = Atomic64FetchAdd(&counter->v, x);
|
||||
|
||||
@ -79,5 +79,6 @@ void SignalCv(Cv *cv, i32 count);
|
||||
////////////////////////////////
|
||||
//~ Counter operations
|
||||
|
||||
u64 ValueFromCounter(Counter *counter);
|
||||
void AddCounter(Counter *counter, i64 x);
|
||||
void YieldOnCounter(Counter *counter);
|
||||
|
||||
@ -294,3 +294,10 @@ Inline u64 DictValueFromHash(Dict *dict, u64 hash)
|
||||
DictEntry *entry = DictEntryFromHash(dict, hash);
|
||||
return entry ? entry->value : 0;
|
||||
}
|
||||
|
||||
Inline u64 DictValueOrNilFromHash(Dict *dict, u64 hash, u64 nil)
|
||||
{
|
||||
__prof;
|
||||
DictEntry *entry = DictEntryFromHash(dict, hash);
|
||||
return entry ? entry->value : nil;
|
||||
}
|
||||
|
||||
@ -1,5 +1,34 @@
|
||||
W32_SharedState W32_shared_state = ZI;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Win32 embedded data
|
||||
|
||||
/* Find first resource with `type` and return the data in `udata`. */
|
||||
BOOL W32_FindEmbeddedRcData(HMODULE module, LPCWSTR type, LPWSTR wstr_entry_name, LONG_PTR udata)
|
||||
{
|
||||
W32_SharedState *g = &W32_shared_state;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
String *out = (String *)udata;
|
||||
b32 found = 0;
|
||||
String entry_name_lower = LowerString(scratch.arena, StringFromWstrNoLimit(scratch.arena, (LPWSTR)wstr_entry_name));
|
||||
if (EqString(entry_name_lower, Lit(Stringize(W32_EmbeddedDataName))))
|
||||
{
|
||||
HRSRC hres = FindResourceW(module, wstr_entry_name, type);
|
||||
if (hres)
|
||||
{
|
||||
HGLOBAL hg = LoadResource(module, hres);
|
||||
if (hg)
|
||||
{
|
||||
found = 1;
|
||||
out->len = SizeofResource(module, hres);
|
||||
out->text = LockResource(hg);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndScratch(scratch);
|
||||
return !found;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ @hookdef Core hooks
|
||||
|
||||
@ -187,9 +216,18 @@ i32 W32_Main(void)
|
||||
/* Query system info */
|
||||
GetSystemInfo(&g->info);
|
||||
|
||||
//- Startup workers
|
||||
/* Startup workers */
|
||||
InitJobWorkers();
|
||||
|
||||
/* Init resources */
|
||||
{
|
||||
String embedded = ZI;
|
||||
EnumResourceNamesW(0, RT_RCDATA, &W32_FindEmbeddedRcData, (LONG_PTR)&embedded);
|
||||
InitBaseResources(embedded);
|
||||
}
|
||||
|
||||
//- App startup
|
||||
|
||||
/* Startup layers */
|
||||
if (!Atomic32Fetch(&g->panicking))
|
||||
{
|
||||
|
||||
@ -13,7 +13,7 @@ u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
||||
////////////////////////////////
|
||||
//~ Shared state
|
||||
|
||||
#define W32_MaxOnExitFuncs 1024
|
||||
#define W32_MaxOnExitFuncs 4096
|
||||
|
||||
Struct(W32_SharedState)
|
||||
{
|
||||
@ -37,6 +37,12 @@ Struct(W32_SharedState)
|
||||
|
||||
extern W32_SharedState W32_shared_state;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Embedded data initialization
|
||||
|
||||
#define W32_EmbeddedDataName embedded_resource_data
|
||||
BOOL W32_FindEmbeddedRcData(HMODULE module, LPCWSTR type, LPWSTR wstr_entry_name, LONG_PTR udata);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup / shutdown jobs
|
||||
|
||||
|
||||
@ -19,7 +19,6 @@ void InitJobWorkers(void)
|
||||
g->timer_start_qpc = qpc.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
/* Init fibers */
|
||||
g->num_fibers = 1; /* Fiber at index 0 always nil */
|
||||
g->fiber_names_arena = AcquireArena(Gibi(64));
|
||||
@ -104,7 +103,6 @@ void InitJobWorkers(void)
|
||||
{
|
||||
name_fmt = Lit("Floating worker #%F");
|
||||
pool->num_worker_threads = 8;
|
||||
pool->thread_affinity_mask = 0x0000000000000FFFull;
|
||||
pool->thread_priority = THREAD_PRIORITY_NORMAL;
|
||||
} break;
|
||||
|
||||
@ -112,7 +110,6 @@ void InitJobWorkers(void)
|
||||
{
|
||||
name_fmt = Lit("Floating worker #%F");
|
||||
pool->num_worker_threads = 8;
|
||||
pool->thread_affinity_mask = 0x0000000000000FFFull;
|
||||
pool->thread_priority = THREAD_PRIORITY_HIGHEST;
|
||||
} break;
|
||||
}
|
||||
@ -840,7 +837,7 @@ ForceNoInline void W32_FiberResume(W32_Fiber *fiber)
|
||||
void W32_YieldFiber(W32_Fiber *fiber, W32_Fiber *parent_fiber)
|
||||
{
|
||||
LAX fiber;
|
||||
Assert(fiber->id == FiberId);
|
||||
Assert(fiber->id == FiberId());
|
||||
Assert(parent_fiber->id == fiber->parent_id);
|
||||
Assert(parent_fiber->id > 0);
|
||||
{
|
||||
@ -959,7 +956,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
|
||||
}
|
||||
}
|
||||
|
||||
i32 worker_fiber_id = FiberId;
|
||||
i32 worker_fiber_id = FiberId();
|
||||
|
||||
W32_Fiber *job_fiber = 0;
|
||||
b32 shutdown = 0;
|
||||
@ -1354,7 +1351,7 @@ W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg)
|
||||
|
||||
void FutexYield(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;
|
||||
if (parent_id != 0)
|
||||
{
|
||||
@ -1446,7 +1443,7 @@ void RunJobEx(GenericJobDesc *desc)
|
||||
{
|
||||
AddCounter(counter, 1);
|
||||
}
|
||||
W32_Fiber *fiber = W32_FiberFromId(FiberId);
|
||||
W32_Fiber *fiber = W32_FiberFromId(FiberId());
|
||||
priority = ClampI32(priority, fiber->job_priority, JobPriority_Count - 1); /* A job cannot create a job with a higher priority than itself */
|
||||
if (pool_kind == JobPool_Inherit)
|
||||
{
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
@Layer bitbuff
|
||||
|
||||
//- Api
|
||||
@IncludeC bitbuff.h
|
||||
|
||||
//- Impl
|
||||
@IncludeC bitbuff.c
|
||||
@ -25,8 +25,8 @@ JobDef(F_LoadJob, sig, _)
|
||||
0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
|
||||
};
|
||||
|
||||
R_Tag resource = sig->resource;
|
||||
String name = R_NameFromTag(resource);
|
||||
Resource resource = sig->resource;
|
||||
String name = NameFromResource(resource);
|
||||
f32 point_size = sig->point_size;
|
||||
AC_Asset *asset = sig->asset;
|
||||
|
||||
@ -37,7 +37,7 @@ JobDef(F_LoadJob, sig, _)
|
||||
Assert(countof(font_codes) < F_LookupTableSize);
|
||||
|
||||
/* Decode */
|
||||
String resource_data = R_DataFromTag(resource);
|
||||
String resource_data = DataFromResource(resource);
|
||||
if (resource_data.len == 0)
|
||||
{
|
||||
/* FIME: Load baked font instead of panicking */
|
||||
@ -104,11 +104,11 @@ JobDef(F_LoadJob, sig, _)
|
||||
//~ Load
|
||||
|
||||
/* Returns the asset from the asset cache */
|
||||
AC_Asset *F_LoadAsset(R_Tag resource, f32 point_size, b32 wait)
|
||||
AC_Asset *F_LoadAsset(Resource resource, f32 point_size, b32 wait)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
String name = R_NameFromTag(resource);
|
||||
String name = NameFromResource(resource);
|
||||
|
||||
/* Concatenate point_size to name for key */
|
||||
String key = StringF(scratch.arena,
|
||||
@ -137,7 +137,7 @@ AC_Asset *F_LoadAsset(R_Tag resource, f32 point_size, b32 wait)
|
||||
return asset;
|
||||
}
|
||||
|
||||
F_Font *F_LoadFontAsync(R_Tag resource, f32 point_size)
|
||||
F_Font *F_LoadFontAsync(Resource resource, f32 point_size)
|
||||
{
|
||||
__prof;
|
||||
AC_Asset *asset = F_LoadAsset(resource, point_size, 0);
|
||||
@ -145,7 +145,7 @@ F_Font *F_LoadFontAsync(R_Tag resource, f32 point_size)
|
||||
return f;
|
||||
}
|
||||
|
||||
F_Font *F_LoadFontWait(R_Tag resource, f32 point_size)
|
||||
F_Font *F_LoadFontWait(Resource resource, f32 point_size)
|
||||
{
|
||||
__prof;
|
||||
AC_Asset *asset = F_LoadAsset(resource, point_size, 1);
|
||||
|
||||
@ -27,14 +27,14 @@ Struct(F_Font)
|
||||
////////////////////////////////
|
||||
//~ Font load job
|
||||
|
||||
JobDecl(F_LoadJob, { AC_Asset *asset; f32 point_size; R_Tag resource; });
|
||||
JobDecl(F_LoadJob, { AC_Asset *asset; f32 point_size; Resource resource; });
|
||||
|
||||
////////////////////////////////
|
||||
//~ Font load operations
|
||||
|
||||
AC_Asset *F_LoadAsset(R_Tag resource, f32 point_size, b32 wait);
|
||||
F_Font *F_LoadFontAsync(R_Tag resource, f32 point_size);
|
||||
F_Font *F_LoadFontWait(R_Tag resource, f32 point_size);
|
||||
AC_Asset *F_LoadAsset(Resource resource, f32 point_size, b32 wait);
|
||||
F_Font *F_LoadFontAsync(Resource resource, f32 point_size);
|
||||
F_Font *F_LoadFontWait(Resource resource, f32 point_size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Font data operations
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
@Dep ttf
|
||||
@Dep gpu
|
||||
@Dep asset_cache
|
||||
@Dep res
|
||||
|
||||
//- Api
|
||||
@IncludeC font.h
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
//- Dependencies
|
||||
@Dep platform
|
||||
@Dep res
|
||||
|
||||
//- Api
|
||||
@IncludeC gpu.h
|
||||
|
||||
1243
src/meta/meta.c
1243
src/meta/meta.c
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,19 @@ String F_GetFull(Arena *arena, String path)
|
||||
return OS_GetFullPath(arena, path);
|
||||
}
|
||||
|
||||
String F_GetFullCrossPlatform(Arena *arena, String path)
|
||||
{
|
||||
String result = OS_GetFullPath(arena, path);
|
||||
for (u64 i = 0; i < result.len; ++i)
|
||||
{
|
||||
if (result.text[i] == '\\')
|
||||
{
|
||||
result.text[i] = '/';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String F_GetFileName(String path)
|
||||
{
|
||||
String result = ZI;
|
||||
|
||||
@ -11,6 +11,7 @@ Enum(F_IterFlag)
|
||||
//~ Path helpers
|
||||
|
||||
String F_GetFull(Arena *arena, String path);
|
||||
String F_GetFullCrossPlatform(Arena *arena, String path);
|
||||
String F_GetFileName(String path);
|
||||
String F_GetParentDir(String path);
|
||||
String F_ExtensionFromFile(String path);
|
||||
|
||||
541
src/meta/meta_lay.c
Normal file
541
src/meta/meta_lay.c
Normal file
@ -0,0 +1,541 @@
|
||||
Readonly M_Token M_NilToken = {
|
||||
.next = &M_NilToken,
|
||||
.file = &M_NilTokenFile,
|
||||
};
|
||||
|
||||
Readonly M_TokenFile M_NilTokenFile = {
|
||||
.next = &M_NilTokenFile,
|
||||
.first_token = &M_NilToken,
|
||||
.last_token = &M_NilToken,
|
||||
};
|
||||
|
||||
Readonly M_Entry M_NilEntry = {
|
||||
.next = &M_NilEntry,
|
||||
.name_token = &M_NilToken,
|
||||
.arg_tokens[0] = &M_NilToken,
|
||||
.arg_tokens[1] = &M_NilToken,
|
||||
};
|
||||
StaticAssert(countof(M_NilEntry.arg_tokens) == 2); /* NilEntry must define point args to nil tokens */
|
||||
|
||||
Readonly M_Layer M_NilLayer = {
|
||||
.next = &M_NilLayer,
|
||||
.file = &M_NilTokenFile,
|
||||
.first = &M_NilEntry,
|
||||
.last = &M_NilEntry,
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Error helpers
|
||||
|
||||
M_Error *M_PushError(Arena *arena, M_ErrorList *l, M_Token *token, String msg)
|
||||
{
|
||||
M_Error *e = PushStruct(arena, M_Error);
|
||||
e->msg = msg;
|
||||
e->token = token ? token : &M_NilToken;
|
||||
QueuePush(l->first, l->last, e);
|
||||
++l->count;
|
||||
return e;
|
||||
}
|
||||
|
||||
void M_AppendErrors(Arena *arena, M_ErrorList *dst, M_ErrorList src)
|
||||
{
|
||||
for (M_Error *e = src.first; e; e = e->next)
|
||||
{
|
||||
M_PushError(arena, dst, e->token, e->msg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Lexer operations
|
||||
|
||||
M_TokenFile *M_PushTokenFile(Arena *arena, M_TokenFileList *l, String name, String data)
|
||||
{
|
||||
M_TokenFile *tf = PushStruct(arena, M_TokenFile);
|
||||
*tf = M_NilTokenFile;
|
||||
tf->valid = 1;
|
||||
tf->name = name;
|
||||
tf->data = data;
|
||||
M_PushToken(arena, tf, Lit(""), M_TokenKind_Eol);
|
||||
QueuePush_NZ(&M_NilTokenFile, l->first, l->last, tf, next);
|
||||
++l->count;
|
||||
return tf;
|
||||
}
|
||||
|
||||
M_Token *M_PushToken(Arena *arena, M_TokenFile *file, String s, M_TokenKind kind)
|
||||
{
|
||||
M_Token *t = PushStruct(arena, M_Token);
|
||||
*t = M_NilToken;
|
||||
t->valid = 1;
|
||||
t->s = s;
|
||||
t->kind = kind;
|
||||
if (file)
|
||||
{
|
||||
t->file = file;
|
||||
}
|
||||
QueuePush_NZ(&M_NilToken, file->first_token, file->last_token, t, next);
|
||||
++file->tokens_count;
|
||||
return t;
|
||||
}
|
||||
|
||||
M_TokenFileList M_TokensFromSrcDirs(Arena *arena, StringList src_dirs)
|
||||
{
|
||||
TempArena scratch = BeginScratch(arena);
|
||||
M_TokenFileList result = ZI;
|
||||
|
||||
/* Build token file list from src dirs */
|
||||
Dict *dedup_dict = InitDict(scratch.arena, 1021);
|
||||
for (StringListNode *dir_name_node = src_dirs.first; dir_name_node; dir_name_node = dir_name_node->next)
|
||||
{
|
||||
String dir_name = dir_name_node->s;
|
||||
StringList files = ZI;
|
||||
F_FilesFromDir(arena, &files, dir_name, F_IterFlag_Recurse);
|
||||
for (StringListNode *file_name_node = files.first; file_name_node; file_name_node = file_name_node->next)
|
||||
{
|
||||
String file_name = file_name_node->s;
|
||||
if (StringEndsWith(file_name, Lit(".lay")))
|
||||
{
|
||||
String tmp_full = F_GetFull(scratch.arena, file_name);
|
||||
u64 hash = HashFnv64(Fnv64Basis, tmp_full);
|
||||
if (DictValueFromHash(dedup_dict, hash) == 0)
|
||||
{
|
||||
SetDictValue(scratch.arena, dedup_dict, hash, 1);
|
||||
String full = PushString(arena, tmp_full);
|
||||
String data = F_DataFromFile(arena, full);
|
||||
M_PushTokenFile(arena, &result, full, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (M_TokenFile *tf = result.first; tf->valid; tf = tf->next)
|
||||
{
|
||||
Enum(TokenizerMode)
|
||||
{
|
||||
TokenizerMode_None,
|
||||
TokenizerMode_SingleLineComment,
|
||||
TokenizerMode_MultiLineComment,
|
||||
};
|
||||
TokenizerMode mode = TokenizerMode_None;
|
||||
|
||||
u8 *t = tf->data.text;
|
||||
u64 l = tf->data.len;
|
||||
u64 p = 0;
|
||||
String cur_ident = STRING(0, t);
|
||||
while (p < l)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case TokenizerMode_None:
|
||||
{
|
||||
u8 c = t[p];
|
||||
b32 is_eol = c == '\r' || c == '\n' || c == 0 || (p + 1) >= l;
|
||||
b32 is_whitespace = is_eol || c == ' ';
|
||||
if (is_whitespace)
|
||||
{ /* Whitespace */
|
||||
if (cur_ident.len > 0)
|
||||
{
|
||||
M_PushToken(arena, tf, cur_ident, M_TokenKind_Ident);
|
||||
cur_ident.len = 0;
|
||||
}
|
||||
if (is_eol)
|
||||
{
|
||||
M_PushToken(arena, tf, STRING(1, &t[p]), M_TokenKind_Eol);
|
||||
}
|
||||
p += 1;
|
||||
}
|
||||
else if (c == '/' && (p + 1) < l && t[p + 1] == '/')
|
||||
{ /* Start single line comment */
|
||||
mode = TokenizerMode_SingleLineComment;
|
||||
p += 2;
|
||||
}
|
||||
else if (c == '/' && (p + 1) < l && t[p + 1] == '*')
|
||||
{ /* Start multi line comment */
|
||||
mode = TokenizerMode_MultiLineComment;
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_ident.len == 0)
|
||||
{
|
||||
cur_ident.text = &t[p];
|
||||
}
|
||||
++cur_ident.len;
|
||||
p += 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
case TokenizerMode_SingleLineComment:
|
||||
{
|
||||
if (t[p] == '\n')
|
||||
{ /* End single line comment */
|
||||
mode = TokenizerMode_None;
|
||||
p += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p += 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
case TokenizerMode_MultiLineComment:
|
||||
{
|
||||
if (t[p] == '*' && (p + 1) < l && t[p + 1] == '/')
|
||||
{ /* End multi line comment */
|
||||
mode = TokenizerMode_None;
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
p += 1;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Parser operations
|
||||
|
||||
M_Layer *M_PushLayer(Arena *arena, M_LayerList *list, M_TokenFile *file)
|
||||
{
|
||||
M_Layer *layer = PushStruct(arena, M_Layer);
|
||||
*layer = M_NilLayer;
|
||||
layer->valid = 1;
|
||||
layer->file = file;
|
||||
QueuePush_NZ(&M_NilLayer, list->first, list->last, layer, next);
|
||||
++list->count;
|
||||
return layer;
|
||||
}
|
||||
|
||||
M_Entry *M_PushEntry(Arena *arena, M_Layer *l, M_EntryKind kind, M_Token *entry_token, u64 args_count, M_Token **args)
|
||||
{
|
||||
M_Entry *e = PushStruct(arena, M_Entry);
|
||||
*e = M_NilEntry;
|
||||
e->valid = 1;
|
||||
e->kind = kind;
|
||||
if (entry_token) e->name_token = entry_token;
|
||||
for (u64 i = 0; i < MinU64(args_count, countof(e->arg_tokens)); ++i)
|
||||
{
|
||||
e->arg_tokens[i] = args[i];
|
||||
}
|
||||
e->args_count = args_count;
|
||||
QueuePush_NZ(&M_NilEntry, l->first, l->last, e, next);
|
||||
++l->count;
|
||||
return e;
|
||||
}
|
||||
|
||||
M_LayerList M_LayersFromTokenFiles(Arena *arena, M_TokenFileList lexed)
|
||||
{
|
||||
TempArena scratch = BeginScratch(arena);
|
||||
M_LayerList result = ZI;
|
||||
result.first = &M_NilLayer;
|
||||
result.last = &M_NilLayer;
|
||||
|
||||
/* Copy errors */
|
||||
b32 lexer_errors_present = 0;
|
||||
for (M_TokenFile *lf = lexed.first; lf->valid; lf = lf->next)
|
||||
{
|
||||
if (lf->errors.count > 0)
|
||||
{
|
||||
M_Layer *layer = M_PushLayer(arena, &result, lf);
|
||||
M_AppendErrors(arena, &layer->errors, lf->errors);
|
||||
lexer_errors_present = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lexer_errors_present)
|
||||
{
|
||||
Dict *rules_dict = InitDict(scratch.arena, 1024);
|
||||
for (u64 i = 0; i < countof(M_entry_kind_rules); ++i)
|
||||
{
|
||||
char *rule_cstr = M_entry_kind_rules[i];
|
||||
u64 rule_hash = HashFnv64(Fnv64Basis, StringFromCstrNoLimit(rule_cstr));
|
||||
SetDictValue(scratch.arena, rules_dict, rule_hash, i + 1);
|
||||
}
|
||||
|
||||
for (M_TokenFile *lf = lexed.first; lf->valid; lf = lf->next)
|
||||
{
|
||||
M_Layer *layer = M_PushLayer(arena, &result, lf);
|
||||
|
||||
M_Token *entry_token = &M_NilToken;
|
||||
M_Token *arg_tokens[countof(M_NilEntry.arg_tokens) + 1];
|
||||
u64 args_count = 0;
|
||||
for (u64 i = 0; i < countof(arg_tokens); ++i)
|
||||
{
|
||||
arg_tokens[i] = &M_NilToken;
|
||||
}
|
||||
|
||||
M_Token *token = lf->first_token;
|
||||
while (token->valid)
|
||||
{
|
||||
if (token->kind == M_TokenKind_Eol)
|
||||
{
|
||||
if (entry_token->valid)
|
||||
{
|
||||
M_Entry *entry = M_PushEntry(arena, layer, M_EntryKind_Unknown, entry_token, args_count, arg_tokens);
|
||||
{
|
||||
u64 entry_hash = HashFnv64(Fnv64Basis, entry_token->s);
|
||||
u64 kind_plus_1 = DictValueFromHash(rules_dict, entry_hash);
|
||||
if (kind_plus_1 > 0)
|
||||
{
|
||||
entry->kind = kind_plus_1 - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
token = token->next;
|
||||
entry_token = &M_NilToken;
|
||||
args_count = 0;
|
||||
for (u64 i = 0; i < countof(arg_tokens); ++i)
|
||||
{
|
||||
arg_tokens[i] = &M_NilToken;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Parse entry */
|
||||
entry_token = token;
|
||||
token = token->next;
|
||||
/* Parse args */
|
||||
while (token->kind != M_TokenKind_Eol)
|
||||
{
|
||||
if (args_count < countof(arg_tokens))
|
||||
{
|
||||
arg_tokens[args_count++] = token;
|
||||
}
|
||||
token = token->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndScratch(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Flatten operations
|
||||
|
||||
M_Layer M_GetFlattenedEntries(Arena *arena, M_LayerList unflattened, StringList starting_layer_names)
|
||||
{
|
||||
TempArena scratch = BeginScratch(arena);
|
||||
M_Layer result = M_NilLayer;
|
||||
|
||||
/* Copy errors */
|
||||
b32 unflattened_errors_present = 0;
|
||||
for (M_Layer *layer = unflattened.first; layer->valid; layer = layer->next)
|
||||
{
|
||||
if (layer->errors.count > 0)
|
||||
{
|
||||
M_AppendErrors(arena, &result.errors, layer->errors);
|
||||
unflattened_errors_present = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!unflattened_errors_present)
|
||||
{
|
||||
Enum(IterStateMode)
|
||||
{
|
||||
IterStateMode_None,
|
||||
IterStateMode_Entered,
|
||||
IterStateMode_Exited
|
||||
};
|
||||
Struct(IterState)
|
||||
{
|
||||
M_Layer *layer;
|
||||
b32 is_entered;
|
||||
b32 is_exited;
|
||||
} NilIterState = {
|
||||
.layer = &M_NilLayer
|
||||
};
|
||||
|
||||
/* Construct state lookups */
|
||||
Dict *layer_ptr_to_state = InitDict(scratch.arena, 1021);
|
||||
Dict *layer_name_to_state = InitDict(scratch.arena, 1021);
|
||||
for (M_Layer *layer = unflattened.first; layer->valid; layer = layer->next)
|
||||
{
|
||||
M_Entry *name_entry = &M_NilEntry;
|
||||
u64 num_name_entries = 0;
|
||||
for (M_Entry *entry = layer->first; entry->valid; entry = entry->next)
|
||||
{
|
||||
if (entry->kind == M_EntryKind_Layer)
|
||||
{
|
||||
if (num_name_entries == 0)
|
||||
{
|
||||
name_entry = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
String err = StringF(arena, "Layer already has name \"%F\"", FmtString(name_entry->arg_tokens[0]->s));
|
||||
M_PushError(arena, &result.errors, entry->name_token, err);
|
||||
}
|
||||
++num_name_entries;
|
||||
}
|
||||
}
|
||||
if (num_name_entries == 1 && name_entry->arg_tokens[0]->s.len > 0)
|
||||
{
|
||||
IterState *state = PushStruct(scratch.arena, IterState);
|
||||
state->layer = layer;
|
||||
|
||||
String name = name_entry->arg_tokens[0]->s;
|
||||
|
||||
u64 name_hash = HashFnv64(Fnv64Basis, name);
|
||||
DictEntry *ptr_dict_entry = EnsureDictEntry(scratch.arena, layer_ptr_to_state, (u64)layer);
|
||||
DictEntry *name_dict_entry = EnsureDictEntry(scratch.arena, layer_name_to_state, name_hash);
|
||||
|
||||
ptr_dict_entry->value = (u64)state;
|
||||
if (name_dict_entry->value == 0)
|
||||
{
|
||||
name_dict_entry->value = (u64)state;
|
||||
}
|
||||
else
|
||||
{
|
||||
String err = StringF(arena, "Layer with name \"%F\" already exists", FmtString(name));
|
||||
M_PushError(arena, &result.errors, name_entry->arg_tokens[0], err);
|
||||
}
|
||||
}
|
||||
else if (num_name_entries == 0)
|
||||
{
|
||||
M_PushError(arena, &result.errors, layer->file->first_token, Lit("Layer is missing a name"));
|
||||
}
|
||||
}
|
||||
|
||||
Struct(StackNode) { StackNode *next; IterState *state; b32 exit; };
|
||||
StackNode *stack = 0;
|
||||
|
||||
/* Init stack with starting layers */
|
||||
for (StringListNode *sln = starting_layer_names.first; sln; sln = sln->next)
|
||||
{
|
||||
String name = sln->s;
|
||||
u64 name_hash = HashFnv64(Fnv64Basis, name);
|
||||
IterState *state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, name_hash, (u64)&NilIterState);
|
||||
M_Layer *layer = state->layer;
|
||||
if (layer->valid)
|
||||
{
|
||||
StackNode *n = PushStruct(scratch.arena, StackNode);
|
||||
n->state = state;
|
||||
StackPush(stack, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
String err = StringF(arena, "Starting layer \"%F\" not found", FmtString(name));
|
||||
M_PushError(arena, &result.errors, 0, err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Flatten via post-order DFS */
|
||||
while (stack)
|
||||
{
|
||||
StackNode *stack_node = stack;
|
||||
IterState *state = stack->state;
|
||||
M_Layer *layer = state->layer;
|
||||
StackPop(stack);
|
||||
|
||||
if (stack_node->exit)
|
||||
{
|
||||
/* Push items to sorted root */
|
||||
state->is_entered = 0;
|
||||
state->is_exited = 1;
|
||||
for (M_Entry *entry = layer->first; entry->valid; entry = entry->next)
|
||||
{
|
||||
M_PushEntry(arena, &result, entry->kind, entry->name_token, entry->args_count, entry->arg_tokens);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state->is_entered)
|
||||
{
|
||||
/* Cyclic dependency */
|
||||
/* FIXME: Handle cyclic dependency error */
|
||||
Assert(0);
|
||||
}
|
||||
else if (!state->is_exited)
|
||||
{
|
||||
state->is_entered = 1;
|
||||
|
||||
/* Push downstream impl enters to stack */
|
||||
for (M_Entry *entry = layer->first; entry->valid; entry = entry->next)
|
||||
{
|
||||
b32 include = (PlatformIsWindows && entry->kind == M_EntryKind_DefaultWindowsImpl);
|
||||
if (include)
|
||||
{
|
||||
M_Token *impl_token = entry->arg_tokens[0];
|
||||
if (impl_token->valid)
|
||||
{
|
||||
String impl_name = impl_token->s;
|
||||
u64 hash = HashFnv64(Fnv64Basis, impl_name);
|
||||
IterState *impl_layer_state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, hash, (u64)&NilIterState);
|
||||
M_Layer *impl_layer = impl_layer_state->layer;
|
||||
if (impl_layer->valid)
|
||||
{
|
||||
if (!impl_layer_state->is_exited)
|
||||
{
|
||||
StackNode *n = PushStruct(scratch.arena, StackNode);
|
||||
n->state = impl_layer_state;
|
||||
StackPush(stack, n);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String err = StringF(arena, "Layer \"%F\" not found", FmtString(impl_name));
|
||||
M_PushError(arena, &result.errors, impl_token, err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
M_PushError(arena, &result.errors, entry->name_token, Lit("Expected layer argument"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Push node exit to stack */
|
||||
{
|
||||
stack_node->exit = 1;
|
||||
StackPush(stack, stack_node);
|
||||
}
|
||||
|
||||
/* Push upstream dep enters to stack */
|
||||
for (M_Entry *entry = layer->first; entry->valid; entry = entry->next)
|
||||
{
|
||||
if (entry->kind == M_EntryKind_Dep)
|
||||
{
|
||||
M_Token *dep_token = entry->arg_tokens[0];
|
||||
if (dep_token->valid)
|
||||
{
|
||||
String dep_name = dep_token->s;
|
||||
u64 hash = HashFnv64(Fnv64Basis, dep_name);
|
||||
IterState *dep_layer_state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, hash, (u64)&NilIterState);
|
||||
M_Layer *dep_layer = dep_layer_state->layer;
|
||||
if (dep_layer->valid)
|
||||
{
|
||||
if (!dep_layer_state->is_exited)
|
||||
{
|
||||
StackNode *n = PushStruct(scratch.arena, StackNode);
|
||||
n->state = dep_layer_state;
|
||||
StackPush(stack, n);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String err = StringF(arena, "Layer \"%F\" not found", FmtString(dep_name));
|
||||
M_PushError(arena, &result.errors, dep_token, err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
M_PushError(arena, &result.errors, entry->name_token, Lit("Expected layer argument"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndScratch(scratch);
|
||||
return result;
|
||||
}
|
||||
154
src/meta/meta_lay.h
Normal file
154
src/meta/meta_lay.h
Normal file
@ -0,0 +1,154 @@
|
||||
////////////////////////////////
|
||||
//~ Error types
|
||||
|
||||
Struct(M_Error)
|
||||
{
|
||||
M_Error *next;
|
||||
String msg;
|
||||
struct M_Token *token;
|
||||
};
|
||||
|
||||
Struct(M_ErrorList)
|
||||
{
|
||||
M_Error *first;
|
||||
M_Error *last;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ File types
|
||||
|
||||
Struct(M_File)
|
||||
{
|
||||
String name;
|
||||
String data;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Token types
|
||||
|
||||
Enum(M_TokenKind)
|
||||
{
|
||||
M_TokenKind_Ident,
|
||||
M_TokenKind_Eol, /* End of line */
|
||||
};
|
||||
|
||||
Struct(M_Token)
|
||||
{
|
||||
b32 valid;
|
||||
M_Token *next;
|
||||
|
||||
M_TokenKind kind;
|
||||
struct M_TokenFile *file;
|
||||
|
||||
String s;
|
||||
} extern Readonly M_NilToken;
|
||||
|
||||
Struct(M_TokenFile)
|
||||
{
|
||||
b32 valid;
|
||||
M_TokenFile *next;
|
||||
|
||||
String name;
|
||||
String data;
|
||||
|
||||
M_Token *first_token;
|
||||
M_Token *last_token;
|
||||
u64 tokens_count;
|
||||
|
||||
M_ErrorList errors;
|
||||
} extern Readonly M_NilTokenFile;
|
||||
|
||||
Struct(M_TokenFileList)
|
||||
{
|
||||
M_TokenFile *first;
|
||||
M_TokenFile *last;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Entry types
|
||||
|
||||
Enum(M_EntryKind)
|
||||
{
|
||||
M_EntryKind_Unknown,
|
||||
M_EntryKind_Layer,
|
||||
M_EntryKind_Dep,
|
||||
M_EntryKind_IncludeC,
|
||||
M_EntryKind_IncludeGpu,
|
||||
M_EntryKind_DefaultWindowsImpl,
|
||||
M_EntryKind_Startup,
|
||||
M_EntryKind_EmbedDir,
|
||||
};
|
||||
|
||||
Struct(M_EntryKindMatch)
|
||||
{
|
||||
char *match_cstr;
|
||||
u64 max_args;
|
||||
};
|
||||
|
||||
Global Readonly char *M_entry_kind_rules[] = {
|
||||
[M_EntryKind_Layer] = "@Layer",
|
||||
[M_EntryKind_Dep] = "@Dep",
|
||||
[M_EntryKind_IncludeC] = "@IncludeC",
|
||||
[M_EntryKind_IncludeGpu] = "@IncludeGpu",
|
||||
[M_EntryKind_DefaultWindowsImpl] = "@DefaultWindowsImpl",
|
||||
[M_EntryKind_Startup] = "@Startup",
|
||||
[M_EntryKind_EmbedDir] = "@EmbedDir",
|
||||
};
|
||||
|
||||
Struct(M_Entry)
|
||||
{
|
||||
b32 valid;
|
||||
M_Entry *next;
|
||||
|
||||
M_EntryKind kind;
|
||||
M_Token *name_token;
|
||||
|
||||
M_Token *arg_tokens[2];
|
||||
u64 args_count;
|
||||
} extern Readonly M_NilEntry;
|
||||
|
||||
Struct(M_Layer)
|
||||
{
|
||||
b32 valid;
|
||||
M_Layer *next;
|
||||
|
||||
M_TokenFile *file;
|
||||
|
||||
M_Entry *first;
|
||||
M_Entry *last;
|
||||
u64 count;
|
||||
M_ErrorList errors;
|
||||
} extern Readonly M_NilLayer;
|
||||
|
||||
Struct(M_LayerList)
|
||||
{
|
||||
M_Layer *first;
|
||||
M_Layer *last;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Error helpers
|
||||
|
||||
M_Error *M_PushError(Arena *arena, M_ErrorList *l, M_Token *token, String msg);
|
||||
void M_AppendErrors(Arena *arena, M_ErrorList *dst, M_ErrorList src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Lexer operations
|
||||
|
||||
M_Token *M_PushToken(Arena *arena, M_TokenFile *file, String s, M_TokenKind kind);
|
||||
M_TokenFileList M_TokensFromSrcDirs(Arena *arena, StringList src_dirs);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Parser operations
|
||||
|
||||
M_Layer *M_PushLayer(Arena *arena, M_LayerList *list, M_TokenFile *file);
|
||||
M_Entry *M_PushEntry(Arena *arena, M_Layer *l, M_EntryKind kind, M_Token *entry_token, u64 args_count, M_Token **args);
|
||||
M_LayerList M_LayersFromTokenFiles(Arena *arena, M_TokenFileList token_files);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Flatten operations
|
||||
|
||||
M_Layer M_GetFlattenedEntries(Arena *arena, M_LayerList unflattened, StringList starting_layer_names);
|
||||
@ -582,7 +582,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host)
|
||||
{
|
||||
//struct sock *sock = packet->sock;
|
||||
P_Address address = packet->address;
|
||||
BB_Buff bb = BitbuffFromString(packet->data);
|
||||
BB_Buff bb = BB_BuffFromString(packet->data);
|
||||
BB_Reader br = BB_ReaderFromBuff(&bb);
|
||||
u32 magic = BB_ReadUBits(&br, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
if (magic == N_PacketMagic)
|
||||
@ -874,7 +874,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BitbuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_TryConnect, 8);
|
||||
@ -887,7 +887,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BitbuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_ConnectSuccess, 8);
|
||||
@ -900,7 +900,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BitbuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_Disconnect, 8);
|
||||
@ -913,7 +913,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BitbuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_Heartbeat, 8);
|
||||
@ -951,7 +951,7 @@ void N_EndUpdate(N_Host *host)
|
||||
}
|
||||
}
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, is_reliable);
|
||||
BB_Buff bb = BitbuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_MsgChunk, 8);
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
//- Dependencies
|
||||
@Dep platform
|
||||
@Dep bitbuff
|
||||
|
||||
//- Api
|
||||
@IncludeC net.h
|
||||
|
||||
28
src/pp/pp.c
28
src/pp/pp.c
@ -1150,9 +1150,9 @@ void UpdateUser(P_Window *window)
|
||||
{
|
||||
Entity *ent = sorted[sorted_index];
|
||||
if (!IsValidAndActive(ent)) continue;
|
||||
//if (S_IsTagNil(ent->sprite)) continue;
|
||||
//if (S_IsNil(ent->sprite)) continue;
|
||||
|
||||
R_Tag sprite = ent->sprite;
|
||||
Resource sprite = ent->sprite;
|
||||
|
||||
Entity *parent = EntityFromId(g->ss_blended, ent->parent);
|
||||
|
||||
@ -1214,7 +1214,7 @@ void UpdateUser(P_Window *window)
|
||||
#endif
|
||||
|
||||
/* Draw sprite */
|
||||
if (!R_IsTagNil(sprite))
|
||||
if (!IsResourceNil(sprite))
|
||||
{
|
||||
S_Sheet *sheet = S_SheetFromResourceAsync(sprite);
|
||||
S_Texture *texture = S_TextureFromResourceAsync(sprite);
|
||||
@ -1244,7 +1244,7 @@ void UpdateUser(P_Window *window)
|
||||
if (HasProp(ent, Prop_TileChunk))
|
||||
{
|
||||
Vec2I32 chunk_index = ent->tile_chunk_index;
|
||||
R_Tag tile_sprite = R_TagFromStore(&GameResources, Lit("sprite/tile.ase"));
|
||||
Resource tile_sprite = ResourceFromStore(&GameResources, Lit("sprite/tile.ase"));
|
||||
S_Texture *tile_texture = S_TextureFromResourceAsync(tile_sprite);
|
||||
if (tile_texture->loaded)
|
||||
{
|
||||
@ -1323,7 +1323,7 @@ void UpdateUser(P_Window *window)
|
||||
|
||||
#if 0
|
||||
/* Draw slices */
|
||||
if (!S_IsTagNil(ent->sprite))
|
||||
if (!S_IsNil(ent->sprite))
|
||||
{
|
||||
S_Sheet *sheet = S_SheetFromResourceAsync(sprite);
|
||||
|
||||
@ -1754,7 +1754,7 @@ void UpdateUser(P_Window *window)
|
||||
{
|
||||
__profn("Draw crosshair");
|
||||
Vec2 crosshair_pos = g->ui_cursor;
|
||||
R_Tag crosshair = R_TagFromStore(GameResources, Lit("sprite/crosshair.ase"));
|
||||
Resource crosshair = ResourceFromStore(GameResources, Lit("sprite/crosshair.ase"));
|
||||
S_Texture *t = S_TextureFromResourceAsync(crosshair);
|
||||
Vec2 size = VEC2(t->width, t->height);
|
||||
Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size));
|
||||
@ -1773,7 +1773,7 @@ void UpdateUser(P_Window *window)
|
||||
}
|
||||
else
|
||||
{
|
||||
S_Texture *t = S_TextureFromResourceAsync(R_TagFromStore(GameResources, Lit("sprite/crosshair.ase")));
|
||||
S_Texture *t = S_TextureFromResourceAsync(ResourceFromStore(GameResources, Lit("sprite/crosshair.ase")));
|
||||
Vec2 size = VEC2(t->width, t->height);
|
||||
Rect cursor_clip = RectFromVec2(g->ui_screen_offset, g->ui_size);
|
||||
cursor_clip.pos = AddVec2(cursor_clip.pos, MulVec2(size, 0.5f));
|
||||
@ -2536,8 +2536,8 @@ JobDef(SimJob, UNUSED sig, UNUSED id)
|
||||
is_master = 1;
|
||||
}
|
||||
|
||||
BB_Buff msg_writer_bb = AcquireBitbuff(Gibi(64));
|
||||
BB_Buff snapshot_writer_bb = AcquireBitbuff(Gibi(64));
|
||||
BB_Buff msg_writer_bb = BB_AcquireBuff(Gibi(64));
|
||||
BB_Buff snapshot_writer_bb = BB_AcquireBuff(Gibi(64));
|
||||
SimAccel accel = AcquireSimAccel();
|
||||
|
||||
ClientStore *store = AcquireClientStore();
|
||||
@ -2646,7 +2646,7 @@ JobDef(SimJob, UNUSED sig, UNUSED id)
|
||||
{
|
||||
if (client->valid)
|
||||
{
|
||||
BB_Buff msg_bb = BitbuffFromString(event->msg);
|
||||
BB_Buff msg_bb = BB_BuffFromString(event->msg);
|
||||
BB_Reader msg_br = BB_ReaderFromBuff(&msg_bb);
|
||||
|
||||
u64 ack = BB_ReadUV(&msg_br);
|
||||
@ -2667,7 +2667,7 @@ JobDef(SimJob, UNUSED sig, UNUSED id)
|
||||
u8 *tmp_encoded_bytes = BB_ReadBytesRaw(&msg_br, tmp_encoded_len);
|
||||
if (!tmp_encoded_bytes) break;
|
||||
|
||||
BB_Buff decoder_bb = BitbuffFromString(STRING(tmp_encoded_len, tmp_encoded_bytes));
|
||||
BB_Buff decoder_bb = BB_BuffFromString(STRING(tmp_encoded_len, tmp_encoded_bytes));
|
||||
BB_Reader decoder_br = BB_ReaderFromBuff(&decoder_bb);
|
||||
u64 base_tick = BB_ReadUV(&decoder_br);
|
||||
u64 tick = BB_ReadUV(&decoder_br);
|
||||
@ -2762,7 +2762,7 @@ JobDef(SimJob, UNUSED sig, UNUSED id)
|
||||
Snapshot *base_ss = SnapshotFromTick(client, base_tick);
|
||||
if (base_ss->tick == base_tick)
|
||||
{
|
||||
BB_Buff bb = BitbuffFromString(n->tmp_encoded);
|
||||
BB_Buff bb = BB_BuffFromString(n->tmp_encoded);
|
||||
BB_Reader br = BB_ReaderFromBuff(&bb);
|
||||
|
||||
/* Acquire & decode snapshot */
|
||||
@ -3203,7 +3203,7 @@ JobDef(SimJob, UNUSED sig, UNUSED id)
|
||||
|
||||
ReleaseClientStore(store);
|
||||
ReleaseSimAccel(&accel);
|
||||
ReleaseBitbuff(&snapshot_writer_bb);
|
||||
ReleaseBitbuff(&msg_writer_bb);
|
||||
BB_ReleaseBuff(&snapshot_writer_bb);
|
||||
BB_ReleaseBuff(&msg_writer_bb);
|
||||
N_ReleaseHost(host);
|
||||
}
|
||||
|
||||
@ -273,7 +273,7 @@ extern SharedUserState shared_user_state;
|
||||
////////////////////////////////
|
||||
//~ Resources
|
||||
|
||||
R_DeclStore(GameResources);
|
||||
DeclResourceStore(GameResources);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
@Dep collider
|
||||
@Dep net
|
||||
@Dep mixer
|
||||
@Dep bitbuff
|
||||
@Dep rendertest
|
||||
@Dep playback
|
||||
|
||||
|
||||
@ -247,7 +247,7 @@ Struct(Entity)
|
||||
|
||||
//- Sprite
|
||||
|
||||
R_Tag sprite;
|
||||
Resource sprite;
|
||||
String sprite_span_name;
|
||||
u32 sprite_tint;
|
||||
Vec3 sprite_emittance;
|
||||
|
||||
@ -114,11 +114,11 @@ Inline b32 EqClientHandle(ClientHandle a, ClientHandle b)
|
||||
//~ Layer types
|
||||
|
||||
/* Absolute layers */
|
||||
#define Layer_FloorDecals (-300)
|
||||
#define Layer_Bullets (-200)
|
||||
#define Layer_Tracers (-100)
|
||||
#define Layer_Shoulders (0)
|
||||
#define Layer_Walls (100)
|
||||
#define Layer_FloorDecals (-300)
|
||||
#define Layer_Bullets (-200)
|
||||
#define Layer_Tracers (-100)
|
||||
#define Layer_Shoulders (0)
|
||||
#define Layer_Walls (100)
|
||||
|
||||
/* Relative layers */
|
||||
#define Layer_DefaultRelative (0)
|
||||
@ -129,21 +129,21 @@ Inline b32 EqClientHandle(ClientHandle a, ClientHandle b)
|
||||
|
||||
Enum(ControlFlag)
|
||||
{
|
||||
ControlFlag_Fire = 1 << 0,
|
||||
ControlFlag_AltFire = 1 << 1,
|
||||
ControlFlag_Fire = 1 << 0,
|
||||
ControlFlag_AltFire = 1 << 1,
|
||||
|
||||
/* Testing */
|
||||
ControlFlag_Drag = 1 << 2,
|
||||
ControlFlag_Delete = 1 << 3,
|
||||
ControlFlag_ClearAll = 1 << 4,
|
||||
ControlFlag_SpawnTest1 = 1 << 5,
|
||||
ControlFlag_SpawnTest2 = 1 << 6,
|
||||
ControlFlag_SpawnTest3 = 1 << 7,
|
||||
ControlFlag_SpawnTest4 = 1 << 8,
|
||||
ControlFlag_TestWalls = 1 << 9,
|
||||
ControlFlag_TestTiles = 1 << 10,
|
||||
ControlFlag_TestExplode = 1 << 11,
|
||||
ControlFlag_TestTeleport = 1 << 12,
|
||||
ControlFlag_Drag = 1 << 2,
|
||||
ControlFlag_Delete = 1 << 3,
|
||||
ControlFlag_ClearAll = 1 << 4,
|
||||
ControlFlag_SpawnTest1 = 1 << 5,
|
||||
ControlFlag_SpawnTest2 = 1 << 6,
|
||||
ControlFlag_SpawnTest3 = 1 << 7,
|
||||
ControlFlag_SpawnTest4 = 1 << 8,
|
||||
ControlFlag_TestWalls = 1 << 9,
|
||||
ControlFlag_TestTiles = 1 << 10,
|
||||
ControlFlag_TestExplode = 1 << 11,
|
||||
ControlFlag_TestTeleport = 1 << 12,
|
||||
};
|
||||
|
||||
Struct(ControlData)
|
||||
@ -179,7 +179,7 @@ StaticAssert(TileKind_Count < 256); /* Tile kind must fit in 8 bits */
|
||||
|
||||
Enum(SyncFlag)
|
||||
{
|
||||
SyncFlag_NoSyncPredictables = 1 << 0
|
||||
SyncFlag_NoSyncPredictables = 1 << 0
|
||||
};
|
||||
|
||||
Struct(Snapshot)
|
||||
|
||||
@ -36,7 +36,7 @@ void ResetSimAccel(Snapshot *ss, SimAccel *accel)
|
||||
Entity *SpawnTestSmg(Entity *parent)
|
||||
{
|
||||
Entity *e = AcquireSyncSrc(parent);
|
||||
e->sprite = R_TagFromStore(&GameResources, Lit("sprite/gun.ase"));
|
||||
e->sprite = ResourceFromStore(&GameResources, Lit("sprite/gun.ase"));
|
||||
|
||||
EnableProp(e, Prop_Attached);
|
||||
e->attach_slice = Lit("attach.wep");
|
||||
@ -52,7 +52,7 @@ Entity *SpawnTestSmg(Entity *parent)
|
||||
Entity *SpawnTestLauncher(Entity *parent)
|
||||
{
|
||||
Entity *e = AcquireSyncSrc(parent);
|
||||
e->sprite = R_TagFromStore(&GameResources, Lit("sprite/gun.ase"));
|
||||
e->sprite = ResourceFromStore(&GameResources, Lit("sprite/gun.ase"));
|
||||
|
||||
EnableProp(e, Prop_Attached);
|
||||
e->attach_slice = Lit("attach.wep");
|
||||
@ -68,7 +68,7 @@ Entity *SpawnTestLauncher(Entity *parent)
|
||||
Entity *SpawnTestChucker(Entity *parent)
|
||||
{
|
||||
Entity *chucker = AcquireSyncSrc(parent);
|
||||
chucker->sprite = R_TagFromStore(&GameResources, Lit("sprite/gun.ase"));
|
||||
chucker->sprite = ResourceFromStore(&GameResources, Lit("sprite/gun.ase"));
|
||||
|
||||
EnableProp(chucker, Prop_Attached);
|
||||
chucker->attach_slice = Lit("attach.wep");
|
||||
@ -119,12 +119,12 @@ Entity *SpawnTestEmployee(Entity *parent)
|
||||
|
||||
{
|
||||
EnableProp(e, Prop_Test);
|
||||
e->sprite = R_TagFromStore(&GameResources, Lit("sprite/tim.ase"));
|
||||
e->sprite = ResourceFromStore(&GameResources, Lit("sprite/tim.ase"));
|
||||
e->mass_unscaled = 10;
|
||||
e->inertia_unscaled = 5;
|
||||
}
|
||||
|
||||
//e->sprite = R_TagFromStore(GameResources, Lit("sprite/box_rounded.ase"));
|
||||
//e->sprite = ResourceFromStore(GameResources, Lit("sprite/box_rounded.ase"));
|
||||
//e->sprite_span_name = Lit("idle.unarmed");
|
||||
//e->sprite_span_name = Lit("idle.one_handed");
|
||||
e->sprite_span_name = Lit("idle.two_handed");
|
||||
@ -257,7 +257,7 @@ void SpawnTestEntities2(Entity *parent, Vec2 pos)
|
||||
Xform xf = XformFromTrs(TRS(.t = pos, .r = rot, .s = size));
|
||||
SetXform(e, xf);
|
||||
|
||||
e->sprite = R_TagFromStore(&GameResources, Lit("sprite/tile.ase"));
|
||||
e->sprite = ResourceFromStore(&GameResources, Lit("sprite/tile.ase"));
|
||||
e->layer = Layer_Shoulders;
|
||||
|
||||
//e->sprite_tint = Alpha32F(ColorBlue, 0.75);
|
||||
@ -299,7 +299,7 @@ void SpawnTestEntities2(Entity *parent, Vec2 pos)
|
||||
Xform xf = XformFromTrs(.t = pos, .r = r, .s = size);
|
||||
SetXform(e, xf);
|
||||
|
||||
e->sprite = R_TagFromStore(GameResources, Lit("sprite/bullet.ase"));
|
||||
e->sprite = ResourceFromStore(GameResources, Lit("sprite/bullet.ase"));
|
||||
e->sprite_collider_slice = Lit("shape");
|
||||
e->layer = Layer_Shoulders;
|
||||
|
||||
@ -327,7 +327,7 @@ void SpawnTestEntities3(Entity *parent, Vec2 pos)
|
||||
Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size));
|
||||
SetXform(e, xf);
|
||||
|
||||
e->sprite = R_TagFromStore(&GameResources, Lit("sprite/box.ase"));
|
||||
e->sprite = ResourceFromStore(&GameResources, Lit("sprite/box.ase"));
|
||||
e->layer = Layer_Shoulders;
|
||||
|
||||
e->sprite_tint = ColorRed;
|
||||
@ -350,8 +350,8 @@ void SpawnTestEntities4(Entity *parent, Vec2 pos)
|
||||
Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size));
|
||||
SetXform(e, xf);
|
||||
|
||||
//e->sprite = R_TagFromStore(GameResources, Lit("sprite/box.ase"));
|
||||
e->sprite = R_TagFromStore(&GameResources, Lit("sprite/tile.ase"));
|
||||
//e->sprite = ResourceFromStore(GameResources, Lit("sprite/box.ase"));
|
||||
e->sprite = ResourceFromStore(&GameResources, Lit("sprite/tile.ase"));
|
||||
e->layer = Layer_Shoulders;
|
||||
|
||||
EnableProp(e, Prop_LightTest);
|
||||
@ -380,10 +380,10 @@ void SpawnTestTile(Snapshot *world, Vec2 world_pos)
|
||||
SetXform(e, xf);
|
||||
|
||||
e->layer = Layer_Walls;
|
||||
e->sprite = R_TagFromStore(GameResources, Lit("sprite/tile.ase"));
|
||||
e->sprite = ResourceFromStore(GameResources, Lit("sprite/tile.ase"));
|
||||
e->sprite_tint = ColorRed;
|
||||
|
||||
S_Sheet *sheet = S_SheetFromResourceAwait(e->sprite);
|
||||
S_Sheet *sheet = S_SheetFromResource(e->sprite);
|
||||
e->sprite_local_xform = XformFromTrs(.s = DivVec2(sheet->frame_size, PIXELS_PER_UNIT));
|
||||
|
||||
EnableProp(e, Prop_Solid);
|
||||
@ -783,7 +783,7 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx)
|
||||
{
|
||||
Xform xf = XformFromTrs(TRS(.t = point, .r = RandF64FromState(&step_ctx->rand, 0, Tau)));
|
||||
Entity *decal = AcquireSyncSrc(root);
|
||||
decal->sprite = R_TagFromStore(&GameResources, Lit("sprite/blood.ase"));
|
||||
decal->sprite = ResourceFromStore(&GameResources, Lit("sprite/blood.ase"));
|
||||
decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f);
|
||||
decal->layer = Layer_FloorDecals;
|
||||
SetXform(decal, xf);
|
||||
@ -1249,9 +1249,9 @@ void StepSim(SimStepCtx *ctx)
|
||||
{
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!ShouldSimulate(ent)) continue;
|
||||
if (R_IsTagNil(ent->sprite)) continue;
|
||||
if (IsResourceNil(ent->sprite)) continue;
|
||||
|
||||
S_Sheet *sheet = S_SheetFromResourceAwait(ent->sprite);
|
||||
S_Sheet *sheet = S_SheetFromResource(ent->sprite);
|
||||
|
||||
/* Update animation */
|
||||
{
|
||||
@ -1359,8 +1359,8 @@ void StepSim(SimStepCtx *ctx)
|
||||
if (!HasProp(ent, Prop_Attached)) continue;
|
||||
|
||||
Entity *parent = EntityFromId(world, ent->parent);
|
||||
R_Tag parent_sprite = parent->sprite;
|
||||
S_Sheet *parent_sheet = S_SheetFromResourceAwait(parent_sprite);
|
||||
Resource parent_sprite = parent->sprite;
|
||||
S_Sheet *parent_sheet = S_SheetFromResource(parent_sprite);
|
||||
|
||||
Xform parent_sprite_xf = parent->sprite_local_xform;
|
||||
|
||||
@ -1450,9 +1450,9 @@ void StepSim(SimStepCtx *ctx)
|
||||
{
|
||||
if (primary_triggered)
|
||||
{
|
||||
R_Tag sprite = ent->sprite;
|
||||
Resource sprite = ent->sprite;
|
||||
u32 animation_frame = ent->animation_frame;
|
||||
S_Sheet *sheet = S_SheetFromResourceAwait(sprite);
|
||||
S_Sheet *sheet = S_SheetFromResource(sprite);
|
||||
Xform sprite_local_xform = ent->sprite_local_xform;
|
||||
S_Slice out_slice = S_SliceFromName(sheet, Lit("out"), animation_frame);
|
||||
Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center);
|
||||
@ -1477,7 +1477,7 @@ void StepSim(SimStepCtx *ctx)
|
||||
bullet->local_collider.points[0] = VEC2(0, 0);
|
||||
bullet->local_collider.count = 1;
|
||||
#else
|
||||
bullet->sprite = R_TagFromStore(GameResources, Lit("sprite/bullet.ase"));
|
||||
bullet->sprite = ResourceFromStore(GameResources, Lit("sprite/bullet.ase"));
|
||||
bullet->sprite_collider_slice = Lit("shape");
|
||||
#endif
|
||||
}
|
||||
@ -1499,9 +1499,9 @@ void StepSim(SimStepCtx *ctx)
|
||||
{
|
||||
if (primary_triggered)
|
||||
{
|
||||
R_Tag sprite = ent->sprite;
|
||||
Resource sprite = ent->sprite;
|
||||
u32 animation_frame = ent->animation_frame;
|
||||
S_Sheet *sheet = S_SheetFromResourceAwait(sprite);
|
||||
S_Sheet *sheet = S_SheetFromResource(sprite);
|
||||
Xform sprite_local_xform = ent->sprite_local_xform;
|
||||
S_Slice out_slice = S_SliceFromName(sheet, Lit("out"), animation_frame);
|
||||
Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center);
|
||||
@ -1673,7 +1673,7 @@ void StepSim(SimStepCtx *ctx)
|
||||
Vec2 sprite_hold_pos;
|
||||
Vec2 sprite_hold_dir;
|
||||
{
|
||||
S_Sheet *sheet = S_SheetFromResourceAwait(ent->sprite);
|
||||
S_Sheet *sheet = S_SheetFromResource(ent->sprite);
|
||||
S_Slice slice = S_SliceFromName(sheet, Lit("attach.wep"), ent->animation_frame);
|
||||
sprite_hold_pos = slice.center;
|
||||
sprite_hold_dir = slice.dir;
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
|
||||
////////////////////////////////
|
||||
//~ Tag helpers
|
||||
|
||||
b32 R_IsTagNil(R_Tag tag)
|
||||
{
|
||||
return tag.hash == 0;
|
||||
}
|
||||
|
||||
R_Tag R_TagFromStore(R_Store *store, String name)
|
||||
{
|
||||
R_Tag result = ZI;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource operations
|
||||
|
||||
String R_DataFromTag(R_Tag tag)
|
||||
{
|
||||
String result = ZI;
|
||||
return result;
|
||||
}
|
||||
|
||||
String R_NameFromTag(R_Tag tag)
|
||||
{
|
||||
String result = ZI;
|
||||
return result;
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
////////////////////////////////
|
||||
//~ Tag types
|
||||
|
||||
Struct(R_Tag)
|
||||
{
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Store types
|
||||
|
||||
#define R_DeclStore(name) extern R_Store name
|
||||
|
||||
Struct(R_Store)
|
||||
{
|
||||
i32 _;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Tag helpers
|
||||
|
||||
b32 R_IsTagNil(R_Tag tag);
|
||||
R_Tag R_TagFromStore(R_Store *store, String name);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource operations
|
||||
|
||||
String R_DataFromTag(R_Tag tag);
|
||||
String R_NameFromTag(R_Tag tag);
|
||||
@ -1,7 +0,0 @@
|
||||
@Layer res
|
||||
|
||||
//- Api
|
||||
@IncludeC res.h
|
||||
|
||||
//- Impl
|
||||
@IncludeC res.c
|
||||
@ -5,8 +5,8 @@ JobDef(SND_LoadJob, sig, UNUSED id)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
R_Tag resource = sig->resource;
|
||||
String name = R_NameFromTag(resource);
|
||||
Resource resource = sig->resource;
|
||||
String name = NameFromResource(resource);
|
||||
AC_Asset *asset = sig->asset;
|
||||
SND_SoundFlag flags = sig->flags;
|
||||
|
||||
@ -17,7 +17,7 @@ JobDef(SND_LoadJob, sig, UNUSED id)
|
||||
|
||||
/* Decode */
|
||||
MP3_Result decoded = ZI;
|
||||
String resource_data = R_DataFromTag(resource);
|
||||
String resource_data = DataFromResource(resource);
|
||||
if (resource_data.len > 0)
|
||||
{
|
||||
u64 decode_flags = 0;
|
||||
@ -80,13 +80,13 @@ JobDef(SND_LoadJob, sig, UNUSED id)
|
||||
////////////////////////////////
|
||||
//~ Load sound
|
||||
|
||||
AC_Asset *SND_LoadAsset(R_Tag resource, SND_SoundFlag flags, b32 wait)
|
||||
AC_Asset *SND_LoadAsset(Resource resource, SND_SoundFlag flags, b32 wait)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
|
||||
/* Generate and append sound flags to name key */
|
||||
String name = R_NameFromTag(resource);
|
||||
String name = NameFromResource(resource);
|
||||
String key = StringF(scratch.arena,
|
||||
"%F%F_sound",
|
||||
FmtString(name),
|
||||
@ -113,7 +113,7 @@ AC_Asset *SND_LoadAsset(R_Tag resource, SND_SoundFlag flags, b32 wait)
|
||||
return asset;
|
||||
}
|
||||
|
||||
SND_Sound *SND_LoadSoundAsync(R_Tag resource, SND_SoundFlag flags)
|
||||
SND_Sound *SND_LoadSoundAsync(Resource resource, SND_SoundFlag flags)
|
||||
{
|
||||
__prof;
|
||||
AC_Asset *asset = SND_LoadAsset(resource, flags, 0);
|
||||
@ -121,7 +121,7 @@ SND_Sound *SND_LoadSoundAsync(R_Tag resource, SND_SoundFlag flags)
|
||||
return sound;
|
||||
}
|
||||
|
||||
SND_Sound *SND_LoadSoundWait(R_Tag resource, SND_SoundFlag flags)
|
||||
SND_Sound *SND_LoadSoundWait(Resource resource, SND_SoundFlag flags)
|
||||
{
|
||||
__prof;
|
||||
AC_Asset *asset = SND_LoadAsset(resource, flags, 1);
|
||||
|
||||
@ -19,7 +19,7 @@ Struct(SND_Sound)
|
||||
////////////////////////////////
|
||||
//~ Sound load operations
|
||||
|
||||
JobDecl(SND_LoadJob, { SND_SoundFlag flags; AC_Asset *asset; R_Tag resource; });
|
||||
AC_Asset *SND_LoadAsset(R_Tag resource, SND_SoundFlag flags, b32 wait);
|
||||
SND_Sound *SND_LoadSoundAsync(R_Tag resource, SND_SoundFlag flags);
|
||||
SND_Sound *SND_LoadSoundWait(R_Tag resource, SND_SoundFlag flags);
|
||||
JobDecl(SND_LoadJob, { SND_SoundFlag flags; AC_Asset *asset; Resource resource; });
|
||||
AC_Asset *SND_LoadAsset(Resource resource, SND_SoundFlag flags, b32 wait);
|
||||
SND_Sound *SND_LoadSoundAsync(Resource resource, SND_SoundFlag flags);
|
||||
SND_Sound *SND_LoadSoundWait(Resource resource, SND_SoundFlag flags);
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
@Dep platform
|
||||
@Dep mp3
|
||||
@Dep asset_cache
|
||||
@Dep res
|
||||
|
||||
//- Api
|
||||
@IncludeC sound.h
|
||||
|
||||
@ -10,34 +10,132 @@ void S_Startup(void)
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Texture operations
|
||||
//~ Load texture job
|
||||
|
||||
S_Texture *S_TextureFromResourceAwait(R_Tag resource)
|
||||
JobDef(S_LoadTextureJob, sig, _)
|
||||
{
|
||||
S_Entry *entry = sig->entry;
|
||||
AddCounter(&entry->texture_load_counter, -1);
|
||||
}
|
||||
|
||||
JobDef(S_LoadSheetJob, sig, _)
|
||||
{
|
||||
S_Entry *entry = sig->entry;
|
||||
AddCounter(&entry->sheet_load_counter, -1);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Cache
|
||||
|
||||
S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags)
|
||||
{
|
||||
S_SharedState *g = &S_shared_state;
|
||||
S_Entry *entry = 0;
|
||||
{
|
||||
S_EntryBin *bin = &g->entry_bins[resource.hash % S_EntryBinsCount];
|
||||
/* Search for entry */
|
||||
entry = bin->first;
|
||||
{
|
||||
Lock lock = LockS(&bin->mutex);
|
||||
{
|
||||
for (; entry; entry = entry->next_in_bin)
|
||||
{
|
||||
if (entry->resource.hash == resource.hash)
|
||||
{
|
||||
entry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Unlock(&lock);
|
||||
}
|
||||
/* Entry not found, re-check & create */
|
||||
if (!entry)
|
||||
{
|
||||
Lock lock = LockE(&bin->mutex);
|
||||
{
|
||||
/* Re-check */
|
||||
entry = bin->first;
|
||||
for (; entry; entry = entry->next_in_bin)
|
||||
{
|
||||
if (entry->resource.hash == resource.hash)
|
||||
{
|
||||
entry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Create */
|
||||
if (!entry)
|
||||
{
|
||||
entry = PushStruct(PermArena, S_Entry);
|
||||
entry->resource = resource;
|
||||
entry->texture = &S_NilTexture;
|
||||
entry->sheet = &S_NilSheet;
|
||||
AddCounter(&entry->texture_load_counter, 1);
|
||||
AddCounter(&entry->sheet_load_counter, 1);
|
||||
QueuePush_N(bin->first, bin->last, entry, next_in_bin);
|
||||
}
|
||||
}
|
||||
Unlock(&lock);
|
||||
}
|
||||
}
|
||||
/* Launch load jobs */
|
||||
if ((flags & S_FetchFlag_Texture)
|
||||
&& !Atomic32Fetch(&entry->texture_touched)
|
||||
&& !Atomic32FetchTestSet(&entry->texture_touched, 0, 1))
|
||||
{
|
||||
RunJob(1, S_LoadTextureJob, pool, JobPriority_Inherit, 0, .entry = entry);
|
||||
}
|
||||
if ((flags & S_FetchFlag_Sheet)
|
||||
&& !Atomic32Fetch(&entry->sheet_touched)
|
||||
&& !Atomic32FetchTestSet(&entry->sheet_touched, 0, 1))
|
||||
{
|
||||
RunJob(1, S_LoadSheetJob, pool, JobPriority_Inherit, 0, .entry = entry);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sprite data retrieval operations
|
||||
|
||||
S_Texture *S_TextureFromResource(Resource resource)
|
||||
{
|
||||
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Texture);
|
||||
YieldOnCounter(&entry->texture_load_counter);
|
||||
return entry->texture;
|
||||
}
|
||||
|
||||
S_Texture *S_TextureFromResourceAsync(Resource resource)
|
||||
{
|
||||
S_Texture *result = &S_NilTexture;
|
||||
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Texture);
|
||||
if (ValueFromCounter(&entry->texture_load_counter) <= 0)
|
||||
{
|
||||
result = entry->texture;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
S_Texture *S_TextureFromResourceAsync(R_Tag resource)
|
||||
S_Sheet *S_SheetFromResource(Resource resource)
|
||||
{
|
||||
S_Texture *result = &S_NilTexture;
|
||||
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Sheet);
|
||||
YieldOnCounter(&entry->sheet_load_counter);
|
||||
return entry->sheet;
|
||||
}
|
||||
|
||||
S_Sheet *S_SheetFromResourceAsync(Resource resource)
|
||||
{
|
||||
S_Sheet *result = &S_NilSheet;
|
||||
S_Entry *entry = S_FetchEntry(resource, JobPool_Inherit, S_FetchFlag_Sheet);
|
||||
if (ValueFromCounter(&entry->sheet_load_counter) <= 0)
|
||||
{
|
||||
result = entry->sheet;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sheet operations
|
||||
|
||||
S_Sheet *S_SheetFromResourceAwait(R_Tag resource)
|
||||
{
|
||||
S_Sheet *result = &S_NilSheet;
|
||||
return result;
|
||||
}
|
||||
|
||||
S_Sheet *S_SheetFromResourceAsync(R_Tag resource)
|
||||
{
|
||||
S_Sheet *result = &S_NilSheet;
|
||||
return result;
|
||||
}
|
||||
//~ Sheet access operations
|
||||
|
||||
S_Span S_SpanFromName(S_Sheet *sheet, String name)
|
||||
{
|
||||
|
||||
@ -1,3 +1,28 @@
|
||||
////////////////////////////////
|
||||
//~ Cache types
|
||||
|
||||
Struct(S_Entry)
|
||||
{
|
||||
S_Entry *next_in_bin;
|
||||
|
||||
struct S_Texture *texture;
|
||||
struct S_Sheet *sheet;
|
||||
|
||||
Atomic32 texture_touched;
|
||||
Atomic32 sheet_touched;
|
||||
|
||||
Resource resource;
|
||||
Counter texture_load_counter;
|
||||
Counter sheet_load_counter;
|
||||
};
|
||||
|
||||
Struct(S_EntryBin)
|
||||
{
|
||||
S_Entry *first;
|
||||
S_Entry *last;
|
||||
Mutex mutex;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Texture types
|
||||
|
||||
@ -88,9 +113,11 @@ extern Readonly S_Sheet S_NilSheet;
|
||||
////////////////////////////////
|
||||
//~ Shared state
|
||||
|
||||
#define S_EntryBinsCount 1024
|
||||
|
||||
Struct(S_SharedState)
|
||||
{
|
||||
i32 _;
|
||||
S_EntryBin entry_bins[S_EntryBinsCount];
|
||||
};
|
||||
|
||||
extern S_SharedState S_shared_state;
|
||||
@ -101,16 +128,34 @@ extern S_SharedState S_shared_state;
|
||||
void S_Startup(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Texture operations
|
||||
//~ Load jobs
|
||||
|
||||
S_Texture *S_TextureFromResource(R_Tag resource);
|
||||
S_Texture *S_TextureFromResourceAsync(R_Tag resource);
|
||||
JobDecl(S_LoadTextureJob, { S_Entry *entry; });
|
||||
JobDecl(S_LoadSheetJob, { S_Entry *entry; });
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sheet operations
|
||||
//~ Cache operations
|
||||
|
||||
S_Sheet *S_SheetFromResourceAwait(R_Tag resource);
|
||||
S_Sheet *S_SheetFromResourceAsync(R_Tag resource);
|
||||
Enum(S_FetchFlag)
|
||||
{
|
||||
S_FetchFlag_None = 0,
|
||||
S_FetchFlag_Texture = (1 << 0),
|
||||
S_FetchFlag_Sheet = (1 << 1),
|
||||
};
|
||||
|
||||
S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sprite data retrieval operations
|
||||
|
||||
S_Texture *S_TextureFromResource(Resource resource);
|
||||
S_Texture *S_TextureFromResourceAsync(Resource resource);
|
||||
|
||||
S_Sheet *S_SheetFromResource(Resource resource);
|
||||
S_Sheet *S_SheetFromResourceAsync(Resource resource);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sheet access operations
|
||||
|
||||
S_Span S_SpanFromName(S_Sheet *sheet, String name);
|
||||
S_Frame S_FrameFromIndex(S_Sheet *sheet, u64 index);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user