util.h (10313B)
1 /* See LICENSE for license details. */ 2 #ifndef _UTIL_H_ 3 #define _UTIL_H_ 4 5 #include <stddef.h> 6 #include <stdint.h> 7 8 #include "compiler.h" 9 10 #ifndef asm 11 #define asm __asm__ 12 #endif 13 14 #ifndef typeof 15 #define typeof __typeof__ 16 #endif 17 18 #if OS_WINDOWS 19 #define EXPORT __declspec(dllexport) 20 #else 21 #define EXPORT 22 #endif 23 24 #ifdef _DEBUG 25 #define DEBUG_EXPORT EXPORT 26 #if OS_WINDOWS 27 #ifdef _BEAMFORMER_DLL 28 #define DEBUG_IMPORT __declspec(dllimport) 29 #else 30 #define DEBUG_IMPORT __declspec(dllexport) 31 #endif 32 #else 33 #ifdef _BEAMFORMER_DLL 34 #define DEBUG_IMPORT extern 35 #else 36 #define DEBUG_IMPORT 37 #endif 38 #endif 39 #define DEBUG_DECL(a) a 40 #define assert(c) do { if (!(c)) debugbreak(); } while (0) 41 #else 42 #define DEBUG_IMPORT global 43 #define DEBUG_EXPORT function 44 #define DEBUG_DECL(a) 45 #define assert(c) (void)(c) 46 #endif 47 #define ASSERT assert 48 49 #if ASAN_ACTIVE 50 void __asan_poison_memory_region(void *, ptrdiff_t); 51 void __asan_unpoison_memory_region(void *, ptrdiff_t); 52 #define asan_poison_region(region, size) __asan_poison_memory_region((region), (size)) 53 #define asan_unpoison_region(region, size) __asan_unpoison_memory_region((region), (size)) 54 #else 55 #define asan_poison_region(...) 56 #define asan_unpoison_region(...) 57 #endif 58 59 #define InvalidCodePath assert(0) 60 #define InvalidDefaultCase default: assert(0); break 61 62 #define arg_list(type, ...) (type []){__VA_ARGS__}, sizeof((type []){__VA_ARGS__}) / sizeof(type) 63 64 #define function static 65 #define global static 66 #define local_persist static 67 68 #define alignof _Alignof 69 #define static_assert _Static_assert 70 71 /* NOTE: garbage to get the prepocessor to properly stringize the value of a macro */ 72 #define str_(...) #__VA_ARGS__ 73 #define str(...) str_(__VA_ARGS__) 74 75 #define countof(a) (iz)(sizeof(a) / sizeof(*a)) 76 #define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) 77 #define ABS(x) ((x) < 0 ? (-x) : (x)) 78 #define BETWEEN(x, a, b) ((x) >= (a) && (x) <= (b)) 79 #define CLAMP(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x)) 80 #define CLAMP01(x) CLAMP(x, 0, 1) 81 #define ISPOWEROF2(a) (((a) & ((a) - 1)) == 0) 82 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 83 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 84 #define ORONE(x) ((x)? (x) : 1) 85 #define SIGN(x) ((x) < 0? -1 : 1) 86 #define swap(a, b) do {typeof(a) __tmp = (a); (a) = (b); (b) = __tmp;} while(0) 87 88 #define ISDIGIT(c) (BETWEEN((c), '0', '9')) 89 #define ISUPPER(c) (((c) & 0x20u) == 0) 90 #define TOLOWER(c) (((c) | 0x20u)) 91 #define TOUPPER(c) (((c) & ~(0x20u))) 92 93 #define f32_cmp(x, y) (ABS((x) - (y)) <= F32_EPSILON * MAX(1.0f, MAX(ABS(x), ABS(y)))) 94 95 #define EachBit(a, it) (u64 it = ctz_u64(a); it != 64; a &= ~(1u << (it)), it = ctz_u64(a)) 96 #define EachElement(array, it) (u64 it = 0; it < countof(array); it += 1) 97 #define EachEnumValue(type, it) (type it = (type)0; it < type##_Count; it = (type)(it + 1)) 98 #define EachNonZeroEnumValue(type, it) (type it = (type)1; it < type##_Count; it = (type)(it + 1)) 99 100 #define spin_wait(c) while ((c)) 101 102 /* NOTE(rnp): no guarantees about actually getting an element */ 103 #define SLLPop(list) list; list = list ? list->next : 0 104 #define SLLPush(v, list) do { \ 105 (v)->next = (list); \ 106 (list) = v; \ 107 } while (0) 108 109 #define SLLPopFreelist(list) list; do { \ 110 asan_unpoison_region((list), sizeof(*(list))); \ 111 (void)SLLPop((list)); \ 112 } while(0) 113 114 #define SLLPushFreelist(v, list) do { \ 115 SLLPush((v), (list)); \ 116 asan_poison_region((v), sizeof(*(v))); \ 117 } while(0) 118 119 #define DLLPushDown(v, list) do { \ 120 (v)->next = (list); \ 121 if ((v)->next) (v)->next->prev = (v); \ 122 (list) = (v); \ 123 } while (0) 124 125 #define DLLRemove(v) do { \ 126 if ((v)->next) (v)->next->prev = (v)->prev; \ 127 if ((v)->prev) (v)->prev->next = (v)->next; \ 128 } while (0) 129 130 #define KB(a) ((u64)(a) << 10ULL) 131 #define MB(a) ((u64)(a) << 20ULL) 132 #define GB(a) ((u64)(a) << 30ULL) 133 134 #define I32_MAX (0x7FFFFFFFL) 135 #define U16_MAX (0x0000FFFFUL) 136 #define U32_MAX (0xFFFFFFFFUL) 137 #define F32_INFINITY (1e+300*1e+300) 138 #define F32_EPSILON (1e-6f) 139 #ifndef PI 140 #define PI (3.14159265358979323846f) 141 #endif 142 143 typedef char c8; 144 typedef uint8_t u8; 145 typedef int16_t i16; 146 typedef uint16_t u16; 147 typedef uint16_t b16; 148 typedef int32_t i32; 149 typedef uint32_t u32; 150 typedef int64_t i64; 151 typedef uint64_t u64; 152 typedef uint32_t b32; 153 typedef float f32; 154 typedef double f64; 155 typedef ptrdiff_t iz; 156 typedef size_t uz; 157 typedef ptrdiff_t iptr; 158 typedef size_t uptr; 159 160 #include "intrinsics.c" 161 162 typedef union { 163 u8 U8[16]; 164 u16 U16[8]; 165 u32 U32[4]; 166 u64 U64[2]; 167 u32x4 U32x4; 168 } u128; 169 170 typedef struct { u8 *beg, *end; } Arena; 171 typedef struct { Arena *arena; u8 *old_beg; } TempArena; 172 173 typedef struct { iz len; u8 *data; } s8; 174 #define s8(s) (s8){.len = countof(s) - 1, .data = (u8 *)s} 175 #define s8_comp(s) {sizeof(s) - 1, (u8 *)s} 176 177 typedef struct { iz len; u16 *data; } s16; 178 179 typedef struct { u32 cp, consumed; } UnicodeDecode; 180 181 /* NOTE: raylib stubs */ 182 #ifndef RAYLIB_H 183 typedef struct { f32 x, y; } Vector2; 184 typedef struct { f32 x, y, w, h; } Rectangle; 185 #endif 186 187 typedef union { 188 struct { i32 x, y; }; 189 struct { i32 w, h; }; 190 i32 E[2]; 191 } iv2; 192 193 typedef union { 194 struct { i32 x, y, z; }; 195 struct { i32 w, h, d; }; 196 iv2 xy; 197 i32 E[3]; 198 } iv3; 199 200 typedef union { 201 struct { u32 x, y; }; 202 struct { u32 w, h; }; 203 u32 E[2]; 204 } uv2; 205 206 typedef union { 207 struct { u32 x, y, z; }; 208 struct { u32 w, h, d; }; 209 uv2 xy; 210 u32 E[3]; 211 } uv3; 212 213 typedef union { 214 struct { u32 x, y, z, w; }; 215 struct { uv3 xyz; u32 _w; }; 216 u32 E[4]; 217 } uv4; 218 219 typedef union { 220 struct { f32 x, y; }; 221 struct { f32 w, h; }; 222 Vector2 rl; 223 f32 E[2]; 224 } v2; 225 226 typedef union { 227 struct { f32 x, y, z; }; 228 struct { f32 w, h, d; }; 229 f32 E[3]; 230 } v3; 231 232 typedef union { 233 struct { f32 x, y, z, w; }; 234 struct { f32 r, g, b, a; }; 235 struct { v3 xyz; f32 _1; }; 236 struct { f32 _2; v3 yzw; }; 237 struct { v2 xy, zw; }; 238 f32 E[4]; 239 } v4; 240 241 #define XZ(v) (v2){.x = v.x, .y = v.z} 242 #define YZ(v) (v2){.x = v.y, .y = v.z} 243 #define XY(v) (v2){.x = v.x, .y = v.y} 244 245 typedef union { 246 struct { v4 x, y, z, w; }; 247 v4 c[4]; 248 f32 E[16]; 249 } m4; 250 251 /* TODO(rnp): delete raylib */ 252 typedef struct { 253 v3 origin; 254 v3 direction; 255 } ray; 256 257 typedef union { 258 struct { v2 pos, size; }; 259 Rectangle rl; 260 } Rect; 261 #define INVERTED_INFINITY_RECT (Rect){.pos = {.x = -F32_INFINITY, .y = -F32_INFINITY}, \ 262 .size = {.x = -F32_INFINITY, .y = -F32_INFINITY}} 263 264 typedef struct { 265 u8 *data; 266 i32 widx; 267 i32 cap; 268 b32 errors; 269 } Stream; 270 271 #define INVALID_FILE (-1) 272 273 typedef struct OS OS; 274 275 typedef struct { 276 Arena arena; 277 iptr handle; 278 iptr window_handle; 279 iptr gl_context; 280 iptr user_context; 281 i32 sync_variable; 282 b32 asleep; 283 } GLWorkerThreadContext; 284 285 #define FILE_WATCH_CALLBACK_FN(name) b32 name(OS *os, s8 path, iptr user_data, Arena arena) 286 typedef FILE_WATCH_CALLBACK_FN(file_watch_callback); 287 288 typedef struct { 289 iptr user_data; 290 u64 hash; 291 file_watch_callback *callback; 292 } FileWatch; 293 294 typedef struct { 295 u64 hash; 296 iptr handle; 297 s8 name; 298 299 FileWatch *data; 300 iz count; 301 iz capacity; 302 Arena buffer; 303 } FileWatchDirectory; 304 305 typedef struct { 306 FileWatchDirectory *data; 307 iz count; 308 iz capacity; 309 iptr handle; 310 } FileWatchContext; 311 312 typedef struct { 313 void *region; 314 iptr os_context; 315 } SharedMemoryRegion; 316 317 #define OS_ALLOC_ARENA_FN(name) Arena name(iz capacity) 318 typedef OS_ALLOC_ARENA_FN(os_alloc_arena_fn); 319 320 #define OS_ADD_FILE_WATCH_FN(name) void name(OS *os, Arena *a, s8 path, \ 321 file_watch_callback *callback, iptr user_data) 322 typedef OS_ADD_FILE_WATCH_FN(os_add_file_watch_fn); 323 324 #define OS_WAKE_WORKER_FN(name) void name(GLWorkerThreadContext *ctx) 325 typedef OS_WAKE_WORKER_FN(os_wake_worker_fn); 326 327 #define OS_READ_WHOLE_FILE_FN(name) s8 name(Arena *arena, char *file) 328 typedef OS_READ_WHOLE_FILE_FN(os_read_whole_file_fn); 329 330 #define OS_WAIT_ON_VALUE_FN(name) b32 name(i32 *value, i32 current, u32 timeout_ms) 331 typedef OS_WAIT_ON_VALUE_FN(os_wait_on_value_fn); 332 333 #define OS_WAKE_WAITERS_FN(name) void name(i32 *sync) 334 typedef OS_WAKE_WAITERS_FN(os_wake_waiters_fn); 335 336 #define OS_WRITE_NEW_FILE_FN(name) b32 name(char *fname, s8 raw) 337 typedef OS_WRITE_NEW_FILE_FN(os_write_new_file_fn); 338 339 #define OS_WRITE_FILE_FN(name) b32 name(iptr file, s8 raw) 340 typedef OS_WRITE_FILE_FN(os_write_file_fn); 341 342 #define OS_THREAD_ENTRY_POINT_FN(name) iptr name(iptr _ctx) 343 typedef OS_THREAD_ENTRY_POINT_FN(os_thread_entry_point_fn); 344 345 #define OS_SHARED_MEMORY_LOCK_REGION_FN(name) b32 name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index, u32 timeout_ms) 346 typedef OS_SHARED_MEMORY_LOCK_REGION_FN(os_shared_memory_region_lock_fn); 347 348 #define OS_SHARED_MEMORY_UNLOCK_REGION_FN(name) void name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index) 349 typedef OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock_fn); 350 351 #define RENDERDOC_GET_API_FN(name) b32 name(u32 version, void **out_api) 352 typedef RENDERDOC_GET_API_FN(renderdoc_get_api_fn); 353 354 #define RENDERDOC_START_FRAME_CAPTURE_FN(name) void name(iptr gl_context, iptr window_handle) 355 typedef RENDERDOC_START_FRAME_CAPTURE_FN(renderdoc_start_frame_capture_fn); 356 357 #define RENDERDOC_END_FRAME_CAPTURE_FN(name) b32 name(iptr gl_context, iptr window_handle) 358 typedef RENDERDOC_END_FRAME_CAPTURE_FN(renderdoc_end_frame_capture_fn); 359 360 typedef alignas(16) u8 RenderDocAPI[216]; 361 #define RENDERDOC_API_FN_ADDR(a, offset) (*(iptr *)((*a) + offset)) 362 #define RENDERDOC_START_FRAME_CAPTURE(a) (renderdoc_start_frame_capture_fn *)RENDERDOC_API_FN_ADDR(a, 152) 363 #define RENDERDOC_END_FRAME_CAPTURE(a) (renderdoc_end_frame_capture_fn *) RENDERDOC_API_FN_ADDR(a, 168) 364 365 struct OS { 366 FileWatchContext file_watch_context; 367 iptr context; 368 iptr error_handle; 369 s8 path_separator; 370 371 GLWorkerThreadContext compute_worker; 372 GLWorkerThreadContext upload_worker; 373 374 DEBUG_DECL(renderdoc_start_frame_capture_fn *start_frame_capture;) 375 DEBUG_DECL(renderdoc_end_frame_capture_fn *end_frame_capture;) 376 }; 377 378 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, (i32)_s.len, (c8 *)_s.data);} 379 380 #include "util.c" 381 #include "math.c" 382 383 #endif /* _UTIL_H_ */