481 lines
12 KiB
C
481 lines
12 KiB
C
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ Compiler feature flags
|
|
|
|
/* Compile definition defaults */
|
|
#ifndef RtcIsEnabled
|
|
# define RtcIsEnabled 0
|
|
#endif
|
|
|
|
#ifndef AsanIsEnabled
|
|
# define AsanIsEnabled 0
|
|
#endif
|
|
|
|
#ifndef CrtlibIsEnabled
|
|
# define CrtlibIsEnabled 0
|
|
#endif
|
|
|
|
#ifndef DebinfoEnabled
|
|
# define DebinfoEnabled 0
|
|
#endif
|
|
|
|
#ifndef DeveloperIsEnabled
|
|
# define DeveloperIsEnabled 0
|
|
#endif
|
|
|
|
#ifndef ProfilingIsEnabled
|
|
# define ProfilingIsEnabled 0
|
|
#endif
|
|
|
|
#ifndef UnoptimizedIsEnabled
|
|
# define UnoptimizedIsEnabled 0
|
|
#endif
|
|
|
|
#ifndef TestsAreEnabled
|
|
# define TestsAreEnabled 0
|
|
#endif
|
|
|
|
#ifndef IncbinRawDir
|
|
# define IncbinDir ""
|
|
#else
|
|
# define IncbinDir Stringize(IncbinRawDir)
|
|
#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(__cplusplus)
|
|
# define LanguageIsCpp 1
|
|
# define LanguageIsC 0
|
|
# define LanguageIsGpu 0
|
|
#elif defined(__STDC_VERSION__)
|
|
# define LanguageIsCpp 0
|
|
# define LanguageIsC 1
|
|
# define LanguageIsGpu 0
|
|
#elif defined(__HLSL_VERSION)
|
|
# define LanguageIsCpp 0
|
|
# define LanguageIsC 0
|
|
# define LanguageIsGpu 1
|
|
#else
|
|
# error Unknown language
|
|
#endif
|
|
|
|
//- Operating 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
|
|
|
|
//- Windows NTDDI version
|
|
/* FIXME: 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
|
|
|
|
////////////////////////////////
|
|
//~ Debug
|
|
|
|
//- Static assert
|
|
#if CompilerIsMsvc || (LanguageIsC && __STDC_VERSION__ < 202311L) || LanguageIsGpu
|
|
# if CompilerIsMsvc
|
|
# define StaticAssert2(cond, line) struct STATIC_ASSERT_____##line {int foo[(cond) ? 1 : -1];}
|
|
# define StaticAssert1(cond, line) StaticAssert2(cond, line)
|
|
# define StaticAssert(cond) StaticAssert1(cond, __LINE__)
|
|
# else
|
|
# define StaticAssert(cond) _Static_assert(cond, "")
|
|
# endif
|
|
#else
|
|
# define StaticAssert(c) static_assert(c, "")
|
|
#endif
|
|
|
|
//- Debug assert
|
|
#if RtcIsEnabled
|
|
# if CompilerIsMsvc
|
|
# define Assert(cond) ((cond) ? 1 : ((*(volatile int *)0) = 0, 0))
|
|
# 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
|
|
|
|
//- Initlist compatibility
|
|
#if CompilerIsMsvc && LanguageIsCpp
|
|
# define CppCompatInitListType(type)
|
|
#else
|
|
# define CppCompatInitListType(type) (type)
|
|
#endif
|
|
|
|
//- 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 LocalPersist static
|
|
#define Global static
|
|
/* TODO: Remove this */
|
|
#define internal 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 CompilerIsMsvc
|
|
# if LanguageIsCpp
|
|
# define FALLTHROUGH [[fallthrough]]
|
|
# else
|
|
# define FALLTHROUGH
|
|
# endif
|
|
#elif 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)
|
|
|
|
////////////////////////////////
|
|
//~ Type helper macros
|
|
|
|
//- typeof
|
|
#if CompilerIsMsvc
|
|
/* Typeof not supported in MSVC */
|
|
# define TypeofIsDefined 0
|
|
# define typeof(type) Assert(0)
|
|
#else
|
|
# define TypeofIsDefined 1
|
|
# if LanguageIsCpp || (__STDC_VERSION__ < 202311L)
|
|
# define typeof(type) __typeof__(type)
|
|
# endif
|
|
#endif
|
|
|
|
//- alignof
|
|
#if (CompilerIsMsvc && LanguageIsC) || (LanguageIsC && (__STDC_VERSION__ < 202311L))
|
|
# define alignof(type) __alignof(type)
|
|
#endif
|
|
|
|
//- sizeof_field
|
|
#define sizeof_field(type, field) sizeof(((type *)0)->field)
|
|
|
|
//- offsetof
|
|
#if 0
|
|
#if !CompilerIsMsvc
|
|
# if !defined _CRT_USE_BUILTIN_OFFSETOF
|
|
# define offsetof(type, field) ((u64)&(((type *)0)->field))
|
|
# else
|
|
# define offsetof(type, field) __builtin_offsetof(type, field)
|
|
# endif
|
|
#endif
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ Array helper macros
|
|
|
|
//- 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)))
|
|
|
|
////////////////////////////////
|
|
//~ Struct alignment / padding macros
|
|
|
|
//- Pack
|
|
#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
|
|
|
|
////////////////////////////////
|
|
//~ 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 ColorWhite Rgb32(0xFF, 0xFF, 0xFF)
|
|
#define ColorBlack Rgb32(0x00, 0x00, 0x00)
|
|
#define ColorRed Rgb32(0xFF, 0x00, 0x00)
|
|
#define ColorGreen Rgb32(0x00, 0xFF, 0x00)
|
|
#define ColorBlue Rgb32(0x00, 0x00, 0xFF)
|
|
#define ColorYellow Rgb32(0xFF, 0xFF, 0x00)
|
|
#define ColorOrange Rgb32(0xFF, 0xA5, 0x00)
|
|
#define ColorPurple Rgb32(0xFF, 0x00, 0XFF)
|
|
|
|
////////////////////////////////
|
|
//~ Gpu helpers
|
|
|
|
#if LanguageIsGpu
|
|
//- Resource heap index
|
|
# define GpuResourceFromUrid(urid) ResourceDescriptorHeap[urid]
|
|
# define GpuResourceFromNurid(nurid) ResourceDescriptorHeap[NonUniformResourceIndex(nurid)]
|
|
|
|
//- Semantic declaration
|
|
# define Semantic(t, n) t n : n
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ Intrinsic headers
|
|
|
|
#if !LanguageIsGpu
|
|
/* 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 "intrin.h"
|
|
#include "nmmintrin.h" /* SSE4.2 */
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ Struct helper macros
|
|
|
|
#define Struct(name) typedef struct name name; struct name
|
|
#define AlignedStruct(name, n) typedef struct name name; struct alignas(n) name
|
|
|
|
////////////////////////////////
|
|
//~ Scalar types
|
|
|
|
#if !LanguageIsGpu
|
|
//- Cpu scalar types
|
|
#include "stdint.h"
|
|
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;
|
|
#else
|
|
//- 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 !LanguageIsGpu
|
|
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
|
|
|
|
////////////////////////////////
|
|
//~ Config
|
|
|
|
#include "../config.h"
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|