//////////////////////////////////////////////////////////// //~ Compiler flag checks #ifndef IsConsoleApp # error Missing compile time definition for 'IsConsoleApp' #endif #ifndef RtcIsEnabled # error Missing compile time definition for 'RtcIsEnabled' #endif #ifndef AsanIsEnabled # error Missing compile time definition for 'AsanIsEnabled' #endif #ifndef CrtlibIsEnabled # error Missing compile time definition for 'CrtlibIsEnabled' #endif #ifndef DebinfoEnabled # error Missing compile time definition for 'DebinfoEnabled' #endif #ifndef DeveloperIsEnabled # error Missing compile time definition for 'DeveloperIsEnabled' #endif #ifndef ProfilingIsEnabled # error Missing compile time definition for 'ProfilingIsEnabled' #endif #ifndef UnoptimizedIsEnabled # error Missing compile time definition for 'UnoptimizedIsEnabled' #endif #ifndef TestsAreEnabled # error Missing compile time definition for 'TestsAreEnabled' #endif #ifndef HotSwappingIsEnabled # error Missing compile time definition for 'HotSwappingIsEnabled' #endif //////////////////////////////////////////////////////////// //~ Machine context //- Compiler #if defined(__clang__) # define CompilerIsClang 1 # define CompilerIsMsvc 0 #elif defined(_MSC_VER) # define CompilerIsClang 0 # define CompilerIsMsvc 1 #else # error Unknown compiler #endif //- Language #if defined(__HLSL_VERSION) # define LanguageIsC 0 # define LanguageIsGpu 1 #else # define LanguageIsC 1 # define LanguageIsGpu 0 #endif //- Platform system #if defined(_WIN32) # define PlatformIsWindows 1 # define PlatformIsMac 0 # define PlatformIsLinux 0 #elif defined(__APPLE__) && defined(__MACH__) # define PlatformIsWindows 0 # define PlatformIsMac 1 # define PlatformIsLinux 0 #elif defined(__gnu_linux__) # define PlatformIsWindows 0 # define PlatformIsMac 0 # define PlatformIsLinux 1 #elif LanguageIsGpu # define PlatformIsWindows 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 # elif LanguageIsGpu # define ArchIsX64 0 # define ArchIsArm64 0 # else # error Unknown architecture # endif //- Cache line size /* TODO: Just hard-code to something like 128 or 256 if Apple silicon is ever supported */ #define CachelineSize 64 //- Windows NTDDI version /* TODO: Remove this */ #if 0 #if CompilerIsMsvc # define NTDDI_WIN11_DT 0x0C0A0000 # define NTDDI_VERSION 0x0A000000 # if RtcIsEnabled # define _ALLOW_RTCc_IN_STL 1 # endif #endif #endif //////////////////////////////////////////////////////////// //~ Platform headers //- Windows headers #if PlatformIsWindows # define COBJMACROS # define WIN32_LEAN_AND_MEAN # define UNICODE # pragma warning(push, 0) # include # include # include # include # include # include # include # include # pragma warning(pop) #endif //////////////////////////////////////////////////////////// //~ Debug //- Static assert #define StaticAssert2(cond, line, counter) struct STATIC_ASSERT_____##line##counter {int foo[(cond) ? 1 : -1];} #define StaticAssert1(cond, line, counter) StaticAssert2(cond, line, counter) #define StaticAssert(cond) StaticAssert1(cond, __LINE__, __COUNTER__) //- Debug assert #if RtcIsEnabled # if CompilerIsMsvc # 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)) # define DEBUGBREAK __builtin_debugtrap() # endif # define DEBUGBREAKABLE { volatile i32 __DEBUGBREAKABLE_VAR = 0; LAX __DEBUGBREAKABLE_VAR; } (void)0 #else # define Assert(cond) (void)(0) #endif //- Root constant assert #define AssertRootConst(s, n) StaticAssert((sizeof(s) % 16 == 0) && /* Root constant struct should pad to 16 byte alignment */ \ ((sizeof(s) / 4) == (n)) && /* Root constant struct size should match the specified 32-bit-constant count */ \ (sizeof(s) <= 256)) /* Root constant struct can only fit 64 DWORDS */ //- Debug alias /* TODO: Remove this */ #if CompilerIsMsvc # if DebinfoEnabled # define DebugAlias(var, alias) *(alias) = &(var) # else # define DebugAlias(var, alias) *(alias) = &(var) # endif #else # if DebinfoEnabled # define DebugAlias(var, alias) __attribute((used)) *(alias) = &(var) # else # define DebugAlias(var, alias) __attribute((unused)) *(alias) = &(var) # endif #endif //- Address sanitization #if AsanIsEnabled void __asan_poison_memory_region(void const volatile *, size_t); void __asan_unpoison_memory_region(void const volatile *add, size_t); # define AsanPoison(addr, size) __asan_poison_memory_region((addr), (size)) # define AsanUnpoison(addr, size) __asan_unpoison_memory_region((addr), (size)) #else # define AsanPoison(addr, size) # define AsanUnpoison(addr, size) #endif //////////////////////////////////////////////////////////// //~ Common utility macros //- ZeroStruct initialization macro #if LanguageIsC # define ZI { 0 } #else # define ZI { } #endif //- Inline #define Inline static inline #if CompilerIsMsvc # define ForceInline Inline __forceinline #else # define ForceInline Inline __attribute((always_inline)) #endif #if CompilerIsMsvc # define ForceNoInline __declspec(noinline) #else # define ForceNoInline __attribute__((noinline)) #endif //- Static #define PERSIST static #define Global static //- Read-only #if PlatformIsWindows # if CompilerIsMsvc # pragma section(".rdata$", read) # define Readonly __declspec(allocate(".rdata$")) # else # define Readonly __declspec(allocate(".rdata")) # endif #elif PlatformIsMac # define Readonly __attribute((section("__TEXT,__const"))) #else # define Readonly __attribute((section(".rodata"))) #endif //- Barriers #if CompilerIsMsvc # define WriteBarrier() _WriteBarrier() # define ReadBarrier() _ReadBarrier() #elif defined(__x86_64) || defined(__i386__) # define WriteBarrier() __asm__ volatile("" ::: "memory") # define ReadBarrier() __asm__ volatile("" ::: "memory") #elif LanguageIsGpu # define WriteBarrier() # define ReadBarrier() #else # error Memory barriers not implemented #endif //- Unused markup /* Strict unused markup */ #if CompilerIsClang # define UNUSED __attribute((unused)) #else # define UNUSED #endif /* Relaxed unused markup */ #define LAX (void) //- Fallthrough #if CompilerIsClang # define FALLTHROUGH __attribute((fallthrough)) #else # define FALLTHROUGH #endif //- Preprocessor concatenation #define Cat1(a, b) a ## b #define Cat(a, b) Cat1(a, b) //- Preprocessor stringization #define Stringize1(x) #x #define Stringize(x) Stringize1(x) //- Sizes #define Kibi(n) (n*1024ULL) #define Mebi(n) (n*Kibi(1024ULL)) #define Gibi(n) (n*Mebi(1024ULL)) #define Tebi(n) (n*Gibi(1024ULL)) //- Time #define NsFromSeconds(s) ((i64)((s) * 1000000000.0)) #define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0) //////////////////////////////////////////////////////////// //~ Linked list helper macros /* Taken from the rad debugger * https://github.com/EpicGamesExt/raddebugger/blob/be5634c44867a2e31f6a109df5e574930992df01/src/base/base_core.h#L239 */ #define CheckNil(nil,p) ((p) == 0 || (p) == nil) #define SetNil(nil,p) ((p) = nil) //- Singly linked list stack (first & next pointers) #define StackPushN(f,n,next) ((n)->next=(f), (f)=(n)) #define StackPopN(f,next) ((f)=(f)->next) #define StackPush(f,n) StackPushN(f,n,next) #define StackPop(f) StackPopN(f,next) //- Singly linked list queue (first, last, & next pointers) #define QueuePushNZ(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 QueuePushFrontNZ(nil,f,l,n,next) (CheckNil(nil,f) ? \ ((f)=(l)=(n),SetNil(nil,(n)->next)) : \ ((n)->next=(f),(f)=(n))) #define QueuePopNZ(nil,f,l,next) ((f)==(l) ? \ (SetNil(nil,f),SetNil(nil,l)) : \ ((f)=(f)->next)) #define QueuePushN(f,l,n,next) QueuePushNZ(0,f,l,n,next) #define QueuePushFrontN(f,l,n,next) QueuePushFrontNZ(0,f,l,n,next) #define QueuePopN(f,l,next) QueuePopNZ(0,f,l,next) #define QueuePush(f,l,n) QueuePushNZ(0,f,l,n,next) #define QueuePushFront(f,l,n) QueuePushFrontNZ(0,f,l,n,next) #define QueuePop(f,l) QueuePopNZ(0,f,l,next) //- Doubly linked list (first, last, next, & prev pointers) #define DllInsertNPZ(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 DllRemoveNPZ(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 DllPushBackNPZ(nil,f,l,n,next,prev) DllInsertNPZ(nil,f,l,l,n,next,prev) #define DllPushFrontNPZ(nil,f,l,n,next,prev) DllInsertNPZ(nil,l,f,f,n,prev,next) #define DllInsertNP(f,l,p,n,next,prev) DllInsertNPZ(0,f,l,p,n,next,prev) #define DllPushBackNP(f,l,n,next,prev) DllPushBackNPZ(0,f,l,n,next,prev) #define DllPushFrontNP(f,l,n,next,prev) DllPushFrontNPZ(0,f,l,n,next,prev) #define DllRemoveNP(f,l,n,next,prev) DllRemoveNPZ(0,f,l,n,next,prev) #define DllInsert(f,l,p,n) DllInsertNPZ(0,f,l,p,n,next,prev) #define DllPushBack(f,l,n) DllPushBackNPZ(0,f,l,n,next,prev) #define DllPushFront(f,l,n) DllPushFrontNPZ(0,f,l,n,next,prev) #define DllRemove(f,l,n) DllRemoveNPZ(0,f,l,n,next,prev) //////////////////////////////////////////////////////////// //~ Color helper macros //- Rgba 32 bit helpers #define Rgb32(r, g, b) Rgba32((r), (g), (b), 0xFF) #define Rgba32(r, g, b, a) (u32)((u32)(r) | ((u32)(g) << 8) | ((u32)(b) << 16) | ((u32)(a) << 24)) #define Bgr32(rgb) ((((rgb >> 0) & 0xFF) << 16) | (((rgb >> 8) & 0xFF) << 8) | (((rgb >> 16) & 0xFF) << 0)) //- Rgba 32 bit float float helpers #define _Rgb32U8FromF(fl) ((u8)((fl * 255.0) + 0.5)) #define Rgba32F(r, g, b, a) Rgba32(_Rgb32U8FromF((r)), _Rgb32U8FromF((g)), _Rgb32U8FromF((b)), _Rgb32U8FromF((a))) #define Rgb32F(r, g, b) Rgba32F((r), (g), (b), 1.f) #define Alpha32F(color, a) ((color) & 0x00FFFFFF) | (_Rgb32U8FromF((a)) << 24) //- Pre-defined colors #define Color_White Rgb32(0xFF, 0xFF, 0xFF) #define Color_Black Rgb32(0x00, 0x00, 0x00) #define Color_Red Rgb32(0xFF, 0x00, 0x00) #define Color_Green Rgb32(0x00, 0xFF, 0x00) #define Color_Blue Rgb32(0x00, 0x00, 0xFF) #define Color_Yellow Rgb32(0xFF, 0xFF, 0x00) #define Color_Orange Rgb32(0xFF, 0xA5, 0x00) #define Color_Purple Rgb32(0xFF, 0x00, 0XFF) //////////////////////////////////////////////////////////// //~ Intrinsic headers #if LanguageIsC /* Intrinsic header info: * mmintrin.h MMX * xmmintrin.h SSE * emmintrin.h SSE2 * pmmintrin.h SSE3 * tmmintrin.h SSSE3 * smmintrin.h SSE4.1 * nmmintrin.h SSE4.2 * ammintrin.h SSE4A * wmmintrin.h AES * immintrin.h AVX, AVX2, FMA */ #include #include /* SSE4.2 */ #endif //////////////////////////////////////////////////////////// //~ Type helper macros //- Struct #define Struct(name) typedef struct name name; struct name #define AlignedStruct(name, n) typedef struct name name; struct alignas(n) name #define AlignedBlock(n) struct alignas(n) //- Enum #if LanguageIsC # define Enum(name) typedef enum name name; enum name #else # define Enum(name) enum name #endif //- alignof #if LanguageIsC && (CompilerIsMsvc || __STDC_VERSION__ < 202311L) # define alignof(type) __alignof(type) #endif //- field sizeof #define sizeof_field(type, field) sizeof(((type *)0)->field) //- countof #define countof(a) (sizeof(a) / sizeof((a)[0])) //- IsArray #define IsIndexable(a) (sizeof(a[0]) != 0) #define IsArray(a) (IsIndexable(a) && (((void *)&a) == ((void *)a))) //- offsetof #if !CompilerIsMsvc # ifdef _CRT_USE_BUILTIN_OFFSETOF # define offsetof(type, field) __builtin_offsetof(type, field) # else # define offsetof(type, field) ((u64)&(((type *)0)->field)) # endif #endif //- struct region #define StructRegion(name) i8 name #define CopyStructRegion(dst, src, r0, r1) CopyBytes(&dst->r0, &src->r0, (u8 *)&dst->r1 - (u8 *)&dst->r0) //- Packed #if CompilerIsMsvc # define Packed(s) __pragma(pack(push, 1)) s __pragma(pack(pop)) #elif CompilerIsClang # define Packed(s) s __attribute((__packed__)) #elif LanguageIsGpu # define Packed(s) s #endif //- alignas #if (CompilerIsMsvc && LanguageIsC) || (LanguageIsC && __STDC_VERSION__ < 202311L) # if CompilerIsMsvc # define alignas(n) __declspec(align(n)) # else # define alignas(n) __attribute__((aligned(n))) # endif #endif //////////////////////////////////////////////////////////// //~ Scalar types #if LanguageIsC //- Cpu scalar types #include typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; typedef float f32; typedef double f64; typedef i8 b8; typedef u32 b32; #elif LanguageIsGpu //- Gpu scalar types typedef int i32; typedef uint u32; typedef float f32; typedef uint b32; #endif //- Min / max constants #define U8Max (0xFF) #define U16Max (0xFFFF) #define U32Max (0xFFFFFFFF) #define U64Max (0xFFFFFFFFFFFFFFFFULL) #define I8Max (0x7F) #define I16Max (0x7FFF) #define I32Max (0x7FFFFFFF) #define I64Max (0x7FFFFFFFFFFFFFFFLL) #define I8Min ((i8)-0x80) #define I16Min ((i16)0x8000) #define I32Min ((i32)0x80000000) #define I64Min ((i64)0x8000000000000000LL) //- Float infinity / nan constants #if LanguageIsC Global const u32 _f32_infinity_u32 = 0x7f800000; Global const f32 *_f32_infinity = (f32 *)&_f32_infinity_u32; #define F32Infinity (*_f32_infinity) Global const u64 _f64_infinity_u64 = 0x7ff0000000000000ULL; Global const f64 *_f64_infinity = (f64 *)&_f64_infinity_u64; #define F64Infinity (*_f64_infinity) Global const u32 _f32_nan_u32 = 0x7f800001; Global const f32 *_f32_nan = (f32 *)&_f32_nan_u32; #define F32Nan (*_f32_nan) Global const u64 _f64_nan_u64 = 0x7ff8000000000001; Global const f64 *_f64_nan = (f64 *)&_f64_nan_u64; #define F64Nan (*_f64_nan) #define IsF32Nan(x) (x != x) #define IsF64Nan(x) (x != x) #endif //////////////////////////////////////////////////////////// //~ Atomics #if LanguageIsC //- Atomic types Struct(Atomic8) { volatile i8 _v; }; Struct(Atomic16) { volatile i16 _v; }; Struct(Atomic32) { volatile i32 _v; }; Struct(Atomic64) { volatile i64 _v; }; //- Cache-line isolated aligned atomic types AlignedStruct(Atomic8Padded, CachelineSize) { Atomic8 v; }; AlignedStruct(Atomic16Padded, CachelineSize) { Atomic16 v; }; AlignedStruct(Atomic32Padded, CachelineSize) { Atomic32 v; }; AlignedStruct(Atomic64Padded, CachelineSize) { Atomic64 v; }; StaticAssert(alignof(Atomic8Padded) == CachelineSize && sizeof(Atomic8Padded) % CachelineSize == 0); StaticAssert(alignof(Atomic16Padded) == CachelineSize && sizeof(Atomic16Padded) % CachelineSize == 0); StaticAssert(alignof(Atomic32Padded) == CachelineSize && sizeof(Atomic32Padded) % CachelineSize == 0); StaticAssert(alignof(Atomic64Padded) == CachelineSize && sizeof(Atomic64Padded) % CachelineSize == 0); #if PlatformIsWindows && ArchIsX64 //- Memory barriers # define CompilerMemoryBarrier() _ReadWriteBarrier() # define HardwareMemoryBarrier() MemoryBarrier() //- 8 bit atomic operations ForceInline i8 Atomic8Fetch (Atomic8 *x) { i8 result = (x)->_v; CompilerMemoryBarrier(); return result; } ForceInline void Atomic8Set (Atomic8 *x, i8 e) { CompilerMemoryBarrier(); (x)->_v = e; } ForceInline i8 Atomic8FetchSet (Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((volatile char *)&(x)->_v, (e)); } ForceInline i8 Atomic8FetchTestSet (Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((volatile char *)&(x)->_v, (e), (c)); } ForceInline i8 Atomic8FetchXor (Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((volatile char *)&(x)->_v, (c)); } ForceInline i8 Atomic8FetchAdd (Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((volatile char *)&(x)->_v, (a)); } //- 16 bit atomic operations ForceInline i16 Atomic16Fetch (Atomic16 *x) { i16 result = (x)->_v; CompilerMemoryBarrier(); return result; } ForceInline void Atomic16Set (Atomic16 *x, i16 e) { CompilerMemoryBarrier(); (x)->_v = e; } ForceInline i16 Atomic16FetchSet (Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&(x)->_v, (e)); } ForceInline i16 Atomic16FetchTestSet (Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&(x)->_v, (e), (c)); } ForceInline i16 Atomic16FetchXor (Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&(x)->_v, (c)); } ForceInline i16 Atomic16FetchAdd (Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&(x)->_v, (a)); } //- 32 bit atomic operations ForceInline i32 Atomic32Fetch (Atomic32 *x) { i32 result = (x)->_v; CompilerMemoryBarrier(); return result; } ForceInline void Atomic32Set (Atomic32 *x, i32 e) { CompilerMemoryBarrier(); (x)->_v = e; } ForceInline i32 Atomic32FetchSet (Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&(x)->_v, (e)); } ForceInline i32 Atomic32FetchTestSet (Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&(x)->_v, (e), (c)); } ForceInline i32 Atomic32FetchXor (Atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&(x)->_v, (c)); } ForceInline i32 Atomic32FetchAdd (Atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&(x)->_v, (a)); } //- 64 bit atomic operations ForceInline i64 Atomic64Fetch (Atomic64 *x) { i64 result = (x)->_v; CompilerMemoryBarrier(); return result; } ForceInline void Atomic64Set (Atomic64 *x, i64 e) { CompilerMemoryBarrier(); (x)->_v = e; } ForceInline i64 Atomic64FetchSet (Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&(x)->_v, (e)); } ForceInline i64 Atomic64FetchTestSet (Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&(x)->_v, (e), (c)); } ForceInline i64 Atomic64FetchXor (Atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&(x)->_v, (c)); } ForceInline i64 Atomic64FetchAdd (Atomic64 *x, i64 a) { return (i64)_InterlockedExchangeAdd64(&(x)->_v, (a)); } #else # error Atomics not implemented #endif #endif //////////////////////////////////////////////////////////// //~ Ticket mutex #if LanguageIsC Struct(TicketMutex) { Atomic64Padded ticket; Atomic64Padded serving; }; ForceInline void LockTicketMutex(TicketMutex *tm) { i64 ticket = Atomic64FetchAdd(&tm->ticket.v, 1); while (Atomic64Fetch(&tm->serving.v) != ticket) { _mm_pause(); } } ForceInline void UnlockTicketMutex(TicketMutex *tm) { /* TODO: Atomic set w/ known ticket + 1 */ Atomic64FetchAdd(&tm->serving.v, 1); } #endif //////////////////////////////////////////////////////////// //~ String types #if LanguageIsC #define STRING(size, data) ((String) { (size), (data) }) #define Lit(cstr_lit) (String) { (sizeof((cstr_lit)) - 1), (u8 *)(cstr_lit) } #define LitNoCast(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) } #define StringFromPointers(p0, p1) ((String) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 }) #define StringFromStruct(ptr) ((String) { sizeof(*(ptr)), (u8 *)(ptr) }) #define StringFromArena(arena) (STRING((arena)->pos, ArenaBase(arena))) /* String from static array */ #define StringFromArray(a) \ ( \ Assert(IsArray(a)), \ ((String) { .len = sizeof(a), .text = (u8 *)(a) }) \ ) Struct(String) { u64 len; u8 *text; }; Struct(String16) { u64 len; u16 *text; }; Struct(String32) { u64 len; u32 *text; }; Struct(StringArray) { u64 count; String *strings; }; Struct(StringListNode) { String s; StringListNode *next; StringListNode *prev; }; Struct(StringList) { StringListNode *first; StringListNode *last; u64 count; }; #endif //////////////////////////////////////////////////////////// //~ Resource types #if LanguageIsC #define ResourceEmbeddedMagic 0xfc060937194f4406 Struct(ResourceStore) { u64 hash; }; Struct(ResourceKey) { u64 hash; }; #endif //////////////////////////////////////////////////////////// //~ Shader types #if LanguageIsC Struct(VertexShader) { ResourceKey resource; }; Struct(PixelShader) { ResourceKey resource; }; Struct(ComputeShader) { ResourceKey resource; }; # define VSDecl(name) extern VertexShader name; # define PSDecl(name) extern PixelShader name; # define CSDecl(name) extern ComputeShader name; //- Resource descriptor index types Struct(StructuredBufferRid) { u32 v; }; Struct(RWStructuredBufferRid) { u32 v; }; Struct(Texture1DRid) { u32 v; }; Struct(Texture2DRid) { u32 v; }; Struct(Texture3DRid) { u32 v; }; Struct(RWTexture1DRid) { u32 v; }; Struct(RWTexture2DRid) { u32 v; }; Struct(RWTexture3DRid) { u32 v; }; Struct(SamplerStateRid) { u32 v; }; #elif LanguageIsGpu //- Resource descriptor index types typedef uint StructuredBufferRid; typedef uint RWStructuredBufferRid; typedef uint Texture1DRid; typedef uint Texture2DRid; typedef uint Texture3DRid; typedef uint RWTexture1DRid; typedef uint RWTexture2DRid; typedef uint RWTexture3DRid; typedef uint SamplerStateRid; //- Shader declaration # define VSDecl(name) # define PSDecl(name) # define CSDecl(name) # define VSDef(name, ...) name(__VA_ARGS__) # define PSDef(name, ...) name(__VA_ARGS__) # define CSDef(name, ...) name(__VA_ARGS__) //- Semantic declaration # define Semantic(t, n) t n : n //- Descriptor heap index # define UniformResourceFromRid(rid) ResourceDescriptorHeap[rid] # define UniformSamplerFromRid(rid) SamplerDescriptorHeap[rid] # define NonUniformResourceFromRid(rid) ResourceDescriptorHeap[NonUniformResourceIndex(rid)] # define NonUniformSamplerFromRid(rid) SamplerDescriptorHeap[NonUniformResourceIndex(rid)] #endif //////////////////////////////////////////////////////////// //~ Fibers # define MaxFibers 4096 StaticAssert(MaxFibers < I16Max); /* MaxFibers should fit in FiberId */ #if LanguageIsC # if PlatformIsWindows # define FiberId() (*(volatile i16 *)__readgsqword(0x20)) # else # error FiberId not implemented # endif #endif //////////////////////////////////////////////////////////// //~ Exit callback types #if LanguageIsC # define ExitFuncDef(name) void name(void) typedef ExitFuncDef(ExitFunc); #endif //////////////////////////////////////////////////////////// //~ @hookdecl Api hooks #if LanguageIsC //- Core hooks StringList GetCommandLineArgs(void); void Echo(String msg); b32 Panic(String msg); b32 IsRunningInDebugger(void); i64 TimeNs(void); u32 GetNumHardwareThreads(void); void TrueRand(String buffer); void OnExit(ExitFunc *func); void SignalExit(i32 code); void ExitNow(i32 code); //- Meta hooks void StartupLayers(void); #endif //////////////////////////////////////////////////////////// //~ Config #include "../config.h"