util.h (10214B)
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 struct { u8 *beg, *end; } Arena; 163 typedef struct { Arena *arena; u8 *old_beg; } TempArena; 164 165 typedef struct { iz len; u8 *data; } s8; 166 #define s8(s) (s8){.len = countof(s) - 1, .data = (u8 *)s} 167 #define s8_comp(s) {sizeof(s) - 1, (u8 *)s} 168 169 typedef struct { iz len; u16 *data; } s16; 170 171 typedef struct { u32 cp, consumed; } UnicodeDecode; 172 173 /* NOTE: raylib stubs */ 174 #ifndef RAYLIB_H 175 typedef struct { f32 x, y; } Vector2; 176 typedef struct { f32 x, y, w, h; } Rectangle; 177 #endif 178 179 typedef union { 180 struct { i32 x, y; }; 181 struct { i32 w, h; }; 182 i32 E[2]; 183 } iv2; 184 185 typedef union { 186 struct { i32 x, y, z; }; 187 struct { i32 w, h, d; }; 188 iv2 xy; 189 i32 E[3]; 190 } iv3; 191 192 typedef union { 193 struct { u32 x, y; }; 194 struct { u32 w, h; }; 195 u32 E[2]; 196 } uv2; 197 198 typedef union { 199 struct { u32 x, y, z; }; 200 struct { u32 w, h, d; }; 201 uv2 xy; 202 u32 E[3]; 203 } uv3; 204 205 typedef union { 206 struct { u32 x, y, z, w; }; 207 struct { uv3 xyz; u32 _w; }; 208 u32 E[4]; 209 } uv4; 210 211 typedef union { 212 struct { f32 x, y; }; 213 struct { f32 w, h; }; 214 Vector2 rl; 215 f32 E[2]; 216 } v2; 217 218 typedef union { 219 struct { f32 x, y, z; }; 220 struct { f32 w, h, d; }; 221 f32 E[3]; 222 } v3; 223 224 typedef union { 225 struct { f32 x, y, z, w; }; 226 struct { f32 r, g, b, a; }; 227 struct { v3 xyz; f32 _1; }; 228 struct { f32 _2; v3 yzw; }; 229 struct { v2 xy, zw; }; 230 f32 E[4]; 231 } v4; 232 233 #define XZ(v) (v2){.x = v.x, .y = v.z} 234 #define YZ(v) (v2){.x = v.y, .y = v.z} 235 #define XY(v) (v2){.x = v.x, .y = v.y} 236 237 typedef union { 238 struct { v4 x, y, z, w; }; 239 v4 c[4]; 240 f32 E[16]; 241 } m4; 242 243 /* TODO(rnp): delete raylib */ 244 typedef struct { 245 v3 origin; 246 v3 direction; 247 } ray; 248 249 typedef union { 250 struct { v2 pos, size; }; 251 Rectangle rl; 252 } Rect; 253 #define INVERTED_INFINITY_RECT (Rect){.pos = {.x = -F32_INFINITY, .y = -F32_INFINITY}, \ 254 .size = {.x = -F32_INFINITY, .y = -F32_INFINITY}} 255 256 typedef struct { 257 u8 *data; 258 i32 widx; 259 i32 cap; 260 b32 errors; 261 } Stream; 262 263 #define INVALID_FILE (-1) 264 265 typedef struct OS OS; 266 267 typedef struct { 268 Arena arena; 269 iptr handle; 270 iptr window_handle; 271 iptr gl_context; 272 iptr user_context; 273 i32 sync_variable; 274 b32 asleep; 275 } GLWorkerThreadContext; 276 277 #define FILE_WATCH_CALLBACK_FN(name) b32 name(OS *os, s8 path, iptr user_data, Arena arena) 278 typedef FILE_WATCH_CALLBACK_FN(file_watch_callback); 279 280 typedef struct { 281 iptr user_data; 282 u64 hash; 283 file_watch_callback *callback; 284 } FileWatch; 285 286 typedef struct { 287 u64 hash; 288 iptr handle; 289 s8 name; 290 291 FileWatch *data; 292 iz count; 293 iz capacity; 294 Arena buffer; 295 } FileWatchDirectory; 296 297 typedef struct { 298 FileWatchDirectory *data; 299 iz count; 300 iz capacity; 301 iptr handle; 302 } FileWatchContext; 303 304 typedef struct { 305 void *region; 306 iptr os_context; 307 } SharedMemoryRegion; 308 309 #define OS_ALLOC_ARENA_FN(name) Arena name(iz capacity) 310 typedef OS_ALLOC_ARENA_FN(os_alloc_arena_fn); 311 312 #define OS_ADD_FILE_WATCH_FN(name) void name(OS *os, Arena *a, s8 path, \ 313 file_watch_callback *callback, iptr user_data) 314 typedef OS_ADD_FILE_WATCH_FN(os_add_file_watch_fn); 315 316 #define OS_WAKE_WORKER_FN(name) void name(GLWorkerThreadContext *ctx) 317 typedef OS_WAKE_WORKER_FN(os_wake_worker_fn); 318 319 #define OS_READ_WHOLE_FILE_FN(name) s8 name(Arena *arena, char *file) 320 typedef OS_READ_WHOLE_FILE_FN(os_read_whole_file_fn); 321 322 #define OS_WAIT_ON_VALUE_FN(name) b32 name(i32 *value, i32 current, u32 timeout_ms) 323 typedef OS_WAIT_ON_VALUE_FN(os_wait_on_value_fn); 324 325 #define OS_WAKE_WAITERS_FN(name) void name(i32 *sync) 326 typedef OS_WAKE_WAITERS_FN(os_wake_waiters_fn); 327 328 #define OS_WRITE_NEW_FILE_FN(name) b32 name(char *fname, s8 raw) 329 typedef OS_WRITE_NEW_FILE_FN(os_write_new_file_fn); 330 331 #define OS_WRITE_FILE_FN(name) b32 name(iptr file, s8 raw) 332 typedef OS_WRITE_FILE_FN(os_write_file_fn); 333 334 #define OS_THREAD_ENTRY_POINT_FN(name) iptr name(iptr _ctx) 335 typedef OS_THREAD_ENTRY_POINT_FN(os_thread_entry_point_fn); 336 337 #define OS_SHARED_MEMORY_LOCK_REGION_FN(name) b32 name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index, u32 timeout_ms) 338 typedef OS_SHARED_MEMORY_LOCK_REGION_FN(os_shared_memory_region_lock_fn); 339 340 #define OS_SHARED_MEMORY_UNLOCK_REGION_FN(name) void name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index) 341 typedef OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock_fn); 342 343 #define RENDERDOC_GET_API_FN(name) b32 name(u32 version, void **out_api) 344 typedef RENDERDOC_GET_API_FN(renderdoc_get_api_fn); 345 346 #define RENDERDOC_START_FRAME_CAPTURE_FN(name) void name(iptr gl_context, iptr window_handle) 347 typedef RENDERDOC_START_FRAME_CAPTURE_FN(renderdoc_start_frame_capture_fn); 348 349 #define RENDERDOC_END_FRAME_CAPTURE_FN(name) b32 name(iptr gl_context, iptr window_handle) 350 typedef RENDERDOC_END_FRAME_CAPTURE_FN(renderdoc_end_frame_capture_fn); 351 352 typedef alignas(16) u8 RenderDocAPI[216]; 353 #define RENDERDOC_API_FN_ADDR(a, offset) (*(iptr *)((*a) + offset)) 354 #define RENDERDOC_START_FRAME_CAPTURE(a) (renderdoc_start_frame_capture_fn *)RENDERDOC_API_FN_ADDR(a, 152) 355 #define RENDERDOC_END_FRAME_CAPTURE(a) (renderdoc_end_frame_capture_fn *) RENDERDOC_API_FN_ADDR(a, 168) 356 357 struct OS { 358 FileWatchContext file_watch_context; 359 iptr context; 360 iptr error_handle; 361 s8 path_separator; 362 363 GLWorkerThreadContext compute_worker; 364 GLWorkerThreadContext upload_worker; 365 366 DEBUG_DECL(renderdoc_start_frame_capture_fn *start_frame_capture;) 367 DEBUG_DECL(renderdoc_end_frame_capture_fn *end_frame_capture;) 368 }; 369 370 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, (i32)_s.len, (c8 *)_s.data);} 371 372 #include "util.c" 373 #include "math.c" 374 375 #endif /* _UTIL_H_ */