742 lines
21 KiB
C
742 lines
21 KiB
C
/* This header is precompiled and automatically included into all source files */
|
|
|
|
/* NOTE: Include guards disabled since it breaks editor parsing */
|
|
//#ifndef COMMON_H
|
|
//#define COMMON_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* ========================== *
|
|
* Compiler headers
|
|
* ========================== */
|
|
|
|
/* 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 <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
#include <intrin.h>
|
|
#include <nmmintrin.h> /* SSE4.2 */
|
|
|
|
/* ========================== *
|
|
* Flag defaults
|
|
* ========================== */
|
|
|
|
/* Compile definition defaults */
|
|
#ifndef RTC
|
|
# define RTC 0
|
|
#endif
|
|
|
|
#ifndef ASAN
|
|
# define ASAN 0
|
|
#endif
|
|
|
|
#ifndef CRTLIB
|
|
# define CRTLIB 0
|
|
#endif
|
|
|
|
#ifndef DEBINFO
|
|
# define DEBINFO 0
|
|
#endif
|
|
|
|
#ifndef DEVELOPER
|
|
# define DEVELOPER 0
|
|
#endif
|
|
|
|
#ifndef PROFILING
|
|
# define PROFILING 0
|
|
#endif
|
|
|
|
#ifndef UNOPTIMIZED
|
|
# define UNOPTIMIZED 0
|
|
#endif
|
|
|
|
#ifndef RUN_TESTS
|
|
# define RUN_TESTS 0
|
|
#endif
|
|
|
|
#ifndef INCBIN_DIR_RAW
|
|
# define INCBIN_DIR ""
|
|
#else
|
|
# define INCBIN_DIR STRINGIZE(INCBIN_DIR_RAW)
|
|
#endif
|
|
|
|
/* ========================== *
|
|
* Machine context
|
|
* ========================== */
|
|
|
|
/* Compiler */
|
|
#if defined(__clang__)
|
|
# define COMPILER_CLANG 1
|
|
# define COMPILER_MSVC 0
|
|
#elif defined(_MSC_VER)
|
|
# define COMPILER_CLANG 0
|
|
# define COMPILER_MSVC 1
|
|
#else
|
|
# error "Unknown compiler"
|
|
#endif
|
|
|
|
/* Operating system */
|
|
#if defined(_WIN32)
|
|
# define PLATFORM_WINDOWS 1
|
|
# define PLATFORM_MAC 0
|
|
# define PLATFORM_LINUX 0
|
|
#elif defined(__APPLE__) && defined(__MACH__)
|
|
# define PLATFORM_WINDOWS 0
|
|
# define PLATFORM_MAC 1
|
|
# define PLATFORM_LINUX 0
|
|
#elif defined(__gnu_linux__)
|
|
# define PLATFORM_WINDOWS 0
|
|
# define PLATFORM_MAC 0
|
|
# define PLATFORM_LINUX 1
|
|
#else
|
|
# error "Unknown OS"
|
|
#endif
|
|
|
|
#if defined(__cplusplus)
|
|
# define LANGUAGE_CPP 1
|
|
# define LANGUAGE_C 0
|
|
#else
|
|
# define LANGUAGE_CPP 0
|
|
# define LANGUAGE_C 1
|
|
#endif
|
|
|
|
/* ========================== *
|
|
* Debug
|
|
* ========================== */
|
|
|
|
/* Compile time assert */
|
|
#define CT_ASSERT3(cond, line) struct CT_ASSERT_____##line {int foo[(cond) ? 1 : -1];}
|
|
#define CT_ASSERT2(cond, line) CT_ASSERT3(cond, line)
|
|
#define CT_ASSERT(cond) CT_ASSERT2(cond, __LINE__)
|
|
|
|
#if COMPILER_MSVC
|
|
# if DEBINFO
|
|
# define DEBUG_ALIAS(var, alias) *(alias) = &(var)
|
|
# else
|
|
# define DEBUG_ALIAS(var, alias) *(alias) = &(var)
|
|
# endif
|
|
#else
|
|
# if DEBINFO
|
|
# define DEBUG_ALIAS(var, alias) __attribute((used)) *(alias) = &(var)
|
|
# else
|
|
# define DEBUG_ALIAS(var, alias) __attribute((unused)) *(alias) = &(var)
|
|
# endif
|
|
#endif
|
|
|
|
#if RTC
|
|
# if COMPILER_MSVC
|
|
# 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; (UNUSED) __DEBUGBREAKABLE_VAR; } (void)0
|
|
#else
|
|
# define ASSERT(cond) (void)(0)
|
|
#endif
|
|
|
|
/* Address sanitization */
|
|
#if ASAN
|
|
void __asan_poison_memory_region(void const volatile *, size_t);
|
|
void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
|
# define ASAN_POISON(addr, size) __asan_poison_memory_region((addr), (size));
|
|
# define ASAN_UNPOISON(addr, size) __asan_unpoison_memory_region((addr), (size));
|
|
#else
|
|
# define ASAN_POISON(addr, size)
|
|
# define ASAN_UNPOISON(addr, size)
|
|
#endif
|
|
|
|
/* ========================== *
|
|
* Common macros
|
|
* ========================== */
|
|
|
|
#if COMPILER_MSVC && LANGUAGE_CPP
|
|
# define CPPCOMPAT_INITLIST_TYPE(type)
|
|
#else
|
|
# define CPPCOMPAT_INITLIST_TYPE(type) (type)
|
|
#endif
|
|
|
|
/* Zero initialization macro */
|
|
#if LANGUAGE_C
|
|
# define ZI { 0 }
|
|
#else
|
|
# define ZI { }
|
|
#endif
|
|
|
|
#if 1
|
|
# define INLINE static inline
|
|
#else
|
|
/* TODO: benchmark benefits of forced inlining */
|
|
# define INLINE static inline __attribute((always_inline))
|
|
#endif
|
|
|
|
#if COMPILER_MSVC
|
|
# define FORCE_INLINE static inline __forceinline
|
|
#else
|
|
# define FORCE_INLINE static inline __attribute((always_inline))
|
|
#endif
|
|
|
|
/* Separate `static` usage into different keywords for easier grepping */
|
|
#define LOCAL_PERSIST static
|
|
#define INTERNAL static
|
|
#define GLOBAL static
|
|
|
|
/* Read-only */
|
|
#if PLATFORM_WINDOWS
|
|
# if COMPILER_MSVC
|
|
# pragma section(".rdata$", read)
|
|
# define READONLY __declspec(allocate(".rdata$"))
|
|
# else
|
|
# define READONLY __declspec(allocate(".rdata"))
|
|
# endif
|
|
#elif PLATFORM_MAC
|
|
# define READONLY __attribute((section("__TEXT,__const")))
|
|
#else
|
|
# define READONLY __attribute((section(".rodata")))
|
|
#endif
|
|
|
|
/* Markup */
|
|
#define UNUSED void
|
|
|
|
#if COMPILER_MSVC
|
|
# if LANGUAGE_CPP
|
|
# define FALLTHROUGH [[fallthrough]]
|
|
# else
|
|
# define FALLTHROUGH
|
|
# endif
|
|
#elif COMPILER_CLANG
|
|
# define FALLTHROUGH __attribute((fallthrough))
|
|
#else
|
|
# define FALLTHROUGH
|
|
#endif
|
|
|
|
/* Sizes */
|
|
#define KILOBYTE(n) (n*1024ULL)
|
|
#define MEGABYTE(n) (n*KILOBYTE(1024ULL))
|
|
#define GIGABYTE(n) (n*MEGABYTE(1024ULL))
|
|
#define TERABYTE(n) (n*GIGABYTE(1024ULL))
|
|
|
|
/* Time */
|
|
#define NS_FROM_SECONDS(s) ((i64)((s) * 1000000000.0))
|
|
#define SECONDS_FROM_NS(ns) ((f64)(ns) / 1000000000.0)
|
|
|
|
/* typeof */
|
|
#if COMPILER_MSVC
|
|
/* Typeof not supported in MSVC */
|
|
# define TYPEOF_DEFINED 0
|
|
# define typeof(type) ASSERT(false)
|
|
#else
|
|
# define TYPEOF_DEFINED 1
|
|
# if LANGUAGE_CPP || (__STDC_VERSION__ < 202311L)
|
|
# define typeof(type) __typeof__(type)
|
|
# endif
|
|
#endif
|
|
|
|
/* alignof */
|
|
#if COMPILER_MSVC || (LANGUAGE_C && (__STDC_VERSION__ < 202311L))
|
|
# define alignof(type) __alignof(type)
|
|
#endif
|
|
|
|
#define ARRAY_COUNT(a) (sizeof(a) / sizeof((a)[0]))
|
|
|
|
/* Field macros */
|
|
#define FIELD_SIZEOF(type, field) sizeof(((type *)0)->field)
|
|
|
|
#if COMPILER_MSVC && !defined _CRT_USE_BUILTIN_OFFSETOF
|
|
# define FIELD_OFFSETOF(type, field) ((u64)&(((type *)0)->field))
|
|
#else
|
|
# define FIELD_OFFSETOF(type, field) __builtin_offsetof(type, field)
|
|
#endif
|
|
|
|
/* Bool */
|
|
#if !LANGUAGE_CPP
|
|
# define true 1
|
|
# define false 0
|
|
#endif
|
|
|
|
/* Array */
|
|
#define IS_INDEXABLE(a) (sizeof(a[0]))
|
|
#define IS_ARRAY(a) (IS_INDEXABLE(a) && (((void *)&a) == ((void *)a)))
|
|
|
|
/* Pack */
|
|
#if COMPILER_MSVC
|
|
# define PACK(s) __pragma(pack(push, 1)) s __pragma(pack(pop))
|
|
#else
|
|
# define PACK(s) s __attribute((__packed__))
|
|
#endif
|
|
|
|
/* Color */
|
|
#define RGB(r, g, b) RGBA((r), (g), (b), 0xFF)
|
|
#define RGBA(r, g, b, a) (u32)((u32)(r) | ((u32)(g) << 8) | ((u32)(b) << 16) | ((u32)(a) << 24))
|
|
#define BGR(rgb) ((((rgb >> 0) & 0xFF) << 16) | (((rgb >> 8) & 0xFF) << 8) | (((rgb >> 16) & 0xFF) << 0))
|
|
|
|
#define _RGB_U8_FROM_F(fl) ((u8)((fl * 255.0) + 0.5))
|
|
#define RGBA_F(r, g, b, a) RGBA(_RGB_U8_FROM_F((r)), _RGB_U8_FROM_F((g)), _RGB_U8_FROM_F((b)), _RGB_U8_FROM_F((a)))
|
|
#define RGB_F(r, g, b) RGBA_F((r), (g), (b), 1.f)
|
|
|
|
#define ALPHA_F(color, a) ((color) & 0x00FFFFFF) | (_RGB_U8_FROM_F((a)) << 24)
|
|
|
|
/* Color defines */
|
|
#define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF)
|
|
#define COLOR_BLACK RGB(0x00, 0x00, 0x00)
|
|
#define COLOR_RED RGB(0xFF, 0x00, 0x00)
|
|
#define COLOR_GREEN RGB(0x00, 0xFF, 0x00)
|
|
#define COLOR_BLUE RGB(0x00, 0x00, 0xFF)
|
|
#define COLOR_YELLOW RGB(0xFF, 0xFF, 0x00)
|
|
#define COLOR_ORANGE RGB(0xFF, 0xA5, 0x00)
|
|
#define COLOR_PURPLE RGB(0xFF, 0x00, 0XFF)
|
|
|
|
/* Barrier */
|
|
#if COMPILER_MSVC
|
|
# define WRITE_BARRIER() _WriteBarrier()
|
|
# define READ_BARRIER() _ReadBarrier()
|
|
#elif defined(__x86_64) || defined(__i386__)
|
|
# define WRITE_BARRIER() __asm__ volatile("" ::: "memory")
|
|
# define READ_BARRIER() __asm__ volatile("" ::: "memory")
|
|
#else
|
|
# error "Memory barriers not implemented"
|
|
#endif
|
|
|
|
/* Cat */
|
|
#define CAT1(a, b) a ## b
|
|
#define CAT(a, b) CAT1(a, b)
|
|
|
|
/* Stringize */
|
|
#define STRINGIZE2(x) #x
|
|
#define STRINGIZE(x) STRINGIZE2(x)
|
|
|
|
/* ========================== *
|
|
* Primitive types
|
|
* ========================== */
|
|
|
|
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 i32 b32;
|
|
|
|
#define U8_MAX (0xFF)
|
|
#define U16_MAX (0xFFFF)
|
|
#define U32_MAX (0xFFFFFFFF)
|
|
#define U64_MAX (0xFFFFFFFFFFFFFFFFULL)
|
|
|
|
#define I8_MAX (0x7F)
|
|
#define I16_MAX (0x7FFF)
|
|
#define I32_MAX (0x7FFFFFFF)
|
|
#define I64_MAX (0x7FFFFFFFFFFFFFFFLL)
|
|
|
|
#define I8_MIN ((i8)-0x80)
|
|
#define I16_MIN ((i16)-0x8000)
|
|
#define I32_MIN ((i32)-0x80000000)
|
|
#define I64_MIN ((i64)-0x8000000000000000ULL)
|
|
|
|
GLOBAL const u32 _f32_infinity_u32 = 0x7f800000;
|
|
GLOBAL const f32 *_f32_infinity = (f32 *)&_f32_infinity_u32;
|
|
#define F32_INFINITY (*_f32_infinity)
|
|
|
|
GLOBAL const u64 _f64_infinity_u64 = 0x7ff0000000000000ULL;
|
|
GLOBAL const f64 *_f64_infinity = (f64 *)&_f64_infinity_u64;
|
|
#define F64_INFINITY (*_f64_infinity)
|
|
|
|
GLOBAL const u32 _f32_nan_u32 = 0x7f800001;
|
|
GLOBAL const f32 *_f32_nan = (f32 *)&_f32_nan_u32;
|
|
#define F32_NAN (*_f32_nan)
|
|
|
|
GLOBAL const u64 _f64_nan_u64 = 0x7ff8000000000001;
|
|
GLOBAL const f64 *_f64_nan = (f64 *)&_f64_nan_u64;
|
|
#define F64_NAN (*_f64_nan)
|
|
|
|
#define F32_IS_NAN(x) (x != x)
|
|
#define F64_IS_NAN(x) (x != x)
|
|
|
|
#define PI ((f32)3.14159265358979323846)
|
|
#define TAU ((f32)6.28318530717958647693)
|
|
|
|
/* ========================== *
|
|
* Atomics
|
|
* ========================== */
|
|
|
|
struct atomic_i32 {
|
|
volatile i32 _v;
|
|
};
|
|
|
|
struct atomic_i64 {
|
|
volatile i64 _v;
|
|
};
|
|
|
|
struct atomic_u32 {
|
|
volatile u32 _v;
|
|
};
|
|
|
|
struct atomic_u64 {
|
|
volatile u64 _v;
|
|
};
|
|
|
|
struct atomic_ptr {
|
|
volatile void *_v;
|
|
};
|
|
|
|
/* ========================== *
|
|
* Common structs
|
|
* ========================== */
|
|
|
|
struct arena {
|
|
u64 pos;
|
|
u64 committed;
|
|
u64 reserved;
|
|
u8 *base;
|
|
#if RTC
|
|
b32 readonly;
|
|
#endif
|
|
};
|
|
|
|
struct string {
|
|
u64 len;
|
|
u8 *text;
|
|
};
|
|
|
|
struct string16 {
|
|
u64 len;
|
|
u16 *text;
|
|
};
|
|
|
|
struct string32 {
|
|
u64 len;
|
|
u32 *text;
|
|
};
|
|
|
|
#define UID(hi64, lo64) ((struct uid) { .hi = (hi64), .lo = (lo64) })
|
|
struct uid {
|
|
u64 hi;
|
|
u64 lo;
|
|
};
|
|
INLINE b32 uid_eq(struct uid a, struct uid b) { return a.hi == b.hi && a.lo == b.lo; }
|
|
INLINE b32 uid_is_zero(struct uid v) { return v.hi == 0 && v.lo == 0; }
|
|
|
|
struct image_rgba {
|
|
u32 width;
|
|
u32 height;
|
|
u32 *pixels; /* Array of [width * height] pixels */
|
|
};
|
|
|
|
struct pcm {
|
|
u64 count;
|
|
i16 *samples;
|
|
};
|
|
|
|
struct sim_client_handle {
|
|
u32 idx;
|
|
u32 gen;
|
|
};
|
|
|
|
struct sim_ent_id {
|
|
struct uid uid;
|
|
};
|
|
|
|
struct space_entry_handle {
|
|
u64 idx;
|
|
u64 gen;
|
|
};
|
|
|
|
struct host_channel_id {
|
|
u32 gen;
|
|
u32 idx;
|
|
};
|
|
|
|
/* ========================== *
|
|
* Tag structs
|
|
* ========================== */
|
|
|
|
struct sprite_tag {
|
|
u64 hash;
|
|
struct string path;
|
|
};
|
|
|
|
/* ========================== *
|
|
* String utils
|
|
* ========================== */
|
|
|
|
/* Expand C string literal with size for string initialization */
|
|
#define LIT(cstr_lit) CPPCOMPAT_INITLIST_TYPE(struct string) { (sizeof((cstr_lit)) - 1), (u8 *)(cstr_lit) }
|
|
|
|
/* Same as `STR`, but works with static variable initialization */
|
|
#define LIT_NOCAST(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
|
|
|
#define STRING(size, data) (CPPCOMPAT_INITLIST_TYPE(struct string) { (size), (data) })
|
|
|
|
#define STRING_FROM_POINTERS(p0, p1) (CPPCOMPAT_INITLIST_TYPE(struct string) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
|
|
|
#define STRING_FROM_STRUCT(ptr) (CPPCOMPAT_INITLIST_TYPE(struct string) { sizeof(*(ptr)), (u8 *)(ptr) })
|
|
|
|
/* String from static array */
|
|
#define STRING_FROM_ARRAY(a) \
|
|
( \
|
|
/* Must be array */ \
|
|
ASSERT(IS_ARRAY(a)), \
|
|
/* Must be array of bytes */ \
|
|
ASSERT(sizeof((a)[0]) == sizeof(u8)), \
|
|
((struct string) { .len = ARRAY_COUNT(a), .text = (u8 *)(a) }) \
|
|
)
|
|
|
|
/* ========================== *
|
|
* Math types
|
|
* ========================== */
|
|
|
|
#define V2(x, y) CPPCOMPAT_INITLIST_TYPE(struct v2) { (x), (y) }
|
|
#define V2_FROM_V2I32(v) V2((v).x, (v).y)
|
|
struct v2 {
|
|
f32 x, y;
|
|
};
|
|
|
|
struct v2_array {
|
|
struct v2 *points;
|
|
u64 count;
|
|
};
|
|
|
|
#define V3(x, y, z) ((struct v3) { (x), (y), (z) })
|
|
struct v3 {
|
|
f32 x, y, z;
|
|
};
|
|
|
|
struct v3_array {
|
|
struct v3 *points;
|
|
u64 count;
|
|
};
|
|
|
|
#define V4(x, y, z, w) ((struct v4) { (x), (y), (z), (w) })
|
|
struct v4 {
|
|
f32 x, y, z, w;
|
|
};
|
|
|
|
struct v4_array {
|
|
struct v4 *points;
|
|
u64 count;
|
|
};
|
|
|
|
#define V2I32(x, y) CPPCOMPAT_INITLIST_TYPE(struct v2i32) { (x), (y) }
|
|
struct v2i32 {
|
|
i32 x, y;
|
|
};
|
|
|
|
struct xform {
|
|
struct v2 bx; /* X basis vector (x axis) */
|
|
struct v2 by; /* Y basis vector (y axis)*/
|
|
struct v2 og; /* Translation vector (origin) */
|
|
};
|
|
|
|
struct mat4x4 {
|
|
union {
|
|
struct { struct v4 bx, by, bz, bw; };
|
|
f32 e[4][4];
|
|
};
|
|
};
|
|
|
|
#define RECT(_x, _y, _width, _height) (struct rect) { .x = (_x), .y = (_y), .width = (_width), .height = (_height) }
|
|
#define RECT_FROM_V2(_pos, _size) (struct rect) { .pos = (_pos), .size = (_size) }
|
|
struct rect {
|
|
union {
|
|
struct { f32 x, y, width, height; };
|
|
struct { struct v2 pos, size; };
|
|
};
|
|
};
|
|
|
|
INLINE b32 rect_eq(struct rect r1, struct rect r2) { return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height == r2.height; }
|
|
|
|
struct aabb {
|
|
struct v2 p0, p1;
|
|
};
|
|
|
|
/* Values expected to be normalized 0.0 -> 1.0 */
|
|
#define CLIP_ALL ((struct clip_rect) { { 0.0f, 0.0f }, { 1.0f, 1.0f } })
|
|
struct clip_rect {
|
|
struct v2 p0, p1;
|
|
};
|
|
|
|
#define QUAD_UNIT_SQUARE (struct quad) { .p0 = V2(0, 0), .p1 = V2(0, 1), .p2 = V2(1, 1), .p3 = V2(1, 0) }
|
|
#define QUAD_UNIT_SQUARE_CENTERED (struct quad) { .p0 = V2(-0.5f, -0.5f), .p1 = V2(0.5f, -0.5f), .p2 = V2(0.5f, 0.5f), .p3 = V2(-0.5f, 0.5f) }
|
|
struct quad {
|
|
union {
|
|
struct { struct v2 p0, p1, p2, p3; };
|
|
struct { struct v2 e[4]; };
|
|
};
|
|
};
|
|
|
|
/* (T)ranslation, (R)otation, (S)cale */
|
|
#define TRS(...) ((struct trs) { .t = V2(0,0), .s = V2(1, 1), .r = 0, __VA_ARGS__ })
|
|
struct trs {
|
|
struct v2 t;
|
|
struct v2 s;
|
|
f32 r;
|
|
};
|
|
|
|
/* ========================== *
|
|
* Collider types
|
|
* ========================== */
|
|
|
|
struct collider_shape {
|
|
struct v2 points[8];
|
|
u32 count;
|
|
f32 radius;
|
|
};
|
|
|
|
/* ========================== *
|
|
* Common utilities
|
|
* ========================== */
|
|
|
|
INLINE u8 min_u8(u8 a, u8 b) { return a <= b ? a : b; }
|
|
INLINE u8 max_u8(u8 a, u8 b) { return a >= b ? a : b; }
|
|
INLINE u32 min_u32(u32 a, u32 b) { return a <= b ? a : b; }
|
|
INLINE u32 max_u32(u32 a, u32 b) { return a >= b ? a : b; }
|
|
INLINE u64 min_u64(u64 a, u64 b) { return a <= b ? a : b; }
|
|
INLINE u64 max_u64(u64 a, u64 b) { return a >= b ? a : b; }
|
|
INLINE i32 min_i32(i32 a, i32 b) { return a <= b ? a : b; }
|
|
INLINE i32 max_i32(i32 a, i32 b) { return a >= b ? a : b; }
|
|
INLINE i64 min_i64(i64 a, i64 b) { return a <= b ? a : b; }
|
|
INLINE i64 max_i64(i64 a, i64 b) { return a >= b ? a : b; }
|
|
INLINE f32 min_f32(f32 a, f32 b) { return a <= b ? a : b; }
|
|
INLINE f32 max_f32(f32 a, f32 b) { return a >= b ? a : b; }
|
|
INLINE f64 min_f64(f64 a, f64 b) { return a <= b ? a : b; }
|
|
INLINE f64 max_f64(f64 a, f64 b) { return a >= b ? a : b; }
|
|
|
|
INLINE u32 clamp_u32(u32 v, u32 min, u32 max) { return v < min ? min : v > max ? max : v; }
|
|
INLINE u64 clamp_u64(u64 v, u64 min, u64 max) { return v < min ? min : v > max ? max : v; }
|
|
INLINE i32 clamp_i32(i32 v, i32 min, i32 max) { return v < min ? min : v > max ? max : v; }
|
|
INLINE i64 clamp_i64(i64 v, i64 min, i64 max) { return v < min ? min : v > max ? max : v; }
|
|
INLINE f32 clamp_f32(f32 v, f32 min, f32 max) { return v < min ? min : v > max ? max : v; }
|
|
INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; }
|
|
|
|
/* ========================== *
|
|
* Profiling
|
|
* ========================== */
|
|
|
|
#if PROFILING
|
|
|
|
#include "third_party/tracy/tracy/TracyC.h"
|
|
|
|
#define PROFILING_CAPTURE_FRAME_IMAGE 1
|
|
|
|
/* Clang/GCC cleanup macros */
|
|
#if COMPILER_MSVC
|
|
# error "MSVC not supported for profiling (cleanup attributes are required for profiling markup)"
|
|
#else
|
|
# ifdef TRACY_NO_CALLSTACK
|
|
# define __prof static const struct ___tracy_source_location_data CAT(__tracy_source_location,__LINE__) = { NULL, __func__, __FILE__, (uint32_t)__LINE__, 0 }; __attribute((cleanup(__prof_zone_cleanup_func))) TracyCZoneCtx __tracy_zone_ctx = ___tracy_emit_zone_begin( &CAT(__tracy_source_location,__LINE__), true );
|
|
# define __profscope(name) static const struct ___tracy_source_location_data CAT(__tracy_source_location,__LINE__) = { #name, __func__, __FILE__, (uint32_t)__LINE__, 0 }; __attribute((cleanup(__prof_zone_cleanup_func))) TracyCZoneCtx __tracy_zone_ctx = ___tracy_emit_zone_begin( &CAT(__tracy_source_location,__LINE__), true );
|
|
# else
|
|
# define __prof static const struct ___tracy_source_location_data CAT(__tracy_source_location,__LINE__) = { NULL, __func__, __FILE__, (uint32_t)__LINE__, 0 }; __attribute((cleanup(__prof_zone_cleanup_func))) TracyCZoneCtx __tracy_zone_ctx = ___tracy_emit_zone_begin_callstack( &CAT(__tracy_source_location,__LINE__), TRACY_CALLSTACK, true );
|
|
# define __profscope(name) static const struct ___tracy_source_location_data CAT(__tracy_source_location,__LINE__) = { #name, __func__, __FILE__, (uint32_t)__LINE__, 0 }; __attribute((cleanup(__prof_zone_cleanup_func))) TracyCZoneCtx __tracy_zone_ctx = ___tracy_emit_zone_begin_callstack( &CAT(__tracy_source_location,__LINE__), TRACY_CALLSTACK, true );
|
|
# endif
|
|
# define __profscope_dx11(dx11_ctx, name, color) static const struct ___tracy_source_location_data CAT(__tracy_gpu_d3d11_source_location,__LINE__) = { #name, __func__, __FILE__, (uint32_t)__LINE__, BGR(color) }; __attribute((cleanup(__prof_dx11_zone_cleanup_func))) TracyCD3D11ZoneCtx __tracy_d3d11_zone_ctx; ___tracy_d3d11_emit_zone_begin( dx11_ctx, &__tracy_d3d11_zone_ctx, &CAT(__tracy_gpu_d3d11_source_location,__LINE__), true);
|
|
#endif
|
|
INLINE void __prof_zone_cleanup_func(TracyCZoneCtx *ctx) { TracyCZoneEnd(*ctx); }
|
|
INLINE void __prof_dx11_zone_cleanup_func(TracyCD3D11ZoneCtx *ctx) { ___tracy_d3d11_emit_zone_end(*ctx); }
|
|
|
|
#define __profalloc(ptr, size) TracyCAlloc((ptr), (size))
|
|
#define __proffree(ptr) TracyCFree((ptr))
|
|
#define __profmsg(txt, len, col) TracyCMessageC((txt), (len), BGR(col));
|
|
#define __profframe(name) TracyCFrameMarkNamed((name))
|
|
#define __profthread(name) TracyCSetThreadName((name))
|
|
|
|
#define __proflock_ctx TracyCSharedLockCtx
|
|
#define __proflock_alloc(ctx) TracyCSharedLockAnnounce((ctx))
|
|
#define __proflock_release(ctx) TracyCSharedLockTerminate((ctx))
|
|
#define __proflock_before_exclusive_lock(ctx) TracyCSharedLockBeforeExclusiveLock((ctx))
|
|
#define __proflock_after_exclusive_lock(ctx) TracyCSharedLockAfterExclusiveLock((ctx))
|
|
#define __proflock_after_exclusive_unlock(ctx) TracyCSharedLockAfterExclusiveUnlock((ctx))
|
|
#define __proflock_after_try_exclusive_lock(ctx, acquired) TracyCSharedLockAfterTryExclusiveLock((ctx), (acquired))
|
|
#define __proflock_before_shared_lock(ctx) TracyCSharedLockBeforeSharedLock((ctx))
|
|
#define __proflock_after_shared_lock(ctx) TracyCSharedLockAfterSharedLock((ctx))
|
|
#define __proflock_after_shared_unlock(ctx) TracyCSharedLockAfterSharedUnlock((ctx))
|
|
#define __proflock_after_try_shared_lock(ctx, acquired) TracyCSharedLockAfterTrySharedLock((ctx), (acquired))
|
|
#define __proflock_mark(ctx) TracyCSharedLockMark((ctx))
|
|
#define __proflock_custom_name(ctx, name, len) TracyCSharedLockCustomName((ctx), (name), (len))
|
|
|
|
#define __prof_dx11_ctx TracyCD3D11Ctx
|
|
#define __prof_dx11_ctx_alloc(ctx, device, devicectx, name, name_len) ctx = ___tracy_d3d11_context_announce(device, devicectx, name, name_len)
|
|
#define __prof_dx11_ctx_release(ctx) ___tracy_d3d11_context_terminate(ctx)
|
|
#define __prof_dx11_collect(ctx) ___tracy_d3d11_context_collect(ctx)
|
|
|
|
enum __prof_plot_type {
|
|
__prof_plot_type_number = TracyPlotFormatNumber,
|
|
__prof_plot_type_memory = TracyPlotFormatMemory,
|
|
__prof_plot_type_percentage = TracyPlotFormatPercentage,
|
|
__prof_plot_type_watt = TracyPlotFormatWatt
|
|
};
|
|
#define __prof_plot_init(name, type, step, fill, color) TracyCPlotConfig(name, type, step, fill, BGR(color))
|
|
#define __prof_plot(name, val) TracyCPlot(name, val)
|
|
#define __prof_plot_i(name, val) TracyCPlotI(name, val)
|
|
|
|
#if PROFILING_CAPTURE_FRAME_IMAGE
|
|
# define __profframeimage(image, width, height, offset, flipped) TracyCFrameImage((image), (width), (height), (offset), (flipped));
|
|
#else
|
|
# define __profframeimage(image, width, height, offset, flipped)
|
|
#endif /* PROFILING_CAPTURE_FRAME_IMAGE */
|
|
|
|
#else
|
|
|
|
#define PROFILING_CAPTURE_FRAME_IMAGE 0
|
|
|
|
#define __prof
|
|
#define __profscope(name)
|
|
#define __profscope_dx11(dx11_ctx, name, color)
|
|
#define __profalloc(ptr, size)
|
|
#define __proffree(ptr)
|
|
#define __profmsg(txt, len, col)
|
|
#define __profframe(name)
|
|
#define __profthread(name)
|
|
#define __profframeimage(image, width, height, offset, flipped)
|
|
#define __proflock_ctx
|
|
#define __proflock_alloc(ctx)
|
|
#define __proflock_release(ctx)
|
|
#define __proflock_before_exclusive_lock(ctx)
|
|
#define __proflock_after_exclusive_lock(ctx)
|
|
#define __proflock_after_exclusive_unlock(ctx)
|
|
#define __proflock_after_try_exclusive_lock(ctx, acquired)
|
|
#define __proflock_before_shared_lock(ctx)
|
|
#define __proflock_after_shared_lock(ctx)
|
|
#define __proflock_after_shared_unlock(ctx)
|
|
#define __proflock_after_try_shared_lock(ctx, acquired)
|
|
#define __proflock_mark(ctx)
|
|
#define __proflock_custom_name(ctx, name, len)
|
|
#define __prof_dx11_ctx
|
|
#define __prof_dx11_ctx_alloc(ctx, device, devicectx, name, name_len)
|
|
#define __prof_dx11_ctx_release(ctx)
|
|
#define __prof_dx11_collect(ctx)
|
|
#define __prof_plot_init(name, type, step, fill, color)
|
|
#define __prof_plot(name, val)
|
|
#define __prof_plot_i(name, val)
|
|
|
|
#endif /* PROFILING */
|
|
|
|
/* ========================== *
|
|
* Configurable constants
|
|
* ========================== */
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|