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