platform layer refactor
This commit is contained in:
parent
7edf600db8
commit
e2ca90f6ad
2
build.c
2
build.c
@ -547,7 +547,7 @@ void OnBuild(StringList cli_args)
|
||||
"-Wno-switch-enum -Wno-assign-enum -Wno-switch-default "
|
||||
"-Wno-reserved-identifier -Wno-reserved-macro-identifier "
|
||||
"-Wno-missing-designated-field-initializers "
|
||||
"-Wno-unsafe-buffer-usage "
|
||||
"-Wno-unsafe-buffer-usage -Wno-visibility "
|
||||
"-Wno-c11-extensions -Wno-gnu-anonymous-struct -Wno-nested-anon-types ");
|
||||
|
||||
/* -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter */
|
||||
|
||||
@ -200,13 +200,13 @@ void P_AppStartup(String args_str)
|
||||
String logfile_path = string_cat(temp.arena, logfile_dir, logfile_name);
|
||||
P_MkDir(logfile_dir);
|
||||
|
||||
log_startup(logfile_path);
|
||||
logf_info("Start of logs");
|
||||
P_LogStartup(logfile_path);
|
||||
P_LogInfoF("Start of logs");
|
||||
arena_temp_end(temp);
|
||||
}
|
||||
logf_info("App started with args \"%F\" (%F parsed)", FMT_STR(args_str), FMT_UINT(args.count));
|
||||
P_LogInfoF("App started with args \"%F\" (%F parsed)", FMT_STR(args_str), FMT_UINT(args.count));
|
||||
for (struct app_arg *arg = args.first; arg; arg = arg->next) {
|
||||
logf_info("Parsed arg: key = \"%F\", value = \"%F\"", FMT_STR(arg->key), FMT_STR(arg->value));
|
||||
P_LogInfoF("Parsed arg: key = \"%F\", value = \"%F\"", FMT_STR(arg->key), FMT_STR(arg->value));
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -216,17 +216,17 @@ void P_AppStartup(String args_str)
|
||||
|
||||
P_WindowSettings window_settings = ZI;
|
||||
String settings_path = app_write_path_cat(temp.arena, settings_file_name);
|
||||
logf_info("Looking for settings file \"%F\"", FMT_STR(settings_path));
|
||||
P_LogInfoF("Looking for settings file \"%F\"", FMT_STR(settings_path));
|
||||
if (P_IsFile(settings_path)) {
|
||||
logf_info("Settings file found");
|
||||
P_LogInfoF("Settings file found");
|
||||
P_File settings_file = P_OpenFileRead(settings_path);
|
||||
String file_data = P_ReadFile(temp.arena, settings_file);
|
||||
P_CloseFIle(settings_file);
|
||||
logf_info("Deserializing settings file data: %F", FMT_STR(file_data));
|
||||
P_LogInfoF("Deserializing settings file data: %F", FMT_STR(file_data));
|
||||
String error = ZI;
|
||||
P_WindowSettings *res = settings_deserialize(temp.arena, file_data, &error);
|
||||
if (error.len > 0) {
|
||||
logf_info("Failed to load settings file with error - %F", FMT_STR(error));
|
||||
P_LogInfoF("Failed to load settings file with error - %F", FMT_STR(error));
|
||||
String msg = string_format(temp.arena,
|
||||
LIT(
|
||||
"Failed to loading settings file \"%F\":\n"
|
||||
@ -239,10 +239,10 @@ void P_AppStartup(String args_str)
|
||||
FMT_STR(error));
|
||||
P_Panic(msg);
|
||||
}
|
||||
logf_info("Settings file loaded successfully");
|
||||
P_LogInfoF("Settings file loaded successfully");
|
||||
window_settings = *res;
|
||||
} else {
|
||||
logf_info("Settings file not found, loading default");
|
||||
P_LogInfoF("Settings file not found, loading default");
|
||||
window_settings = default_window_settings(window);
|
||||
}
|
||||
string_copy_to_string(STRING_FROM_ARRAY(window_settings.title), LIT(WINDOW_TITLE));
|
||||
@ -285,13 +285,13 @@ void P_AppStartup(String args_str)
|
||||
|
||||
P_WindowSettings settings = P_GetWindowSettings(window);
|
||||
String str = settings_serialize(temp.arena, &settings);
|
||||
logf_info("Serialized window settings: %F", FMT_STR(str));
|
||||
P_LogInfoF("Serialized window settings: %F", FMT_STR(str));
|
||||
|
||||
logf_info("Writing settings file to path \"%F\"", FMT_STR(window_settings_path));
|
||||
P_LogInfoF("Writing settings file to path \"%F\"", FMT_STR(window_settings_path));
|
||||
P_File settings_file = P_OpenFileWrite(window_settings_path);
|
||||
P_WriteFile(settings_file, str);
|
||||
P_CloseFIle(settings_file);
|
||||
logf_info("Finished writing settings file");
|
||||
P_LogInfoF("Finished writing settings file");
|
||||
|
||||
arena_temp_end(temp);
|
||||
}
|
||||
@ -301,6 +301,6 @@ void P_AppStartup(String args_str)
|
||||
P_ReleaseWindow(window);
|
||||
#endif
|
||||
|
||||
//logf_info("Program exited normally");
|
||||
//P_LogInfoF("Program exited normally");
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
typedef struct Ase_Error Ase_Error;
|
||||
struct Ase_Error {
|
||||
Struct(Ase_Error) {
|
||||
String msg;
|
||||
Ase_Error *next;
|
||||
};
|
||||
|
||||
typedef struct Ase_ErrorList Ase_ErrorList;
|
||||
struct Ase_ErrorList {
|
||||
Struct(Ase_ErrorList) {
|
||||
u64 count;
|
||||
Ase_Error *first;
|
||||
Ase_Error *last;
|
||||
};
|
||||
|
||||
typedef struct Ase_Slice Ase_Slice;
|
||||
struct Ase_Slice {
|
||||
Struct(Ase_Slice) {
|
||||
u32 start;
|
||||
i32 x1;
|
||||
i32 y1;
|
||||
@ -21,24 +18,21 @@ struct Ase_Slice {
|
||||
Ase_Slice *next;
|
||||
};
|
||||
|
||||
typedef struct Ase_SliceKey Ase_SliceKey;
|
||||
struct Ase_SliceKey {
|
||||
Struct(Ase_SliceKey) {
|
||||
String name;
|
||||
u32 num_slices;
|
||||
Ase_Slice *slice_head;
|
||||
Ase_SliceKey *next;
|
||||
};
|
||||
|
||||
typedef struct Ase_Span Ase_Span;
|
||||
struct Ase_Span {
|
||||
Struct(Ase_Span) {
|
||||
String name;
|
||||
u32 start;
|
||||
u32 end;
|
||||
Ase_Span *next;
|
||||
};
|
||||
|
||||
typedef struct Ase_Frame Ase_Frame;
|
||||
struct Ase_Frame {
|
||||
Struct(Ase_Frame) {
|
||||
u32 index;
|
||||
u32 x1;
|
||||
u32 y1;
|
||||
@ -48,15 +42,13 @@ struct Ase_Frame {
|
||||
Ase_Frame *next;
|
||||
};
|
||||
|
||||
typedef struct Ase_DecodedImage Ase_DecodedImage;
|
||||
struct Ase_DecodedImage {
|
||||
Struct(Ase_DecodedImage) {
|
||||
ImageDataRgba image;
|
||||
Ase_ErrorList errors;
|
||||
b32 success;
|
||||
};
|
||||
|
||||
typedef struct Ase_DecodedSheet Ase_DecodedSheet;
|
||||
struct Ase_DecodedSheet {
|
||||
Struct(Ase_DecodedSheet) {
|
||||
V2 image_size;
|
||||
V2 frame_size;
|
||||
u32 num_frames;
|
||||
|
||||
@ -40,7 +40,7 @@ AC_StartupReceipt asset_cache_startup(void)
|
||||
INTERNAL void refresh_dbg_table(void)
|
||||
{
|
||||
#if RTC
|
||||
P_Lock lock = snc_lock_e(&G.dbg_table_mutex);
|
||||
P_Lock lock = P_LockE(&G.dbg_table_mutex);
|
||||
MEMZERO_ARRAY(G.dbg_table);
|
||||
G.dbg_table_count = 0;
|
||||
for (u64 i = 0; i < countof(G.lookup); ++i) {
|
||||
@ -49,7 +49,7 @@ INTERNAL void refresh_dbg_table(void)
|
||||
G.dbg_table[G.dbg_table_count++] = asset;
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ INTERNAL void refresh_dbg_table(void)
|
||||
* Check returned slot->hash != 0 for presence. */
|
||||
INTERNAL AC_Asset *asset_cache_get_slot_locked(P_Lock *lock, String key, u64 hash)
|
||||
{
|
||||
snc_assert_locked_e_or_s(lock, &G.lookup_mutex);
|
||||
P_AssertLockedES(lock, &G.lookup_mutex);
|
||||
(UNUSED)lock;
|
||||
|
||||
u64 index = hash % countof(G.lookup);
|
||||
@ -101,9 +101,9 @@ AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch)
|
||||
|
||||
/* Lookup */
|
||||
{
|
||||
P_Lock lock = snc_lock_s(&G.lookup_mutex);
|
||||
P_Lock lock = P_LockS(&G.lookup_mutex);
|
||||
asset = asset_cache_get_slot_locked(&lock, key, hash);
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Insert if not found */
|
||||
@ -112,7 +112,7 @@ AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch)
|
||||
*is_first_touch = 0;
|
||||
}
|
||||
} else {
|
||||
P_Lock lock = snc_lock_e(&G.lookup_mutex);
|
||||
P_Lock lock = P_LockE(&G.lookup_mutex);
|
||||
|
||||
/* Re-check asset presence in case it was inserted since lock */
|
||||
asset = asset_cache_get_slot_locked(&lock, key, hash);
|
||||
@ -129,13 +129,13 @@ AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch)
|
||||
asset_cache_store_close(&store);
|
||||
}
|
||||
/* Initialize asset data */
|
||||
logf_info("Inserting asset cache entry for \"%F\"", FMT_STR(key));
|
||||
P_LogInfoF("Inserting asset cache entry for \"%F\"", FMT_STR(key));
|
||||
*asset = (AC_Asset) {
|
||||
.status = ASSET_STATUS_UNINITIALIZED,
|
||||
.hash = hash,
|
||||
.key = key_stored
|
||||
};
|
||||
snc_counter_add(&asset->counter, 1);
|
||||
P_CounterAdd(&asset->counter, 1);
|
||||
if (is_first_touch) {
|
||||
*is_first_touch = 1;
|
||||
}
|
||||
@ -144,7 +144,7 @@ AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch)
|
||||
refresh_dbg_table();
|
||||
}
|
||||
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
return asset;
|
||||
@ -165,7 +165,7 @@ void asset_cache_mark_ready(AC_Asset *asset, void *store_data)
|
||||
{
|
||||
asset->store_data = store_data;
|
||||
asset->status = ASSET_STATUS_READY;
|
||||
snc_counter_add(&asset->counter, -1);
|
||||
P_CounterAdd(&asset->counter, -1);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -174,7 +174,7 @@ void asset_cache_mark_ready(AC_Asset *asset, void *store_data)
|
||||
|
||||
void asset_cache_wait(AC_Asset *asset)
|
||||
{
|
||||
snc_counter_wait(&asset->counter);
|
||||
P_WaitOnCounter(&asset->counter);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -196,7 +196,7 @@ void *asset_cache_get_store_data(AC_Asset *asset)
|
||||
/* Asset store should be opened to allocate memory to the store arena */
|
||||
AC_Store asset_cache_store_open(void)
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.store_mutex);
|
||||
P_Lock lock = P_LockE(&G.store_mutex);
|
||||
AC_Store store = {
|
||||
.lock = lock,
|
||||
.arena = G.store_arena
|
||||
@ -206,5 +206,5 @@ AC_Store asset_cache_store_open(void)
|
||||
|
||||
void asset_cache_store_close(AC_Store *store)
|
||||
{
|
||||
snc_unlock(&store->lock);
|
||||
P_Unlock(&store->lock);
|
||||
}
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
typedef enum AC_Status {
|
||||
typedef i32 AC_Status; enum {
|
||||
ASSET_STATUS_NONE,
|
||||
|
||||
ASSET_STATUS_UNINITIALIZED,
|
||||
/* TODO: ASSET_STATUS_QUEUED? */
|
||||
ASSET_STATUS_LOADING,
|
||||
ASSET_STATUS_READY
|
||||
} AC_Status;
|
||||
};
|
||||
|
||||
typedef struct AC_Asset AC_Asset;
|
||||
struct AC_Asset {
|
||||
Struct(AC_Asset) {
|
||||
/* Managed via asset_cache_touch */
|
||||
u64 hash;
|
||||
String key;
|
||||
@ -22,16 +21,14 @@ struct AC_Asset {
|
||||
void *store_data;
|
||||
};
|
||||
|
||||
typedef struct AC_Store AC_Store;
|
||||
struct AC_Store {
|
||||
Struct(AC_Store) {
|
||||
Arena *arena;
|
||||
|
||||
/* Internal */
|
||||
P_Lock lock;
|
||||
};
|
||||
|
||||
typedef struct AC_StartupReceipt AC_StartupReceipt;
|
||||
struct AC_StartupReceipt { i32 _; };
|
||||
Struct(AC_StartupReceipt) { i32 _; };
|
||||
AC_StartupReceipt asset_cache_startup(void);
|
||||
|
||||
AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch);
|
||||
|
||||
@ -18,8 +18,7 @@
|
||||
* Equivalent to arena_push but without actually allocating anything or modifying the arena. */
|
||||
#define arena_push_dry(a, type) (type *)(_arena_push_dry((a), alignof(type)))
|
||||
|
||||
typedef struct Arena Arena;
|
||||
struct Arena {
|
||||
Struct(Arena) {
|
||||
u64 pos;
|
||||
u64 committed;
|
||||
u64 reserved;
|
||||
@ -28,8 +27,7 @@ struct Arena {
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct TempArena TempArena;
|
||||
struct TempArena {
|
||||
Struct(TempArena) {
|
||||
Arena *arena;
|
||||
u64 start_pos;
|
||||
|
||||
@ -131,13 +129,11 @@ INLINE void *_arena_push_dry(Arena *arena, u64 align)
|
||||
|
||||
#define SCRATCH_ARENAS_PER_CTX 2
|
||||
|
||||
typedef struct ScratchCtx ScratchCtx;
|
||||
struct ScratchCtx {
|
||||
Struct(ScratchCtx) {
|
||||
Arena *arenas[SCRATCH_ARENAS_PER_CTX];
|
||||
};
|
||||
|
||||
typedef struct SharedScratchCtx SharedScratchCtx;
|
||||
struct SharedScratchCtx {
|
||||
Struct(SharedScratchCtx) {
|
||||
ScratchCtx scratch_contexts[MAX_FIBERS];
|
||||
};
|
||||
|
||||
|
||||
@ -3,24 +3,20 @@
|
||||
* ========================== */
|
||||
|
||||
/* NOTE: Must be aligned to 32 bit boundary by user */
|
||||
typedef struct Atomic8 Atomic8;
|
||||
struct Atomic8 {
|
||||
Struct(Atomic8) {
|
||||
volatile i8 _v;
|
||||
};
|
||||
|
||||
/* NOTE: Must be aligned to 32 bit boundary by user */
|
||||
typedef struct Atomic16 Atomic16;
|
||||
struct Atomic16 {
|
||||
Struct(Atomic16) {
|
||||
volatile i16 _v;
|
||||
};
|
||||
|
||||
typedef struct Atomic32 Atomic32;
|
||||
struct Atomic32 {
|
||||
Struct(Atomic32) {
|
||||
volatile i32 _v;
|
||||
};
|
||||
|
||||
typedef struct Atomic64 Atomic64;
|
||||
struct Atomic64 {
|
||||
Struct(Atomic64) {
|
||||
volatile i64 _v;
|
||||
};
|
||||
|
||||
@ -28,29 +24,25 @@ struct Atomic64 {
|
||||
* Cache-line isolated atomic types
|
||||
* ========================== */
|
||||
|
||||
typedef struct Atomic8Padded Atomic8Padded;
|
||||
struct alignas(64) Atomic8Padded {
|
||||
AlignedStruct(Atomic8Padded, 64) {
|
||||
Atomic8 v;
|
||||
u8 _pad[60];
|
||||
};
|
||||
STATIC_ASSERT(sizeof(Atomic8Padded) == 64 && alignof(Atomic8Padded) == 64);
|
||||
|
||||
typedef struct Atomic16Padded Atomic16Padded;
|
||||
struct alignas(64) Atomic16Padded {
|
||||
AlignedStruct(Atomic16Padded, 64) {
|
||||
Atomic16 v;
|
||||
u8 _pad[60];
|
||||
};
|
||||
STATIC_ASSERT(sizeof(Atomic16Padded) == 64 && alignof(Atomic16Padded) == 64);
|
||||
|
||||
typedef struct Atomic32Padded Atomic32Padded;
|
||||
struct alignas(64) Atomic32Padded {
|
||||
AlignedStruct(Atomic32Padded, 64) {
|
||||
Atomic32 v;
|
||||
u8 _pad[60];
|
||||
};
|
||||
STATIC_ASSERT(sizeof(Atomic32Padded) == 64 && alignof(Atomic32Padded) == 64);
|
||||
|
||||
typedef struct Atomic64Padded Atomic64Padded;
|
||||
struct alignas(64) Atomic64Padded {
|
||||
AlignedStruct(Atomic64Padded, 64) {
|
||||
Atomic64 v;
|
||||
u8 _pad[56];
|
||||
};
|
||||
|
||||
@ -2,8 +2,7 @@
|
||||
* Bitbuff
|
||||
* ========================== */
|
||||
|
||||
typedef struct Bitbuff Bitbuff;
|
||||
struct Bitbuff {
|
||||
Struct(Bitbuff) {
|
||||
b32 is_backed_by_arena;
|
||||
|
||||
/* If `is_arena_bitbuff` is 1, this dynamically-sized arena will be used for reading & writing (meaning writing cannot overflow) */
|
||||
@ -23,8 +22,7 @@ Bitbuff bitbuff_from_string(String s);
|
||||
* ========================== */
|
||||
|
||||
/* NOTE: base_len is not stored in writer (as it is in the reader) since a dynamic arena-backed bitbuff could grow meaning len needs to be re-checked */
|
||||
typedef struct BitbuffWriter BitbuffWriter;
|
||||
struct BitbuffWriter {
|
||||
Struct(BitbuffWriter) {
|
||||
b32 overflowed;
|
||||
Bitbuff *bb;
|
||||
u8 *base;
|
||||
@ -72,8 +70,7 @@ void bw_write_dbg_marker(BitbuffWriter *bw, String name);
|
||||
* Reader
|
||||
* ========================== */
|
||||
|
||||
typedef struct BitbuffReader BitbuffReader;
|
||||
struct BitbuffReader {
|
||||
Struct(BitbuffReader) {
|
||||
b32 overflowed;
|
||||
u64 base_len;
|
||||
u8 *base;
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
typedef struct BuddyLevel BuddyLevel;
|
||||
typedef struct BuddyBlock BuddyBlock;
|
||||
struct BuddyBlock {
|
||||
Struct(BuddyBlock) {
|
||||
b32 is_used;
|
||||
BuddyLevel *level;
|
||||
struct BuddyLevel *level;
|
||||
BuddyBlock *parent;
|
||||
BuddyBlock *sibling;
|
||||
|
||||
@ -13,18 +11,15 @@ struct BuddyBlock {
|
||||
u8 *memory;
|
||||
};
|
||||
|
||||
typedef struct BuddyCtx BuddyCtx;
|
||||
typedef struct BuddyLevel BuddyLevel;
|
||||
struct BuddyLevel {
|
||||
BuddyCtx *ctx;
|
||||
Struct(BuddyLevel) {
|
||||
struct BuddyCtx *ctx;
|
||||
b32 backed; /* Signals whether this level is backed by memory in the ctx arena */
|
||||
u32 tier;
|
||||
u64 size;
|
||||
BuddyBlock *first_unused_block;
|
||||
};
|
||||
|
||||
typedef struct BuddyCtx BuddyCtx;
|
||||
struct BuddyCtx {
|
||||
Struct(BuddyCtx) {
|
||||
Arena *meta_arena;
|
||||
Arena *data_arena;
|
||||
BuddyLevel *levels;
|
||||
|
||||
@ -365,19 +365,22 @@ GLOBAL const f64 *_f64_nan = (f64 *)&_f64_nan_u64;
|
||||
#define F32_IS_NAN(x) (x != x)
|
||||
#define F64_IS_NAN(x) (x != x)
|
||||
|
||||
#define Struct(name) typedef struct name name; struct name
|
||||
#define AlignedStruct(name, n) typedef struct name name; struct alignas(n) name
|
||||
|
||||
/* ========================== *
|
||||
* Common structs
|
||||
* ========================== */
|
||||
|
||||
typedef struct ImageDataRgba ImageDataRgba;
|
||||
struct ImageDataRgba {
|
||||
Struct(ImageDataRgba)
|
||||
{
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 *pixels; /* Array of [width * height] pixels */
|
||||
};
|
||||
|
||||
typedef struct PcmData PcmData;
|
||||
struct PcmData {
|
||||
Struct(PcmData)
|
||||
{
|
||||
u64 count;
|
||||
i16 *samples;
|
||||
};
|
||||
|
||||
@ -18,8 +18,7 @@ enum _incbin_state {
|
||||
INCBIN_STATE_SEARCHED
|
||||
};
|
||||
|
||||
typedef struct _IncbinRcResource _IncbinRcResource;
|
||||
struct _IncbinRcResource {
|
||||
Struct(_IncbinRcResource) {
|
||||
Atomic32 state;
|
||||
String rc_name;
|
||||
String data;
|
||||
|
||||
@ -9,62 +9,52 @@
|
||||
|
||||
#define V2FromXY(x, y) CPPCOMPAT_INITLIST_TYPE(V2) { (x), (y) }
|
||||
#define V2FromV2i32(v) V2FromXY((v).x, (v).y)
|
||||
typedef struct V2 V2;
|
||||
struct V2 {
|
||||
Struct(V2) {
|
||||
f32 x, y;
|
||||
};
|
||||
|
||||
typedef struct V2Array V2Array;
|
||||
struct V2Array {
|
||||
Struct(V2Array) {
|
||||
V2 *points;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
#define V3FromXYZ(x, y, z) ((V3) { (x), (y), (z) })
|
||||
typedef struct V3 V3;
|
||||
struct V3 {
|
||||
Struct(V3) {
|
||||
f32 x, y, z;
|
||||
};
|
||||
|
||||
typedef struct V3Array V3Array;
|
||||
struct V3Array {
|
||||
Struct(V3Array) {
|
||||
V3 *points;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
#define V4FromXYZW(x, y, z, w) ((V4) { (x), (y), (z), (w) })
|
||||
typedef struct V4 V4;
|
||||
struct V4 {
|
||||
Struct(V4) {
|
||||
f32 x, y, z, w;
|
||||
};
|
||||
|
||||
typedef struct V4Array V4Array;
|
||||
struct V4Array {
|
||||
Struct(V4Array) {
|
||||
V4 *points;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
#define V2i32FromXY(x, y) CPPCOMPAT_INITLIST_TYPE(V2i32) { (x), (y) }
|
||||
typedef struct V2i32 V2i32;
|
||||
struct V2i32 {
|
||||
Struct(V2i32) {
|
||||
i32 x, y;
|
||||
};
|
||||
|
||||
#define V3i32FromXYZ(x, y, z) CPPCOMPAT_INITLIST_TYPE(V3i32) { (x), (y), (z) }
|
||||
typedef struct V3i32 V3i32;
|
||||
struct V3i32 {
|
||||
Struct(V3i32) {
|
||||
i32 x, y, z;
|
||||
};
|
||||
|
||||
typedef struct Xform Xform;
|
||||
struct Xform {
|
||||
Struct(Xform) {
|
||||
V2 bx; /* X basis vector (x axis) */
|
||||
V2 by; /* Y basis vector (y axis)*/
|
||||
V2 og; /* Translation vector (origin) */
|
||||
};
|
||||
|
||||
typedef struct Mat4x4 Mat4x4;
|
||||
struct Mat4x4 {
|
||||
Struct(Mat4x4) {
|
||||
union {
|
||||
struct { V4 bx, by, bz, bw; };
|
||||
f32 e[4][4];
|
||||
@ -73,8 +63,7 @@ struct Mat4x4 {
|
||||
|
||||
#define RECT(_x, _y, _width, _height) (Rect) { .x = (_x), .y = (_y), .width = (_width), .height = (_height) }
|
||||
#define RECT_FROM_V2(_pos, _size) (Rect) { .pos = (_pos), .size = (_size) }
|
||||
typedef struct Rect Rect;
|
||||
struct Rect {
|
||||
Struct(Rect) {
|
||||
union {
|
||||
struct { f32 x, y, width, height; };
|
||||
struct { V2 pos, size; };
|
||||
@ -83,22 +72,19 @@ struct Rect {
|
||||
|
||||
INLINE b32 rect_eq(Rect r1, Rect r2) { return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height == r2.height; }
|
||||
|
||||
typedef struct Aabb Aabb;
|
||||
struct Aabb {
|
||||
Struct(Aabb) {
|
||||
V2 p0, p1;
|
||||
};
|
||||
|
||||
/* Values expected to be normalized 0.0 -> 1.0 */
|
||||
#define CLIP_ALL ((ClipRect) { { 0.0f, 0.0f }, { 1.0f, 1.0f } })
|
||||
typedef struct ClipRect ClipRect;
|
||||
struct ClipRect {
|
||||
Struct(ClipRect) {
|
||||
V2 p0, p1;
|
||||
};
|
||||
|
||||
#define QUAD_UNIT_SQUARE (Quad) { .p0 = V2FromXY(0, 0), .p1 = V2FromXY(0, 1), .p2 = V2FromXY(1, 1), .p3 = V2FromXY(1, 0) }
|
||||
#define QUAD_UNIT_SQUARE_CENTERED (Quad) { .p0 = V2FromXY(-0.5f, -0.5f), .p1 = V2FromXY(0.5f, -0.5f), .p2 = V2FromXY(0.5f, 0.5f), .p3 = V2FromXY(-0.5f, 0.5f) }
|
||||
typedef struct Quad Quad;
|
||||
struct Quad {
|
||||
Struct(Quad) {
|
||||
union {
|
||||
struct { V2 p0, p1, p2, p3; };
|
||||
struct { V2 e[4]; };
|
||||
@ -107,8 +93,7 @@ struct Quad {
|
||||
|
||||
/* (T)ranslation, (R)otation, (S)cale */
|
||||
#define MakeTrs(...) ((Trs) { .t = V2FromXY(0,0), .s = V2FromXY(1, 1), .r = 0, __VA_ARGS__ })
|
||||
typedef struct Trs Trs;
|
||||
struct Trs {
|
||||
Struct(Trs) {
|
||||
V2 t;
|
||||
V2 s;
|
||||
f32 r;
|
||||
@ -1397,8 +1382,7 @@ INLINE V2 math_poly_center(V2Array a)
|
||||
* ========================== */
|
||||
|
||||
/* https://box2d.org/files/ErinCatto_SoftConstraints_GDC2011.pdf */
|
||||
typedef struct SoftSpring SoftSpring;
|
||||
struct SoftSpring {
|
||||
Struct(SoftSpring) {
|
||||
f32 bias_rate;
|
||||
f32 mass_scale;
|
||||
f32 impulse_scale;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
typedef struct RandState RandState;
|
||||
struct RandState {
|
||||
Struct(RandState) {
|
||||
/* If a state's seed == 0 upon a call to a related function, it will be initialized using platform's true rng source */
|
||||
u64 seed;
|
||||
u64 counter;
|
||||
|
||||
@ -1,23 +1,19 @@
|
||||
typedef struct String String;
|
||||
struct String {
|
||||
Struct(String) {
|
||||
u64 len;
|
||||
u8 *text;
|
||||
};
|
||||
|
||||
typedef struct String16 String16;
|
||||
struct String16 {
|
||||
Struct(String16) {
|
||||
u64 len;
|
||||
u16 *text;
|
||||
};
|
||||
|
||||
typedef struct String32 String32;
|
||||
struct String32 {
|
||||
Struct(String32) {
|
||||
u64 len;
|
||||
u32 *text;
|
||||
};
|
||||
|
||||
typedef struct StringArray StringArray;
|
||||
struct StringArray {
|
||||
Struct(StringArray) {
|
||||
u64 count;
|
||||
String *strings;
|
||||
};
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#define MakeUID(hi64, lo64) ((UID) { .hi = (hi64), .lo = (lo64) })
|
||||
typedef struct UID UID;
|
||||
struct UID {
|
||||
Struct(UID) {
|
||||
u64 hi;
|
||||
u64 lo;
|
||||
};
|
||||
|
||||
@ -2,14 +2,12 @@
|
||||
* utf8
|
||||
* ========================== */
|
||||
|
||||
typedef struct Utf8DecodeResult Utf8DecodeResult;
|
||||
struct Utf8DecodeResult {
|
||||
Struct(Utf8DecodeResult) {
|
||||
u32 advance8;
|
||||
u32 codepoint;
|
||||
};
|
||||
|
||||
typedef struct Utf8EncodeResult Utf8EncodeResult;
|
||||
struct Utf8EncodeResult {
|
||||
Struct(Utf8EncodeResult) {
|
||||
u32 count8;
|
||||
u8 chars8[4];
|
||||
};
|
||||
@ -21,14 +19,12 @@ Utf8EncodeResult uni_encode_utf8(u32 codepoint);
|
||||
* utf16
|
||||
* ========================== */
|
||||
|
||||
typedef struct Utf16DecodeResult Utf16DecodeResult;
|
||||
struct Utf16DecodeResult {
|
||||
Struct(Utf16DecodeResult) {
|
||||
u32 advance16;
|
||||
u32 codepoint;
|
||||
};
|
||||
|
||||
typedef struct Utf16EncodeResult Utf16EncodeResult;
|
||||
struct Utf16EncodeResult {
|
||||
Struct(Utf16EncodeResult) {
|
||||
u32 count16;
|
||||
u16 chars16[2];
|
||||
};
|
||||
@ -42,14 +38,12 @@ b32 uni_is_utf16_low_surrogate(u16 c);
|
||||
* utf32
|
||||
* ========================== */
|
||||
|
||||
typedef struct Utf32DecodeResult Utf32DecodeResult;
|
||||
struct Utf32DecodeResult {
|
||||
Struct(Utf32DecodeResult) {
|
||||
u32 advance32;
|
||||
u32 codepoint;
|
||||
};
|
||||
|
||||
typedef struct Utf32EncodeResult Utf32EncodeResult;
|
||||
struct Utf32EncodeResult {
|
||||
Struct(Utf32EncodeResult) {
|
||||
u32 chars32;
|
||||
};
|
||||
|
||||
|
||||
@ -94,8 +94,7 @@ INLINE void merge_sort(void *items, u64 item_count, u64 item_size, sort_compare_
|
||||
* Simple chaining hash -> 64 bit value table for generic use
|
||||
* ========================== */
|
||||
|
||||
typedef struct DictEntry DictEntry;
|
||||
struct DictEntry {
|
||||
Struct(DictEntry) {
|
||||
u64 hash;
|
||||
u64 value;
|
||||
DictEntry *prev_in_bin;
|
||||
@ -104,14 +103,12 @@ struct DictEntry {
|
||||
DictEntry *next;
|
||||
};
|
||||
|
||||
typedef struct DictBin DictBin;
|
||||
struct DictBin {
|
||||
Struct(DictBin) {
|
||||
DictEntry *first;
|
||||
DictEntry *last;
|
||||
};
|
||||
|
||||
typedef struct Dict Dict;
|
||||
struct Dict {
|
||||
Struct(Dict) {
|
||||
u64 bins_count;
|
||||
DictBin *bins;
|
||||
DictEntry *first_free;
|
||||
|
||||
@ -1,50 +1,42 @@
|
||||
typedef struct CLD_Shape CLD_Shape;
|
||||
struct CLD_Shape {
|
||||
Struct(CLD_Shape) {
|
||||
V2 points[8];
|
||||
u32 count;
|
||||
f32 radius;
|
||||
};
|
||||
|
||||
typedef struct CLD_SupportPoint CLD_SupportPoint;
|
||||
struct CLD_SupportPoint {
|
||||
Struct(CLD_SupportPoint) {
|
||||
V2 p;
|
||||
u32 i; /* Index of original point in shape */
|
||||
};
|
||||
|
||||
typedef struct CLD_MenkowskiPoint CLD_MenkowskiPoint;
|
||||
struct CLD_MenkowskiPoint {
|
||||
Struct(CLD_MenkowskiPoint) {
|
||||
V2 p; /* Menkowski difference point */
|
||||
CLD_SupportPoint s0; /* Support point of first shape in dir */
|
||||
CLD_SupportPoint s1; /* Support point of second shape in -dir */
|
||||
};
|
||||
|
||||
typedef struct CLD_MenkowskiSimplex CLD_MenkowskiSimplex;
|
||||
struct CLD_MenkowskiSimplex {
|
||||
Struct(CLD_MenkowskiSimplex) {
|
||||
u32 len;
|
||||
CLD_MenkowskiPoint a, b, c;
|
||||
};
|
||||
|
||||
typedef struct CLD_MenkowskiFeature CLD_MenkowskiFeature;
|
||||
struct CLD_MenkowskiFeature {
|
||||
Struct(CLD_MenkowskiFeature) {
|
||||
u32 len;
|
||||
CLD_MenkowskiPoint a, b;
|
||||
};
|
||||
|
||||
typedef struct CLD_CollisionPoint CLD_CollisionPoint;
|
||||
struct CLD_CollisionPoint {
|
||||
Struct(CLD_CollisionPoint) {
|
||||
V2 point;
|
||||
f32 separation;
|
||||
u32 id; /* Based on polygon edge-to-edge */
|
||||
};
|
||||
|
||||
typedef struct CLD_Prototype CLD_Prototype;
|
||||
struct CLD_Prototype {
|
||||
Struct(CLD_Prototype) {
|
||||
V2 points[64];
|
||||
u32 len;
|
||||
};
|
||||
|
||||
typedef struct CLD_CollisionResult CLD_CollisionResult;
|
||||
struct CLD_CollisionResult {
|
||||
Struct(CLD_CollisionResult) {
|
||||
V2 normal;
|
||||
CLD_CollisionPoint points[2];
|
||||
u32 num_points;
|
||||
@ -59,8 +51,7 @@ struct CLD_CollisionResult {
|
||||
V2 a0_clipped, b0_clipped, a1_clipped, b1_clipped;
|
||||
};
|
||||
|
||||
typedef struct CLD_ClosestResult CLD_ClosestResult;
|
||||
struct CLD_ClosestResult {
|
||||
Struct(CLD_ClosestResult) {
|
||||
V2 p0, p1;
|
||||
b32 colliding;
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
typedef struct D_StartupReceipt D_StartupReceipt;
|
||||
struct D_StartupReceipt { i32 _; };
|
||||
Struct(D_StartupReceipt) { i32 _; };
|
||||
D_StartupReceipt draw_startup(F_StartupReceipt *font_sr);
|
||||
|
||||
/* ========================== *
|
||||
@ -12,8 +11,7 @@ D_StartupReceipt draw_startup(F_StartupReceipt *font_sr);
|
||||
__VA_ARGS__ \
|
||||
})
|
||||
|
||||
typedef struct D_MaterialParams D_MaterialParams;
|
||||
struct D_MaterialParams {
|
||||
Struct(D_MaterialParams) {
|
||||
Xform xf;
|
||||
G_Resource *texture;
|
||||
ClipRect clip;
|
||||
@ -74,8 +72,7 @@ void draw_grid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 lin
|
||||
__VA_ARGS__ \
|
||||
})
|
||||
|
||||
typedef struct D_UiRectParams D_UiRectParams;
|
||||
struct D_UiRectParams {
|
||||
Struct(D_UiRectParams) {
|
||||
Xform xf;
|
||||
G_Resource *texture;
|
||||
ClipRect clip;
|
||||
@ -98,29 +95,28 @@ void draw_ui_rect(G_RenderSig *sig, D_UiRectParams params);
|
||||
})
|
||||
|
||||
/* How is text aligned within its area */
|
||||
typedef enum D_TextAlignment {
|
||||
typedef i32 D_TextAlignment; enum {
|
||||
DRAW_TEXT_ALIGNMENT_LEFT, /* Default */
|
||||
DRAW_TEXT_ALIGNMENT_CENTER,
|
||||
DRAW_TEXT_ALIGNMENT_RIGHT
|
||||
} D_TextAlignment;
|
||||
};
|
||||
|
||||
/* How does the specified text position relate to the text area.
|
||||
* E.g. BOTTOM & RIGHT means the bottom-right of the text area will snap to
|
||||
* the specified position. */
|
||||
typedef enum D_TextOffsetX {
|
||||
typedef i32 D_TextOffsetX; enum {
|
||||
DRAW_TEXT_OFFSET_X_LEFT, /* Default */
|
||||
DRAW_TEXT_OFFSET_X_CENTER,
|
||||
DRAW_TEXT_OFFSET_X_RIGHT
|
||||
} D_TextOffsetX;
|
||||
};
|
||||
|
||||
typedef enum D_TextOffsetY {
|
||||
typedef i32 D_TextOffsetY; enum {
|
||||
DRAW_TEXT_OFFSET_Y_TOP, /* Default */
|
||||
DRAW_TEXT_OFFSET_Y_CENTER,
|
||||
DRAW_TEXT_OFFSET_Y_BOTTOM
|
||||
} D_TextOffsetY;
|
||||
};
|
||||
|
||||
typedef struct D_TextParams D_TextParams;
|
||||
struct D_TextParams {
|
||||
Struct(D_TextParams) {
|
||||
F_Font *font;
|
||||
V2 pos;
|
||||
f32 scale;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
typedef struct DXC_Result DXC_Result;
|
||||
struct DXC_Result {
|
||||
Struct(DXC_Result) {
|
||||
String dxc;
|
||||
String errors;
|
||||
b32 success;
|
||||
|
||||
@ -21,8 +21,6 @@ DXC_Result dxc_compile(Arena *arena, String shader_source, i32 num_args, String
|
||||
#pragma warning(push, 0)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define UNICODE
|
||||
# define NTDDI_WIN11_DT 0x0C0A0000
|
||||
# define NTDDI_VERSION 0x0A000000
|
||||
# include <Windows.h>
|
||||
# include <atlbase.h>
|
||||
# include <dxcapi.h>
|
||||
|
||||
29
src/editor_include.h
Normal file
29
src/editor_include.h
Normal file
@ -0,0 +1,29 @@
|
||||
// This is an auto generated file containing all includes necessary to assist in editor parsing
|
||||
|
||||
#include "app/app.h"
|
||||
#include "ase/ase.h"
|
||||
#include "asset_cache/asset_cache.h"
|
||||
#include "base/base.h"
|
||||
#include "collider/collider.h"
|
||||
#include "draw/draw.h"
|
||||
#include "dxc/dxc.h"
|
||||
#include "font/font.h"
|
||||
#include "gp/gp.h"
|
||||
#include "inc/inc.h"
|
||||
#include "json/json.h"
|
||||
#include "kernel/kernel.h"
|
||||
#include "mixer/mixer.h"
|
||||
#include "mp3/mp3.h"
|
||||
#include "net/net.h"
|
||||
#include "platform/platform.h"
|
||||
#include "playback/playback.h"
|
||||
#include "prof/prof.h"
|
||||
#include "resource/resource.h"
|
||||
#include "settings/settings.h"
|
||||
#include "sim/sim.h"
|
||||
#include "sound/sound.h"
|
||||
#include "sprite/sprite.h"
|
||||
#include "tar/tar.h"
|
||||
#include "ttf/ttf.h"
|
||||
#include "user/user.h"
|
||||
#include "watch/watch.h"
|
||||
@ -48,24 +48,24 @@ INTERNAL struct font_task_params *font_task_params_alloc(void)
|
||||
{
|
||||
struct font_task_params *p = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = P_LockE(&G.params.mutex);
|
||||
if (G.params.head_free) {
|
||||
p = G.params.head_free;
|
||||
G.params.head_free = p->next_free;
|
||||
} else {
|
||||
p = arena_push(G.params.arena, struct font_task_params);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
INTERNAL void font_task_params_release(struct font_task_params *p)
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = P_LockE(&G.params.mutex);
|
||||
p->next_free = G.params.head_free;
|
||||
G.params.head_free = p;
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -82,7 +82,7 @@ INTERNAL P_JobDef(font_load_asset_job, job)
|
||||
f32 point_size = params->point_size;
|
||||
AC_Asset *asset = params->asset;
|
||||
|
||||
logf_info("Loading font \"%F\" (point size %F)", FMT_STR(path), FMT_FLOAT((f64)point_size));
|
||||
P_LogInfoF("Loading font \"%F\" (point size %F)", FMT_STR(path), FMT_FLOAT((f64)point_size));
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
ASSERT(string_ends_with(path, LIT(".ttf")));
|
||||
@ -138,7 +138,7 @@ INTERNAL P_JobDef(font_load_asset_job, job)
|
||||
|
||||
font_task_params_release(params);
|
||||
|
||||
logf_success("Loaded font \"%F\" (point size %F) in %F seconds", FMT_STR(path), FMT_FLOAT((f64)point_size), FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)));
|
||||
P_LogSuccessF("Loaded font \"%F\" (point size %F) in %F seconds", FMT_STR(path), FMT_FLOAT((f64)point_size), FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)));
|
||||
asset_cache_mark_ready(asset, font);
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
typedef struct F_Glyph F_Glyph;
|
||||
struct F_Glyph {
|
||||
Struct(F_Glyph) {
|
||||
f32 off_x;
|
||||
f32 off_y;
|
||||
i32 advance;
|
||||
@ -8,8 +7,7 @@ struct F_Glyph {
|
||||
Rect atlas_rect;
|
||||
};
|
||||
|
||||
typedef struct F_Font F_Font;
|
||||
struct F_Font {
|
||||
Struct(F_Font) {
|
||||
G_Resource *texture;
|
||||
u32 image_width;
|
||||
u32 image_height;
|
||||
@ -19,8 +17,7 @@ struct F_Font {
|
||||
u16 *lookup;
|
||||
};
|
||||
|
||||
typedef struct F_StartupReceipt F_StartupReceipt;
|
||||
struct F_StartupReceipt { i32 _; };
|
||||
Struct(F_StartupReceipt) { i32 _; };
|
||||
F_StartupReceipt font_startup(AC_StartupReceipt *asset_cache_sr, TTF_StartupReceipt *ttf_sr);
|
||||
|
||||
AC_Asset *font_load_asset(String path, f32 point_size, b32 wait);
|
||||
|
||||
169
src/gp/gp_core.h
169
src/gp/gp_core.h
@ -1,56 +1,21 @@
|
||||
typedef struct G_Indices G_Indices;
|
||||
struct G_Indices {
|
||||
////////////////////////////////
|
||||
//~ Opaque types
|
||||
|
||||
Struct(G_Resource);
|
||||
Struct(G_RenderSig);
|
||||
Struct(G_Swapchain);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Render
|
||||
|
||||
Struct(G_Indices)
|
||||
{
|
||||
u32 count;
|
||||
u32 *indices;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
void gp_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
* Resource
|
||||
* ========================== */
|
||||
|
||||
typedef struct G_Resource G_Resource;
|
||||
|
||||
/* NOTE: Internally, the layer will make sure to not release any resources
|
||||
* until after any in-flight GPU runs finish using them. However, it is up to
|
||||
* the caller to make sure the released resources aren't then referenced in
|
||||
* any runs
|
||||
*/
|
||||
void gp_resource_release(G_Resource *resource);
|
||||
|
||||
/* ========================== *
|
||||
* Texture
|
||||
* ========================== */
|
||||
|
||||
typedef enum G_TextureFormat {
|
||||
GP_TEXTURE_FORMAT_NONE,
|
||||
GP_TEXTURE_FORMAT_R8_UNORM,
|
||||
GP_TEXTURE_FORMAT_R8G8B8A8_UNORM,
|
||||
GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
GP_TEXTURE_FORMAT_R16G16B16A16_FLOAT,
|
||||
|
||||
NUM_GP_TEXTURE_FORMATS
|
||||
} G_TextureFormat;
|
||||
|
||||
typedef enum G_TextureFlag {
|
||||
GP_TEXTURE_FLAG_NONE = (0),
|
||||
GP_TEXTURE_FLAG_TARGETABLE = (1 << 0)
|
||||
} G_TextureFlag;
|
||||
|
||||
G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void *initial_data);
|
||||
|
||||
V2i32 gp_texture_get_size(G_Resource *texture);
|
||||
|
||||
/* ========================== *
|
||||
* Render
|
||||
* ========================== */
|
||||
|
||||
typedef enum G_RenderCmdKind {
|
||||
typedef i32 G_RenderCmdKind; enum
|
||||
{
|
||||
GP_RENDER_CMD_KIND_NONE,
|
||||
GP_RENDER_CMD_KIND_DRAW_MATERIAL,
|
||||
GP_RENDER_CMD_KIND_DRAW_UI_RECT,
|
||||
@ -58,13 +23,15 @@ typedef enum G_RenderCmdKind {
|
||||
GP_RENDER_CMD_KIND_PUSH_GRID,
|
||||
|
||||
NUM_GP_RENDER_CMD_KINDS
|
||||
} G_RenderCmdKind;
|
||||
};
|
||||
|
||||
typedef struct G_RenderCmdDesc G_RenderCmdDesc;
|
||||
struct G_RenderCmdDesc {
|
||||
Struct(G_RenderCmdDesc)
|
||||
{
|
||||
G_RenderCmdKind kind;
|
||||
union {
|
||||
struct {
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
Xform xf;
|
||||
G_Resource *texture;
|
||||
ClipRect clip;
|
||||
@ -73,18 +40,21 @@ struct G_RenderCmdDesc {
|
||||
V3 light_emittance;
|
||||
u32 grid_cmd_id;
|
||||
} material;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
Xform xf;
|
||||
G_Resource *texture;
|
||||
ClipRect clip;
|
||||
u32 tint;
|
||||
} ui_rect;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
V2Array vertices;
|
||||
G_Indices indices;
|
||||
u32 color;
|
||||
} ui_shape;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
f32 line_thickness;
|
||||
f32 line_spacing;
|
||||
V2 offset;
|
||||
@ -97,8 +67,8 @@ struct G_RenderCmdDesc {
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct G_RenderParams G_RenderParams;
|
||||
struct G_RenderParams {
|
||||
Struct(G_RenderParams)
|
||||
{
|
||||
V2i32 ui_size;
|
||||
V2i32 render_size;
|
||||
Xform world_to_render_xf;
|
||||
@ -106,7 +76,61 @@ struct G_RenderParams {
|
||||
b32 effects_disabled;
|
||||
};
|
||||
|
||||
typedef struct G_RenderSig G_RenderSig;
|
||||
////////////////////////////////
|
||||
//~ Texture
|
||||
|
||||
typedef i32 G_TextureFormat; enum
|
||||
{
|
||||
GP_TEXTURE_FORMAT_NONE,
|
||||
GP_TEXTURE_FORMAT_R8_UNORM,
|
||||
GP_TEXTURE_FORMAT_R8G8B8A8_UNORM,
|
||||
GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
GP_TEXTURE_FORMAT_R16G16B16A16_FLOAT,
|
||||
|
||||
NUM_GP_TEXTURE_FORMATS
|
||||
};
|
||||
|
||||
typedef i32 G_TextureFlag; enum
|
||||
{
|
||||
GP_TEXTURE_FLAG_NONE = (0),
|
||||
GP_TEXTURE_FLAG_TARGETABLE = (1 << 0)
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Memory info
|
||||
|
||||
Struct(G_MemoryInfo)
|
||||
{
|
||||
u64 local_used;
|
||||
u64 local_budget;
|
||||
u64 non_local_used;
|
||||
u64 non_local_budget;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
void gp_startup(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource operations
|
||||
|
||||
/* NOTE: Internally, the layer will make sure to not release any resources
|
||||
* until after any in-flight GPU runs finish using them. However, it is up to
|
||||
* the caller to make sure the released resources aren't then referenced in
|
||||
* any runs
|
||||
*/
|
||||
void gp_resource_release(G_Resource *resource);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Texture operations
|
||||
|
||||
G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void *initial_data);
|
||||
|
||||
V2i32 gp_texture_get_size(G_Resource *texture);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Render operations
|
||||
|
||||
G_RenderSig *gp_render_sig_alloc(void);
|
||||
|
||||
@ -115,25 +139,13 @@ u32 gp_push_render_cmd(G_RenderSig *render_sig, G_RenderCmdDesc *desc);
|
||||
|
||||
G_Resource *gp_run_render(G_RenderSig *gp_render_sig, G_RenderParams render_params);
|
||||
|
||||
/* ========================== *
|
||||
* Memory info
|
||||
* ========================== */
|
||||
|
||||
typedef struct G_MemoryInfo G_MemoryInfo;
|
||||
struct G_MemoryInfo {
|
||||
u64 local_used;
|
||||
u64 local_budget;
|
||||
u64 non_local_used;
|
||||
u64 non_local_budget;
|
||||
};
|
||||
////////////////////////////////
|
||||
//~ Memory query
|
||||
|
||||
G_MemoryInfo gp_query_memory_info(void);
|
||||
|
||||
/* ========================== *
|
||||
* Swapchain
|
||||
* ========================== */
|
||||
|
||||
typedef struct G_Swapchain G_Swapchain;
|
||||
////////////////////////////////
|
||||
//~ Swapchain
|
||||
|
||||
G_Swapchain *gp_swapchain_alloc(P_Window *window, V2i32 resolution);
|
||||
|
||||
@ -143,9 +155,8 @@ void gp_swapchain_release(G_Swapchain *gp_swapchain);
|
||||
* This should be called before rendering for minimum latency. */
|
||||
void gp_swapchain_wait(G_Swapchain *gp_swapchain);
|
||||
|
||||
/* ========================== *
|
||||
* Present
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Present
|
||||
|
||||
/* 1. Clears the backbuffer and ensures it's at size `backbuffer_resolution`
|
||||
* 2. Blits `texture` to the backbuffer using `texture_xf`
|
||||
|
||||
@ -448,12 +448,12 @@ INTERNAL P_ExitFuncDef(gp_shutdown)
|
||||
#endif
|
||||
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
P_Lock lock = P_LockE(&G.evictor_wake_mutex);
|
||||
G.evictor_shutdown = 1;
|
||||
snc_cv_signal(&G.evictor_wake_cv, I32_MAX);
|
||||
snc_unlock(&lock);
|
||||
P_SignalCv(&G.evictor_wake_cv, I32_MAX);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
snc_counter_wait(&G.evictor_job_counter);
|
||||
P_WaitOnCounter(&G.evictor_job_counter);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -601,21 +601,21 @@ INTERNAL void dx12_init_device(void)
|
||||
success = value != 0;
|
||||
}
|
||||
}
|
||||
logf_info("D3D12 profiling is enabled, attempting to set stable power state (this will increase GPU timing stability at the cost of performance)");
|
||||
P_LogInfoF("D3D12 profiling is enabled, attempting to set stable power state (this will increase GPU timing stability at the cost of performance)");
|
||||
if (success) {
|
||||
logf_info("Machine is in developer mode, calling ID3D12Device::SetStablePowerState");
|
||||
P_LogInfoF("Machine is in developer mode, calling ID3D12Device::SetStablePowerState");
|
||||
hr = ID3D12Device_SetStablePowerState(G.device, 1);
|
||||
if (SUCCEEDED(hr)) {
|
||||
logf_info("ID3D12Device::SetStablePowerState succeeded");
|
||||
P_LogInfoF("ID3D12Device::SetStablePowerState succeeded");
|
||||
} else {
|
||||
success = 0;
|
||||
logf_error("ID3D12Device::SetStablePowerState failed");
|
||||
P_LogErrorF("ID3D12Device::SetStablePowerState failed");
|
||||
}
|
||||
} else {
|
||||
logf_warning("Machine is not in developer mode, cannot call ID3D12Device::SetStablePowerState");
|
||||
P_LogWarningF("Machine is not in developer mode, cannot call ID3D12Device::SetStablePowerState");
|
||||
}
|
||||
if (!success) {
|
||||
logf_warning("Profiling is enabled, but ID3D12Device::SetStablePowerState could not be called. This means that GPU timing may be unreliable.");
|
||||
P_LogWarningF("Profiling is enabled, but ID3D12Device::SetStablePowerState could not be called. This means that GPU timing may be unreliable.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -660,7 +660,7 @@ INTERNAL void dx12_init_objects(void)
|
||||
{
|
||||
P_Counter counter = ZI;
|
||||
P_Run(DX12_NUM_QUEUES, command_queue_alloc_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
#if PROFILING
|
||||
{
|
||||
@ -754,20 +754,20 @@ INTERNAL void dx12_init_pipelines(void)
|
||||
sig.pipelines_out = pipelines;
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_pipelines, pipeline_alloc_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
for (u32 i = 0; i < num_pipelines; ++i) {
|
||||
struct pipeline *pipeline = pipelines[i];
|
||||
if (pipeline->success) {
|
||||
logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
||||
P_LogSuccessF("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
||||
if (pipeline->error.len) {
|
||||
String msg = string_format(scratch.arena, LIT("Warning while compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(pipeline->error));
|
||||
log_warning(msg);
|
||||
P_LogWarning(msg);
|
||||
}
|
||||
} else {
|
||||
String error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
||||
String msg = string_format(scratch.arena, LIT("Error initializing pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
||||
log_error(msg);
|
||||
P_LogError(msg);
|
||||
P_MessageBox(P_MessageBoxKind_Warning, msg);
|
||||
}
|
||||
}
|
||||
@ -829,7 +829,7 @@ INTERNAL void dx12_init_noise(void)
|
||||
sig.resource = r;
|
||||
sig.data = data.text;
|
||||
P_Run(1, dx12_upload_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -881,7 +881,7 @@ INTERNAL P_JobDef(shader_compile_job, job)
|
||||
DXC_Result dxc_result = ZI;
|
||||
{
|
||||
__profn("Compile shader");
|
||||
logf_info("Compiling shader \"%F:%F\"", FMT_STR(desc->friendly_name), FMT_STR(desc->entry));
|
||||
P_LogInfoF("Compiling shader \"%F:%F\"", FMT_STR(desc->friendly_name), FMT_STR(desc->entry));
|
||||
/* NOTE: `DXC_ARGS` is supplied by build system at compile time */
|
||||
char *dxc_args_cstr = STRINGIZE(DXC_ARGS);
|
||||
String dxc_args_str = string_from_cstr_no_limit(dxc_args_cstr);
|
||||
@ -925,14 +925,14 @@ INTERNAL P_JobDef(pipeline_alloc_job, job)
|
||||
|
||||
struct pipeline *pipeline = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = P_LockE(&G.pipelines_mutex);
|
||||
if (G.first_free_pipeline) {
|
||||
pipeline = G.first_free_pipeline;
|
||||
G.first_free_pipeline = pipeline->next;
|
||||
} else {
|
||||
pipeline = arena_push_no_zero(G.pipelines_arena, struct pipeline);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(pipeline);
|
||||
pipelines_out[job.id] = pipeline;
|
||||
@ -944,7 +944,7 @@ INTERNAL P_JobDef(pipeline_alloc_job, job)
|
||||
{
|
||||
i64 start_ns = P_TimeNs();
|
||||
String pipeline_name = pipeline->name;
|
||||
logf_info("Loading pipeline \"%F\"", FMT_STR(pipeline_name));
|
||||
P_LogInfoF("Loading pipeline \"%F\"", FMT_STR(pipeline_name));
|
||||
b32 success = 1;
|
||||
HRESULT hr = 0;
|
||||
|
||||
@ -1192,12 +1192,12 @@ INTERNAL void pipeline_release_now(struct pipeline *pipeline)
|
||||
if (pipeline->pso) {
|
||||
ID3D12PipelineState_Release(pipeline->pso);
|
||||
}
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = P_LockE(&G.pipelines_mutex);
|
||||
{
|
||||
pipeline->next = G.first_free_pipeline;
|
||||
G.first_free_pipeline = pipeline;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -1209,12 +1209,12 @@ INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
|
||||
__prof;
|
||||
struct pipeline_scope *scope = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = P_LockE(&G.pipelines_mutex);
|
||||
if (G.first_free_pipeline_scope) {
|
||||
scope = G.first_free_pipeline_scope;
|
||||
G.first_free_pipeline_scope = scope->next_free;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
Arena *arena = 0;
|
||||
if (scope) {
|
||||
@ -1232,7 +1232,7 @@ INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
|
||||
INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
|
||||
{
|
||||
__prof;
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = P_LockE(&G.pipelines_mutex);
|
||||
{
|
||||
for (DictEntry *entry = scope->refs->first; entry; entry = entry->next) {
|
||||
struct pipeline *pipeline = (struct pipeline *)entry->value;
|
||||
@ -1243,7 +1243,7 @@ INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
|
||||
scope->next_free = G.first_free_pipeline_scope;
|
||||
G.first_free_pipeline_scope = scope;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
INTERNAL READONLY struct pipeline g_nil_pipeline = ZI;
|
||||
@ -1258,12 +1258,12 @@ INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, Strin
|
||||
res = tmp;
|
||||
} else {
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = P_LockE(&G.pipelines_mutex);
|
||||
tmp = (struct pipeline *)dict_get(G.top_successful_pipelines, hash);
|
||||
if (tmp) {
|
||||
++tmp->refcount;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
if (tmp) {
|
||||
dict_set(scope->arena, scope->refs, hash, (u64)tmp);
|
||||
@ -1277,7 +1277,7 @@ INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, Strin
|
||||
INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines)
|
||||
{
|
||||
__prof;
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = P_LockE(&G.pipelines_mutex);
|
||||
{
|
||||
for (u64 i = 0; i < num_pipelines; ++i) {
|
||||
struct pipeline *pipeline = pipelines[i];
|
||||
@ -1302,7 +1302,7 @@ INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines)
|
||||
}
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
@ -1326,7 +1326,7 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
struct shader_compile_desc *shader_descs = 0;
|
||||
struct shader_compile_result *shader_results = 0;
|
||||
if (is_rs || is_cs) {
|
||||
logf_debug("Change detected in shader source file \"%F\", recompiling...", FMT_STR(name));
|
||||
P_LogDebugF("Change detected in shader source file \"%F\", recompiling...", FMT_STR(name));
|
||||
success = 1;
|
||||
P_File file = P_OpenFileReadWait(name);
|
||||
String data = P_ReadFile(scratch.arena, file);
|
||||
@ -1373,7 +1373,7 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
{
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_shaders, shader_compile_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
}
|
||||
P_CloseFIle(file);
|
||||
@ -1384,14 +1384,14 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
struct shader_compile_desc *desc = &shader_descs[i];
|
||||
struct shader_compile_result *result = &shader_results[i];
|
||||
if (result->success) {
|
||||
logf_success("Finished compiling shader \"%F:%F\" in %F seconds", FMT_STR(desc->friendly_name), FMT_STR(desc->entry), FMT_FLOAT(SECONDS_FROM_NS(result->elapsed_ns)));
|
||||
P_LogSuccessF("Finished compiling shader \"%F:%F\" in %F seconds", FMT_STR(desc->friendly_name), FMT_STR(desc->entry), FMT_FLOAT(SECONDS_FROM_NS(result->elapsed_ns)));
|
||||
if (result->errors.len > 0) {
|
||||
String msg = result->errors;
|
||||
log_warning(msg);
|
||||
P_LogWarning(msg);
|
||||
}
|
||||
} else {
|
||||
String msg = result->errors;
|
||||
log_error(msg);
|
||||
P_LogError(msg);
|
||||
success = 0;
|
||||
}
|
||||
}
|
||||
@ -1425,23 +1425,23 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
sig.pipelines_out = pipelines;
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_pipelines, pipeline_alloc_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
{
|
||||
P_Lock lock = snc_lock_s(&G.pipelines_mutex);
|
||||
P_Lock lock = P_LockS(&G.pipelines_mutex);
|
||||
for (u32 i = 0; i < num_pipelines; ++i) {
|
||||
struct pipeline *pipeline = pipelines[i];
|
||||
if (pipeline->success) {
|
||||
logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
||||
P_LogSuccessF("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
||||
if (pipeline->error.len > 0) {
|
||||
String msg = string_format(scratch.arena, LIT("Warning while compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(pipeline->error));
|
||||
log_warning(msg);
|
||||
P_LogWarning(msg);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
String error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
||||
String msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
||||
log_error(msg);
|
||||
P_LogError(msg);
|
||||
}
|
||||
struct pipeline *old_pipeline = (struct pipeline *)dict_get(G.top_successful_pipelines, pipeline->hash);
|
||||
if (!old_pipeline) {
|
||||
@ -1453,7 +1453,7 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
pipeline_register(num_pipelines, pipelines);
|
||||
}
|
||||
@ -1474,7 +1474,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
|
||||
u32 index = 0;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = ZI;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&dh->mutex);
|
||||
P_Lock lock = P_LockE(&dh->mutex);
|
||||
if (dh->first_free_descriptor) {
|
||||
d = dh->first_free_descriptor;
|
||||
dh->first_free_descriptor = d->next_free;
|
||||
@ -1488,7 +1488,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
|
||||
index = dh->num_descriptors_reserved++;
|
||||
handle.ptr = dh->handle.ptr + (index * dh->descriptor_size);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(d);
|
||||
d->heap = dh;
|
||||
@ -1500,12 +1500,12 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
|
||||
INTERNAL void descriptor_release(struct descriptor *descriptor)
|
||||
{
|
||||
struct cpu_descriptor_heap *dh = descriptor->heap;
|
||||
P_Lock lock = snc_lock_e(&dh->mutex);
|
||||
P_Lock lock = P_LockE(&dh->mutex);
|
||||
{
|
||||
descriptor->next_free = dh->first_free_descriptor;
|
||||
dh->first_free_descriptor = descriptor;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -1569,31 +1569,31 @@ INTERNAL void fenced_release(void *data, enum fenced_release_kind kind)
|
||||
/* Read current fence target values from command queues */
|
||||
for (u32 i = 0; i < countof(G.command_queues); ++i) {
|
||||
struct command_queue *cq = G.command_queues[i];
|
||||
P_Lock lock = snc_lock_s(&cq->submit_fence_mutex);
|
||||
P_Lock lock = P_LockS(&cq->submit_fence_mutex);
|
||||
{
|
||||
fr_targets[i] = cq->submit_fence_target;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Push data to release queue */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.fenced_releases_mutex);
|
||||
P_Lock lock = P_LockE(&G.fenced_releases_mutex);
|
||||
{
|
||||
*arena_push(G.fenced_releases_arena, struct fenced_release_data) = fr;
|
||||
MEMCPY(G.fenced_release_targets, fr_targets, sizeof(fr_targets));
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Wake evictor */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
P_Lock lock = P_LockE(&G.evictor_wake_mutex);
|
||||
{
|
||||
++G.evictor_wake_gen;
|
||||
snc_cv_signal(&G.evictor_wake_cv, I32_MAX);
|
||||
P_SignalCv(&G.evictor_wake_cv, I32_MAX);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1606,14 +1606,14 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr
|
||||
__prof;
|
||||
struct dx12_resource *r = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.resources_mutex);
|
||||
P_Lock lock = P_LockE(&G.resources_mutex);
|
||||
if (G.first_free_resource) {
|
||||
r = G.first_free_resource;
|
||||
G.first_free_resource = r->next_free;
|
||||
} else {
|
||||
r = arena_push_no_zero(G.resources_arena, struct dx12_resource);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(r);
|
||||
|
||||
@ -1657,10 +1657,10 @@ INTERNAL void dx12_resource_release_now(struct dx12_resource *t)
|
||||
ID3D12Resource_Release(t->resource);
|
||||
|
||||
/* Add to free list */
|
||||
P_Lock lock = snc_lock_e(&G.resources_mutex);
|
||||
P_Lock lock = P_LockE(&G.resources_mutex);
|
||||
t->next_free = G.first_free_resource;
|
||||
G.first_free_resource = t;
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
void gp_resource_release(G_Resource *resource)
|
||||
@ -1797,7 +1797,7 @@ INTERNAL struct command_list *command_list_open(struct command_list_pool *pool)
|
||||
struct ID3D12GraphicsCommandList *old_cl = 0;
|
||||
struct ID3D12CommandAllocator *old_ca = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&pool->mutex);
|
||||
P_Lock lock = P_LockE(&pool->mutex);
|
||||
/* Find first command list ready for reuse */
|
||||
for (struct command_list *tmp = pool->first_submitted_command_list; tmp; tmp = tmp->next_submitted) {
|
||||
if (completed_fence_value >= tmp->submitted_fence_target) {
|
||||
@ -1824,12 +1824,12 @@ INTERNAL struct command_list *command_list_open(struct command_list_pool *pool)
|
||||
} else {
|
||||
cl = arena_push_no_zero(pool->arena, struct command_list);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(cl);
|
||||
cl->cq = cq;
|
||||
cl->pool = pool;
|
||||
cl->global_record_lock = snc_lock_s(&G.global_command_list_record_mutex);
|
||||
cl->global_record_lock = P_LockS(&G.global_command_list_record_mutex);
|
||||
|
||||
HRESULT hr = 0;
|
||||
if (old_cl) {
|
||||
@ -1887,20 +1887,20 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
u64 submit_fence_target = 0;
|
||||
{
|
||||
__profn("Execute");
|
||||
P_Lock submit_lock = snc_lock_s(&G.global_submit_mutex);
|
||||
P_Lock fence_lock = snc_lock_e(&cq->submit_fence_mutex);
|
||||
P_Lock submit_lock = P_LockS(&G.global_submit_mutex);
|
||||
P_Lock fence_lock = P_LockE(&cq->submit_fence_mutex);
|
||||
{
|
||||
submit_fence_target = ++cq->submit_fence_target;
|
||||
ID3D12CommandQueue_ExecuteCommandLists(cq->cq, 1, (ID3D12CommandList **)&cl->cl);
|
||||
ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, submit_fence_target);
|
||||
}
|
||||
snc_unlock(&fence_lock);
|
||||
snc_unlock(&submit_lock);
|
||||
P_Unlock(&fence_lock);
|
||||
P_Unlock(&submit_lock);
|
||||
}
|
||||
|
||||
/* Add descriptor heaps to submitted list */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.command_descriptor_heaps_mutex);
|
||||
P_Lock lock = P_LockE(&G.command_descriptor_heaps_mutex);
|
||||
for (struct command_descriptor_heap *cdh = cl->first_command_descriptor_heap; cdh; cdh = cdh->next_in_command_list) {
|
||||
cdh->submitted_cq = cq;
|
||||
cdh->submitted_fence_target = submit_fence_target;
|
||||
@ -1911,12 +1911,12 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
}
|
||||
G.last_submitted_command_descriptor_heap = cdh;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Add command buffers to submitted list */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.command_buffers_mutex);
|
||||
P_Lock lock = P_LockE(&G.command_buffers_mutex);
|
||||
for (struct command_buffer *cb = cl->first_command_buffer; cb; cb = cb->next_in_command_list) {
|
||||
struct command_buffer_group *group = cb->group;
|
||||
cb->submitted_cq = cq;
|
||||
@ -1928,21 +1928,21 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
}
|
||||
group->last_submitted = cb;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Add command list to pool submitted list */
|
||||
snc_unlock(&cl->global_record_lock);
|
||||
P_Unlock(&cl->global_record_lock);
|
||||
cl->submitted_fence_target = submit_fence_target;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&pool->mutex);
|
||||
P_Lock lock = P_LockE(&pool->mutex);
|
||||
if (pool->last_submitted_command_list) {
|
||||
pool->last_submitted_command_list->next_submitted = cl;
|
||||
} else {
|
||||
pool->first_submitted_command_list = cl;
|
||||
}
|
||||
pool->last_submitted_command_list = cl;
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
return submit_fence_target;
|
||||
@ -1963,7 +1963,7 @@ INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struc
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE old_start_cpu_handle = ZI;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE old_start_gpu_handle = ZI;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.command_descriptor_heaps_mutex);
|
||||
P_Lock lock = P_LockE(&G.command_descriptor_heaps_mutex);
|
||||
/* Find first heap ready for reuse */
|
||||
for (struct command_descriptor_heap *tmp = G.first_submitted_command_descriptor_heap; tmp; tmp = tmp->next_submitted) {
|
||||
/* TODO: Cache completed fence values */
|
||||
@ -1994,7 +1994,7 @@ INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struc
|
||||
/* No available heap available for reuse, allocate new */
|
||||
cdh = arena_push_no_zero(G.command_descriptor_heaps_arena, struct command_descriptor_heap);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(cdh);
|
||||
|
||||
@ -2017,9 +2017,9 @@ INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struc
|
||||
|
||||
/* Copy CPU heap */
|
||||
{
|
||||
P_Lock lock = snc_lock_s(&dh_cpu->mutex);
|
||||
P_Lock lock = P_LockS(&dh_cpu->mutex);
|
||||
ID3D12Device_CopyDescriptorsSimple(G.device, dh_cpu->num_descriptors_reserved, cdh->start_cpu_handle, dh_cpu->handle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Insert into command list */
|
||||
@ -2071,7 +2071,7 @@ INTERNAL struct command_buffer *_command_list_push_buffer(struct command_list *c
|
||||
struct command_buffer *cb = 0;
|
||||
struct dx12_resource *r = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.command_buffers_mutex);
|
||||
P_Lock lock = P_LockE(&G.command_buffers_mutex);
|
||||
|
||||
{
|
||||
u64 group_hash = command_buffer_hash_from_size(size);
|
||||
@ -2111,7 +2111,7 @@ INTERNAL struct command_buffer *_command_list_push_buffer(struct command_list *c
|
||||
/* Allocate new */
|
||||
cb = arena_push_no_zero(G.command_buffers_arena, struct command_buffer);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(cb);
|
||||
cb->group = cb_group;
|
||||
@ -2265,7 +2265,7 @@ G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void
|
||||
sig.resource = r;
|
||||
sig.data = initial_data;
|
||||
P_Run(1, dx12_upload_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
|
||||
return (G_Resource *)r;
|
||||
@ -2377,7 +2377,7 @@ INTERNAL P_JobDef(dx12_upload_job, job)
|
||||
wait_sig.target = fence_target;
|
||||
P_Counter counter = ZI;
|
||||
P_Run(1, dx12_wait_fence_job, &wait_sig, P_Pool_Floating, P_Priority_Low, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
|
||||
/* Release upload heap now */
|
||||
@ -3209,14 +3209,14 @@ G_Swapchain *gp_swapchain_alloc(P_Window *window, V2i32 resolution)
|
||||
|
||||
struct swapchain *swapchain = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.swapchains_mutex);
|
||||
P_Lock lock = P_LockE(&G.swapchains_mutex);
|
||||
if (G.first_free_swapchain) {
|
||||
swapchain = G.first_free_swapchain;
|
||||
G.first_free_swapchain = swapchain->next_free;
|
||||
} else {
|
||||
swapchain = arena_push(G.swapchains_arena, struct swapchain);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Create swapchain1 */
|
||||
@ -3293,9 +3293,9 @@ INTERNAL struct swapchain_buffer *update_swapchain(struct swapchain *swapchain,
|
||||
struct command_queue *cq = G.command_queues[DX12_QUEUE_DIRECT];
|
||||
/* Lock direct queue submissions (in case any write to backbuffer) */
|
||||
/* TODO: Less overkill approach - Only flush present_blit since we know it's the only operation targeting backbuffer */
|
||||
P_Lock lock = snc_lock_e(&cq->submit_fence_mutex);
|
||||
P_Lock lock = P_LockE(&cq->submit_fence_mutex);
|
||||
//DEBUGBREAKABLE;
|
||||
//P_Lock lock = snc_lock_e(&G.global_command_list_record_mutex);
|
||||
//P_Lock lock = P_LockE(&G.global_command_list_record_mutex);
|
||||
{
|
||||
/* Flush direct queue */
|
||||
//ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, ++cq->submit_fence_target);
|
||||
@ -3320,7 +3320,7 @@ INTERNAL struct swapchain_buffer *update_swapchain(struct swapchain *swapchain,
|
||||
P_Panic(LIT("Failed to resize swapchain"));
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
|
||||
swapchain_init_resources(swapchain);
|
||||
|
||||
@ -3464,14 +3464,14 @@ void gp_present(G_Swapchain *gp_swapchain, V2i32 backbuffer_resolution, G_Resour
|
||||
|
||||
__profn("Mark queue frames");
|
||||
/* Lock because frame marks shouldn't occur while command lists are recording */
|
||||
P_Lock lock = snc_lock_e(&G.global_command_list_record_mutex);
|
||||
P_Lock lock = P_LockE(&G.global_command_list_record_mutex);
|
||||
for (u32 i = 0; i < countof(G.command_queues); ++i) {
|
||||
{
|
||||
struct command_queue *cq = G.command_queues[i];
|
||||
__prof_dx12_new_frame(cq->prof);
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
{
|
||||
__profn("Collect queues");
|
||||
@ -3505,13 +3505,13 @@ INTERNAL P_JobDef(dx12_evictor_job, _)
|
||||
struct fenced_release_data *fenced_releases = 0;
|
||||
{
|
||||
__profn("Copy queued releases");
|
||||
P_Lock lock = snc_lock_e(&G.fenced_releases_mutex);
|
||||
P_Lock lock = P_LockE(&G.fenced_releases_mutex);
|
||||
num_fenced_releases = G.fenced_releases_arena->pos / sizeof(struct fenced_release_data);
|
||||
fenced_releases = arena_push_array_no_zero(scratch.arena, struct fenced_release_data, num_fenced_releases);
|
||||
MEMCPY(fenced_releases, arena_base(G.fenced_releases_arena), G.fenced_releases_arena->pos);
|
||||
arena_reset(G.fenced_releases_arena);
|
||||
MEMCPY(targets, G.fenced_release_targets, sizeof(targets));
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Wait until fences reach target */
|
||||
@ -3530,7 +3530,7 @@ INTERNAL P_JobDef(dx12_evictor_job, _)
|
||||
{
|
||||
P_Counter counter = ZI;
|
||||
P_Run(1, dx12_wait_fence_job, &sig, P_Pool_Floating, P_Priority_Low, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3563,14 +3563,14 @@ INTERNAL P_JobDef(dx12_evictor_job, _)
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
P_Lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
P_Lock lock = P_LockE(&G.evictor_wake_mutex);
|
||||
{
|
||||
while (!G.evictor_shutdown && G.evictor_wake_gen == 0) {
|
||||
snc_cv_wait(&G.evictor_wake_cv, &lock);
|
||||
P_WaitOnCv(&G.evictor_wake_cv, &lock);
|
||||
}
|
||||
shutdown = G.evictor_shutdown;
|
||||
G.evictor_wake_gen = 0;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
|
||||
typedef enum JSON_Type {
|
||||
typedef i32 JSON_Type; enum {
|
||||
JSON_TYPE_NULL,
|
||||
JSON_TYPE_BOOL,
|
||||
JSON_TYPE_NUMBER,
|
||||
JSON_TYPE_STRING,
|
||||
JSON_TYPE_ARRAY,
|
||||
JSON_TYPE_OBJECT
|
||||
} JSON_Type;
|
||||
};
|
||||
|
||||
typedef struct JSON_Blob JSON_Blob;
|
||||
struct JSON_Blob {
|
||||
Struct(JSON_Blob) {
|
||||
JSON_Type type;
|
||||
String key;
|
||||
|
||||
@ -25,23 +24,20 @@ struct JSON_Blob {
|
||||
} value;
|
||||
};
|
||||
|
||||
typedef struct JSON_Error JSON_Error;
|
||||
struct JSON_Error {
|
||||
Struct(JSON_Error) {
|
||||
String msg;
|
||||
u64 start;
|
||||
u64 end;
|
||||
JSON_Error *next;
|
||||
};
|
||||
|
||||
typedef struct JSON_ErrorList JSON_ErrorList;
|
||||
struct JSON_ErrorList {
|
||||
Struct(JSON_ErrorList) {
|
||||
u64 count;
|
||||
JSON_Error *first;
|
||||
JSON_Error *last;
|
||||
};
|
||||
|
||||
typedef struct JSON_Result JSON_Result;
|
||||
struct JSON_Result {
|
||||
Struct(JSON_Result) {
|
||||
JSON_Blob *root;
|
||||
JSON_ErrorList errors;
|
||||
};
|
||||
|
||||
@ -96,7 +96,7 @@ INTERNAL struct track *track_from_handle(M_Handle handle)
|
||||
|
||||
INTERNAL struct track *track_alloc_locked(P_Lock *lock, SND_Sound *sound)
|
||||
{
|
||||
snc_assert_locked_e(lock, &G.mutex);
|
||||
P_AssertLockedE(lock, &G.mutex);
|
||||
(UNUSED)lock;
|
||||
|
||||
struct track *track = 0;
|
||||
@ -135,7 +135,7 @@ INTERNAL struct track *track_alloc_locked(P_Lock *lock, SND_Sound *sound)
|
||||
|
||||
INTERNAL void track_release_locked(P_Lock *lock, struct track *track)
|
||||
{
|
||||
snc_assert_locked_e(lock, &G.mutex);
|
||||
P_AssertLockedE(lock, &G.mutex);
|
||||
(UNUSED)lock;
|
||||
|
||||
/* Remove from playing list */
|
||||
@ -181,12 +181,12 @@ M_Handle mixer_play_ex(SND_Sound *sound, M_TrackDesc desc)
|
||||
{
|
||||
struct track *track;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = P_LockE(&G.mutex);
|
||||
{
|
||||
track = track_alloc_locked(&lock, sound);
|
||||
track->desc = desc;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
return track_to_handle(track);
|
||||
}
|
||||
@ -199,7 +199,7 @@ M_TrackDesc mixer_track_get(M_Handle handle)
|
||||
struct track *track = track_from_handle(handle);
|
||||
if (track) {
|
||||
/* TODO: Only lock mutex on track itself or something */
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = P_LockE(&G.mutex);
|
||||
{
|
||||
/* Confirm handle is still valid now that we're locked */
|
||||
track = track_from_handle(handle);
|
||||
@ -207,7 +207,7 @@ M_TrackDesc mixer_track_get(M_Handle handle)
|
||||
res = track->desc;
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -219,7 +219,7 @@ void mixer_track_set(M_Handle handle, M_TrackDesc desc)
|
||||
struct track *track = track_from_handle(handle);
|
||||
if (track) {
|
||||
/* TODO: Only lock mutex on track itself or something */
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = P_LockE(&G.mutex);
|
||||
{
|
||||
/* Confirm handle is still valid now that we're locked */
|
||||
track = track_from_handle(handle);
|
||||
@ -227,18 +227,18 @@ void mixer_track_set(M_Handle handle, M_TrackDesc desc)
|
||||
track->desc = desc;
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
void mixer_set_listener(V2 pos, V2 dir)
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = P_LockE(&G.mutex);
|
||||
{
|
||||
G.listener_pos = pos;
|
||||
G.listener_dir = v2_norm(dir);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -274,7 +274,7 @@ M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||
struct mix **mixes = 0;
|
||||
u64 mixes_count = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = P_LockE(&G.mutex);
|
||||
|
||||
/* Read listener info */
|
||||
listener_pos = G.listener_pos;
|
||||
@ -289,7 +289,7 @@ M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||
mixes[mixes_count++] = mix;
|
||||
}
|
||||
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
for (u64 mix_index = 0; mix_index < mixes_count; ++mix_index) {
|
||||
@ -462,7 +462,7 @@ M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||
|
||||
{
|
||||
__profn("Update track effect data");
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = P_LockE(&G.mutex);
|
||||
for (u64 i = 0; i < mixes_count; ++i) {
|
||||
struct mix *mix = mixes[i];
|
||||
struct track *track = track_from_handle(mix->track_handle);
|
||||
@ -473,7 +473,7 @@ M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||
}
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
@ -13,8 +13,7 @@
|
||||
__VA_ARGS__ \
|
||||
})
|
||||
|
||||
typedef struct M_TrackDesc M_TrackDesc;
|
||||
struct M_TrackDesc {
|
||||
Struct(M_TrackDesc) {
|
||||
u32 flags;
|
||||
f32 volume; /* 0 -> 1.0+ */
|
||||
f32 speed; /* 0 -> 1.0+ */
|
||||
@ -24,21 +23,18 @@ struct M_TrackDesc {
|
||||
V2 pos;
|
||||
};
|
||||
|
||||
typedef struct M_Handle M_Handle;
|
||||
struct M_Handle {
|
||||
Struct(M_Handle) {
|
||||
u64 gen;
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* Stereo mix of 32 bit float samples */
|
||||
typedef struct M_PcmF32 M_PcmF32;
|
||||
struct M_PcmF32 {
|
||||
Struct(M_PcmF32) {
|
||||
u64 count;
|
||||
f32 *samples;
|
||||
};
|
||||
|
||||
typedef struct M_StartupReceipt M_StartupReceipt;
|
||||
struct M_StartupReceipt { i32 _; };
|
||||
Struct(M_StartupReceipt) { i32 _; };
|
||||
M_StartupReceipt mixer_startup(void);
|
||||
|
||||
/* Interface */
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
#define MP3_DECODE_FLAG_NONE 0x00
|
||||
#define MP3_DECODE_FLAG_STEREO 0x01
|
||||
|
||||
typedef struct MP3_Result MP3_Result;
|
||||
struct MP3_Result {
|
||||
Struct(MP3_Result) {
|
||||
PcmData pcm;
|
||||
b32 success;
|
||||
};
|
||||
|
||||
@ -672,7 +672,7 @@ N_EventList host_update_begin(Arena *arena, N_Host *host)
|
||||
{
|
||||
/* A foreign host is trying to connect to us */
|
||||
if (!channel->valid) {
|
||||
logf_info("Host received conection attempt from %F", FMT_STR(P_StringFromAddress(scratch.arena, address)));
|
||||
P_LogInfoF("Host received conection attempt from %F", FMT_STR(P_StringFromAddress(scratch.arena, address)));
|
||||
/* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */
|
||||
channel = host_channel_alloc(host, address);
|
||||
}
|
||||
@ -685,7 +685,7 @@ N_EventList host_update_begin(Arena *arena, N_Host *host)
|
||||
{
|
||||
/* We successfully connected to a foreign host and they are ready to receive messages */
|
||||
if (channel->valid && !channel->connected) {
|
||||
logf_info("Host received connection from %F", FMT_STR(P_StringFromAddress(scratch.arena, address)));
|
||||
P_LogInfoF("Host received connection from %F", FMT_STR(P_StringFromAddress(scratch.arena, address)));
|
||||
N_Event *event = push_event(arena, &events);
|
||||
event->kind = HOST_EVENT_KIND_CHANNEL_OPENED;
|
||||
event->channel_id = channel->id;
|
||||
@ -697,7 +697,7 @@ N_EventList host_update_begin(Arena *arena, N_Host *host)
|
||||
{
|
||||
/* A foreign host disconnected from us */
|
||||
if (channel->valid) {
|
||||
logf_info("Host received disconnection from %F", FMT_STR(P_StringFromAddress(scratch.arena, address)));
|
||||
P_LogInfoF("Host received disconnection from %F", FMT_STR(P_StringFromAddress(scratch.arena, address)));
|
||||
N_Event *event = push_event(arena, &events);
|
||||
event->kind = HOST_EVENT_KIND_CHANNEL_CLOSED;
|
||||
event->channel_id = channel->id;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#define N_NumChannelLookupBins 512
|
||||
#define N_NumMsgAssemblerLookupBins 16384
|
||||
|
||||
typedef enum N_CmdKind {
|
||||
typedef i32 N_CmdKind; enum {
|
||||
HOST_CMD_KIND_NONE,
|
||||
|
||||
HOST_CMD_KIND_TRY_CONNECT,
|
||||
@ -16,30 +16,28 @@ typedef enum N_CmdKind {
|
||||
HOST_CMD_KIND_DISCONNECT,
|
||||
HOST_CMD_KIND_HEARTBEAT,
|
||||
HOST_CMD_KIND_WRITE
|
||||
} N_CmdKind;
|
||||
};
|
||||
|
||||
typedef enum N_EventKind {
|
||||
typedef i32 N_EventKind; enum {
|
||||
HOST_EVENT_KIND_NONE,
|
||||
|
||||
HOST_EVENT_KIND_CHANNEL_OPENED,
|
||||
HOST_EVENT_KIND_CHANNEL_CLOSED,
|
||||
HOST_EVENT_KIND_MSG
|
||||
} N_EventKind;
|
||||
};
|
||||
|
||||
typedef enum N_WriteFlag {
|
||||
typedef i32 N_WriteFlag; enum {
|
||||
HOST_WRITE_FLAG_NONE = 0,
|
||||
|
||||
HOST_WRITE_FLAG_RELIABLE = (1 << 0)
|
||||
} N_WriteFlag;
|
||||
};
|
||||
|
||||
typedef struct N_ChannelId N_ChannelId;
|
||||
struct N_ChannelId {
|
||||
Struct(N_ChannelId) {
|
||||
u32 gen;
|
||||
u32 idx;
|
||||
};
|
||||
|
||||
typedef struct N_Cmd N_Cmd;
|
||||
struct N_Cmd {
|
||||
Struct(N_Cmd) {
|
||||
N_CmdKind kind;
|
||||
N_ChannelId channel_id;
|
||||
|
||||
@ -53,8 +51,7 @@ struct N_Cmd {
|
||||
N_Cmd *next;
|
||||
};
|
||||
|
||||
typedef struct N_Event N_Event;
|
||||
struct N_Event {
|
||||
Struct(N_Event) {
|
||||
N_EventKind kind;
|
||||
N_ChannelId channel_id;
|
||||
String msg;
|
||||
@ -62,27 +59,23 @@ struct N_Event {
|
||||
N_Event *next;
|
||||
};
|
||||
|
||||
typedef struct N_EventList N_EventList;
|
||||
struct N_EventList {
|
||||
Struct(N_EventList) {
|
||||
N_Event *first;
|
||||
N_Event *last;
|
||||
};
|
||||
|
||||
typedef struct N_ChannelLookupBin N_ChannelLookupBin;
|
||||
struct N_ChannelLookupBin {
|
||||
Struct(N_ChannelLookupBin) {
|
||||
struct host_channel *first;
|
||||
struct host_channel *last;
|
||||
};
|
||||
|
||||
typedef struct N_RcvBuffer N_RcvBuffer;
|
||||
struct N_RcvBuffer {
|
||||
Struct(N_RcvBuffer) {
|
||||
Arena *arena;
|
||||
struct host_rcv_packet *first_packet;
|
||||
struct host_rcv_packet *last_packet;
|
||||
};
|
||||
|
||||
typedef struct N_SndPacket N_SndPacket;
|
||||
struct N_SndPacket {
|
||||
Struct(N_SndPacket) {
|
||||
N_SndPacket *next;
|
||||
u64 seq;
|
||||
|
||||
@ -90,8 +83,7 @@ struct N_SndPacket {
|
||||
u8 data[N_MaxPacketLen];
|
||||
};
|
||||
|
||||
typedef struct N_Host N_Host;
|
||||
struct N_Host {
|
||||
Struct(N_Host) {
|
||||
Arena *arena;
|
||||
|
||||
P_Sock *sock;
|
||||
@ -130,8 +122,7 @@ struct N_Host {
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
typedef struct N_StartupReceipt N_StartupReceipt;
|
||||
struct N_StartupReceipt { i32 _; };
|
||||
Struct(N_StartupReceipt) { i32 _; };
|
||||
N_StartupReceipt host_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#include "platform.h"
|
||||
|
||||
#include "platform_snc.c"
|
||||
#include "platform_sleep.c"
|
||||
#include "platform_log.c"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
@ -4,11 +4,28 @@
|
||||
#include "../base/base.h"
|
||||
|
||||
#include "platform_snc.h"
|
||||
#include "platform_sleep.h"
|
||||
#include "platform_core.h"
|
||||
#include "platform_log.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#pragma warning(push, 0)
|
||||
# define UNICODE
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
/* FIXME: Remove this */
|
||||
# define NTDDI_WIN11_DT 0x0C0A0000
|
||||
# define NTDDI_VERSION 0x0A000000
|
||||
# include <Windows.h>
|
||||
# include <WinSock2.h>
|
||||
# include <TlHelp32.h>
|
||||
# include <WS2tcpip.h>
|
||||
# include <windowsx.h>
|
||||
# include <ShlObj_core.h>
|
||||
# include <fileapi.h>
|
||||
# include <dwmapi.h>
|
||||
# include <bcrypt.h>
|
||||
# include <avrt.h>
|
||||
# include <shellapi.h>
|
||||
#pragma warning(pop)
|
||||
# include "platform_win32.h"
|
||||
#endif
|
||||
|
||||
|
||||
@ -1,19 +1,24 @@
|
||||
/* ========================== *
|
||||
* Wait
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Opaque types
|
||||
|
||||
Struct(P_Watch);
|
||||
Struct(P_Window);
|
||||
Struct(P_Sock);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Wait
|
||||
|
||||
/* Futex-like wait & wake */
|
||||
|
||||
void P_Wait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns);
|
||||
|
||||
void P_Wake(void *addr, i32 count);
|
||||
|
||||
/* ========================== *
|
||||
* Job
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Job
|
||||
|
||||
/* Work pools contain their own worker threads with their own thread priority/affinity based on the intended context of the pool. */
|
||||
typedef enum P_Pool {
|
||||
typedef i32 P_Pool; enum
|
||||
{
|
||||
P_Pool_Inherit = -1,
|
||||
|
||||
/* The floating pool contains a large number of lower priority threads that have affinity over the entire CPU.
|
||||
@ -26,20 +31,21 @@ typedef enum P_Pool {
|
||||
P_Pool_Sim = 4,
|
||||
|
||||
P_Pool_Count
|
||||
} P_Pool;
|
||||
};
|
||||
|
||||
/* Job execution order within a pool is based on priority. */
|
||||
typedef enum P_Priority {
|
||||
typedef i32 P_Priority; enum
|
||||
{
|
||||
P_Priority_Inherit = -1,
|
||||
P_Priority_High = 0,
|
||||
P_Priority_Normal = 1,
|
||||
P_Priority_Low = 2,
|
||||
|
||||
P_Priority_Count
|
||||
} P_Priority;
|
||||
};
|
||||
|
||||
typedef struct P_JobData P_JobData;
|
||||
struct P_JobData {
|
||||
Struct(P_JobData)
|
||||
{
|
||||
i32 id;
|
||||
void *sig;
|
||||
};
|
||||
@ -47,14 +53,11 @@ struct P_JobData {
|
||||
#define P_JobDef(job_name, arg_name) void job_name(P_JobData arg_name)
|
||||
typedef P_JobDef(P_JobFunc, job_data);
|
||||
|
||||
void P_Run(i32 count, P_JobFunc *func, void *sig, P_Pool pool_kind, P_Priority priority, P_Counter *counter);
|
||||
////////////////////////////////
|
||||
//~ Time
|
||||
|
||||
/* ========================== *
|
||||
* Time
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_DateTime P_DateTime;
|
||||
struct P_DateTime {
|
||||
Struct(P_DateTime)
|
||||
{
|
||||
u32 year;
|
||||
u32 month;
|
||||
u32 day_of_week;
|
||||
@ -65,117 +68,62 @@ struct P_DateTime {
|
||||
u32 milliseconds;
|
||||
};
|
||||
|
||||
P_DateTime P_LocalTime(void);
|
||||
////////////////////////////////
|
||||
//~ File
|
||||
|
||||
i64 P_TimeNs(void);
|
||||
|
||||
/* ========================== *
|
||||
* File system
|
||||
*
|
||||
* NOTE: File paths use forward slash '/' as delimiter
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_File P_File;
|
||||
struct P_File {
|
||||
Struct(P_File)
|
||||
{
|
||||
u64 handle;
|
||||
b32 valid;
|
||||
};
|
||||
|
||||
typedef struct P_FileTime P_FileTime;
|
||||
struct P_FileTime {
|
||||
Struct(P_FileTime)
|
||||
{
|
||||
P_DateTime created;
|
||||
P_DateTime accessed;
|
||||
P_DateTime modified;
|
||||
};
|
||||
|
||||
String P_GetWritePath(Arena *arena);
|
||||
|
||||
b32 P_IsFile(String path);
|
||||
|
||||
b32 P_IsDir(String path);
|
||||
|
||||
void P_MkDir(String path);
|
||||
|
||||
P_File P_OpenFileRead(String path);
|
||||
|
||||
P_File P_OpenFileReadWait(String path); /* Waits until file is not being used by another program */
|
||||
|
||||
P_File P_OpenFileWrite(String path);
|
||||
|
||||
P_File P_OpenFileAppend(String path);
|
||||
|
||||
void P_CloseFIle(P_File file);
|
||||
|
||||
String P_ReadFile(Arena *arena, P_File file);
|
||||
|
||||
void P_WriteFile(P_File file, String data);
|
||||
|
||||
u64 P_GetFileSize(P_File file);
|
||||
|
||||
P_FileTime P_GetFileTime(P_File file);
|
||||
|
||||
/* ========================== *
|
||||
* File map
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_FileMap P_FileMap;
|
||||
struct P_FileMap {
|
||||
Struct(P_FileMap)
|
||||
{
|
||||
String mapped_memory;
|
||||
u64 handle;
|
||||
b32 valid;
|
||||
};
|
||||
|
||||
P_FileMap P_OpenFileMap(P_File file);
|
||||
////////////////////////////////
|
||||
//~ Watch
|
||||
|
||||
void P_CloseFileMap(P_FileMap map);
|
||||
|
||||
String P_GetFileMapData(P_FileMap map);
|
||||
|
||||
/* ========================== *
|
||||
* Watch
|
||||
* ========================== */
|
||||
|
||||
typedef enum P_WatchInfoKind {
|
||||
typedef i32 P_WatchInfoKind; enum
|
||||
{
|
||||
P_WatchInfoKind_Unknown,
|
||||
P_WatchInfoKind_Added,
|
||||
P_WatchInfoKind_Removed,
|
||||
P_WatchInfoKind_Modified,
|
||||
P_WatchInfoKind_RenamedOld,
|
||||
P_WatchInfoKind_RenamedNew
|
||||
} P_WatchInfoKind;
|
||||
};
|
||||
|
||||
typedef struct P_WatchInfo P_WatchInfo;
|
||||
struct P_WatchInfo {
|
||||
Struct(P_WatchInfo)
|
||||
{
|
||||
P_WatchInfoKind kind;
|
||||
String name;
|
||||
P_WatchInfo *next;
|
||||
P_WatchInfo *prev;
|
||||
};
|
||||
|
||||
typedef struct P_WatchInfoList P_WatchInfoList;
|
||||
struct P_WatchInfoList {
|
||||
Struct(P_WatchInfoList)
|
||||
{
|
||||
P_WatchInfo *first;
|
||||
P_WatchInfo *last;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
typedef struct P_Watch P_Watch;
|
||||
////////////////////////////////
|
||||
//~ Window events
|
||||
|
||||
P_Watch *P_AllocWatch(String path);
|
||||
|
||||
void P_ReleaseWatch(P_Watch *dw);
|
||||
|
||||
P_WatchInfoList P_ReadWatchWait(Arena *arena, P_Watch *dw);
|
||||
|
||||
void P_WakeWatch(P_Watch *dw);
|
||||
|
||||
/* ========================== *
|
||||
* Window
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_Window P_Window;
|
||||
|
||||
typedef enum P_Btn {
|
||||
typedef i32 P_Btn; enum
|
||||
{
|
||||
P_Btn_None,
|
||||
|
||||
P_Btn_M1,
|
||||
@ -277,9 +225,10 @@ typedef enum P_Btn {
|
||||
P_Btn_Semicolon,
|
||||
|
||||
P_Btn_Count
|
||||
} P_Btn;
|
||||
};
|
||||
|
||||
typedef enum P_WindowEventKind {
|
||||
typedef i32 P_WindowEventKind; enum
|
||||
{
|
||||
P_WindowEventKind_None,
|
||||
|
||||
P_WindowEventKind_ButtonDown,
|
||||
@ -290,10 +239,10 @@ typedef enum P_WindowEventKind {
|
||||
P_WindowEventKind_Quit,
|
||||
|
||||
P_WindowEventKind_Count
|
||||
} P_WindowEventKind;
|
||||
};
|
||||
|
||||
typedef struct P_WindowEvent P_WindowEvent;
|
||||
struct P_WindowEvent {
|
||||
Struct(P_WindowEvent)
|
||||
{
|
||||
P_WindowEventKind kind;
|
||||
|
||||
/* P_WindowEventKind_BUTTON_DOWN */
|
||||
@ -311,18 +260,22 @@ struct P_WindowEvent {
|
||||
V2 mouse_delta;
|
||||
};
|
||||
|
||||
typedef struct P_WindowEventArray P_WindowEventArray;
|
||||
struct P_WindowEventArray {
|
||||
Struct(P_WindowEventArray)
|
||||
{
|
||||
u64 count;
|
||||
P_WindowEvent *events;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Window settings
|
||||
|
||||
/* NOTE:
|
||||
* A window object can only be interacted with by the thread that created it.
|
||||
* This restriction is in place because of how Win32 works, IE you cannot
|
||||
* create a Win32 window in one thread and process its messages on another. */
|
||||
|
||||
typedef enum P_WindowSettingsFlag {
|
||||
typedef i32 P_WindowSettingsFlag; enum
|
||||
{
|
||||
P_WindowSettingsFlag_None = 0x00,
|
||||
P_WindowSettingsFlag_Fullscreen = 0x01,
|
||||
|
||||
@ -331,16 +284,17 @@ typedef enum P_WindowSettingsFlag {
|
||||
* restore to being maximized once it's un-minimized. */
|
||||
P_WindowSettingsFlag_Maximized = 0x02,
|
||||
P_WindowSettingsFlag_Minimized = 0x04
|
||||
} P_WindowSettingsFlag;
|
||||
};
|
||||
|
||||
typedef enum P_WindowFlag {
|
||||
typedef i32 P_WindowFlag; enum
|
||||
{
|
||||
P_WindowFlag_None = 0x00,
|
||||
P_WindowFlag_Showing = 0x02
|
||||
} P_WindowFlag;
|
||||
};
|
||||
|
||||
/* P_UpdateWindowSettings should be used when altering settings values */
|
||||
typedef struct P_WindowSettings P_WindowSettings;
|
||||
struct P_WindowSettings {
|
||||
Struct(P_WindowSettings)
|
||||
{
|
||||
char title[256];
|
||||
u32 flags;
|
||||
|
||||
@ -354,48 +308,17 @@ struct P_WindowSettings {
|
||||
i32 floating_height;
|
||||
};
|
||||
|
||||
P_Window *P_AllocWindow(void);
|
||||
////////////////////////////////
|
||||
//~ Address
|
||||
|
||||
void P_ReleaseWindow(P_Window *window);
|
||||
|
||||
P_WindowEventArray P_PopWindowEvents(Arena *arena, P_Window *window);
|
||||
|
||||
void P_UpdateWindowSettings(P_Window *window, P_WindowSettings *settings);
|
||||
|
||||
P_WindowSettings P_GetWindowSettings(P_Window *window);
|
||||
|
||||
void P_ShowWindow(P_Window *window);
|
||||
|
||||
V2 P_GetWindowSize(P_Window *window);
|
||||
|
||||
V2 P_GetWindowMonitorSize(P_Window *window);
|
||||
|
||||
/* Returns a platform specific representation of the window. E.g. `hwnd` on win32. */
|
||||
u64 P_GetInternalWindowHandle(P_Window *window);
|
||||
|
||||
void P_SetWindowCursorPos(P_Window *window, V2 pos);
|
||||
|
||||
void P_ShowWindowCursor(P_Window *window);
|
||||
|
||||
void P_HideWindowCursor(P_Window *window);
|
||||
|
||||
void P_EnableWindoweCursorClip(P_Window *window, Rect bounds);
|
||||
|
||||
void P_DisableWindoweCursorClip(P_Window *window);
|
||||
|
||||
void P_ToggleWindowTopmost(P_Window *window);
|
||||
|
||||
/* ========================== *
|
||||
* Address
|
||||
* ========================== */
|
||||
|
||||
typedef enum P_AddressFamily {
|
||||
typedef i32 P_AddressFamily; enum
|
||||
{
|
||||
P_AddressFamily_Ipv4,
|
||||
P_AddressFamily_Ipv6
|
||||
} P_AddressFamily;
|
||||
};
|
||||
|
||||
typedef struct P_Address P_Address;
|
||||
struct P_Address {
|
||||
Struct(P_Address)
|
||||
{
|
||||
b32 valid;
|
||||
P_AddressFamily family;
|
||||
/* NOTE: ipnb & portnb are stored in network byte order */
|
||||
@ -403,80 +326,154 @@ struct P_Address {
|
||||
u16 portnb;
|
||||
};
|
||||
|
||||
P_Address P_AddressFromString(String str);
|
||||
////////////////////////////////
|
||||
//~ Sock
|
||||
|
||||
P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr);
|
||||
|
||||
P_Address P_AddressFromPort(u16 port);
|
||||
|
||||
String P_StringFromAddress(Arena *arena, P_Address address);
|
||||
|
||||
b32 P_AddressIsEqual(P_Address a, P_Address b);
|
||||
|
||||
/* ========================== *
|
||||
* Sock
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_SockReadResult P_SockReadResult;
|
||||
struct P_SockReadResult {
|
||||
Struct(P_SockReadResult)
|
||||
{
|
||||
b32 valid; /* Since data.len = 0 can be valid */
|
||||
P_Address address;
|
||||
String data;
|
||||
};
|
||||
|
||||
typedef struct P_Sock P_Sock;
|
||||
////////////////////////////////
|
||||
//~ Message box
|
||||
|
||||
P_Sock *P_AllocSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
|
||||
|
||||
void P_ReleaseSock(P_Sock *sock);
|
||||
|
||||
P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock);
|
||||
|
||||
void P_WriteSock(P_Sock *sock, P_Address address, String data);
|
||||
|
||||
/* ========================== *
|
||||
* Util
|
||||
* ========================== */
|
||||
|
||||
typedef enum P_MessageBoxKind {
|
||||
typedef i32 P_MessageBoxKind; enum
|
||||
{
|
||||
P_MessageBoxKind_Ok,
|
||||
P_MessageBoxKind_Warning,
|
||||
P_MessageBoxKind_Error,
|
||||
P_MessageBoxKind_Fatal
|
||||
} P_MessageBoxKind;
|
||||
|
||||
void P_MessageBox(P_MessageBoxKind kind, String message);
|
||||
|
||||
void P_SetClipboardText(String str);
|
||||
|
||||
String P_GetClipboardText(Arena *arena);
|
||||
|
||||
u32 P_GetLogicalProcessorCount(void);
|
||||
|
||||
u32 P_GetThreadId(void);
|
||||
|
||||
i64 P_GetCurrentSchedulerPeriodNs(void);
|
||||
|
||||
/* ========================== *
|
||||
* Exit
|
||||
* ========================== */
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Exit callback function
|
||||
|
||||
#define P_ExitFuncDef(name) void name(void)
|
||||
typedef P_ExitFuncDef(P_ExitFunc);
|
||||
|
||||
/* Registers a function to be called during graceful shutdown (in reverse order) */
|
||||
void P_OnExit(P_ExitFunc *func);
|
||||
////////////////////////////////
|
||||
//~ Job helpers
|
||||
|
||||
/* Signals the program to shut down gracefully and run exit callbacks */
|
||||
void P_Exit(void);
|
||||
void P_Run(i32 count, P_JobFunc *func, void *sig, P_Pool pool_kind, P_Priority priority, P_Counter *counter);
|
||||
|
||||
/* Forcefully exits the program and displays `msg` to the user */
|
||||
void P_Panic(String msg);
|
||||
////////////////////////////////
|
||||
//~ Time helpers
|
||||
|
||||
/* ========================== *
|
||||
* App entry point
|
||||
* ========================== */
|
||||
P_DateTime P_LocalTime(void);
|
||||
i64 P_TimeNs(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ File system operations
|
||||
|
||||
/* NOTE: File paths use forward slash '/' as delimiter */
|
||||
|
||||
//- File system helpers
|
||||
String P_GetWritePath(Arena *arena);
|
||||
b32 P_IsFile(String path);
|
||||
b32 P_IsDir(String path);
|
||||
void P_MkDir(String path);
|
||||
|
||||
//- File creation
|
||||
P_File P_OpenFileRead(String path);
|
||||
P_File P_OpenFileReadWait(String path); /* Waits until file is not being used by another program */
|
||||
P_File P_OpenFileWrite(String path);
|
||||
P_File P_OpenFileAppend(String path);
|
||||
void P_CloseFIle(P_File file);
|
||||
|
||||
//- File data operations
|
||||
String P_ReadFile(Arena *arena, P_File file);
|
||||
void P_WriteFile(P_File file, String data);
|
||||
|
||||
//- File info
|
||||
u64 P_GetFileSize(P_File file);
|
||||
P_FileTime P_GetFileTime(P_File file);
|
||||
|
||||
////////////////////////////////
|
||||
//~ File map operations
|
||||
|
||||
P_FileMap P_OpenFileMap(P_File file);
|
||||
void P_CloseFileMap(P_FileMap map);
|
||||
String P_GetFileMapData(P_FileMap map);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Watch operations
|
||||
|
||||
/* A watch object allows the caller to watch for changes in a directory */
|
||||
|
||||
P_Watch *P_AllocWatch(String path);
|
||||
void P_ReleaseWatch(P_Watch *dw);
|
||||
P_WatchInfoList P_ReadWatchWait(Arena *arena, P_Watch *dw);
|
||||
void P_WakeWatch(P_Watch *dw);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Window operations
|
||||
|
||||
P_Window *P_AllocWindow(void);
|
||||
void P_ReleaseWindow(P_Window *window);
|
||||
|
||||
//- Window events
|
||||
P_WindowEventArray P_PopWindowEvents(Arena *arena, P_Window *window);
|
||||
|
||||
//- Window settings
|
||||
void P_UpdateWindowSettings(P_Window *window, P_WindowSettings *settings);
|
||||
P_WindowSettings P_GetWindowSettings(P_Window *window);
|
||||
void P_ShowWindow(P_Window *window);
|
||||
void P_SetWindowCursorPos(P_Window *window, V2 pos);
|
||||
void P_ShowWindowCursor(P_Window *window);
|
||||
void P_HideWindowCursor(P_Window *window);
|
||||
void P_EnableWindoweCursorClip(P_Window *window, Rect bounds);
|
||||
void P_DisableWindoweCursorClip(P_Window *window);
|
||||
void P_ToggleWindowTopmost(P_Window *window);
|
||||
|
||||
//- Window info
|
||||
V2 P_GetWindowSize(P_Window *window);
|
||||
V2 P_GetWindowMonitorSize(P_Window *window);
|
||||
u64 P_GetInternalWindowHandle(P_Window *window);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Address helpers
|
||||
|
||||
P_Address P_AddressFromString(String str);
|
||||
P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr);
|
||||
P_Address P_AddressFromPort(u16 port);
|
||||
String P_StringFromAddress(Arena *arena, P_Address address);
|
||||
b32 P_AddressIsEqual(P_Address a, P_Address b);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sock operations
|
||||
|
||||
P_Sock *P_AllocSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
|
||||
void P_ReleaseSock(P_Sock *sock);
|
||||
P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock);
|
||||
void P_WriteSock(P_Sock *sock, P_Address address, String data);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Utils
|
||||
|
||||
void P_MessageBox(P_MessageBoxKind kind, String message);
|
||||
void P_SetClipboardText(String str);
|
||||
String P_GetClipboardText(Arena *arena);
|
||||
u32 P_GetLogicalProcessorCount(void);
|
||||
u32 P_GetThreadId(void);
|
||||
i64 P_GetCurrentSchedulerPeriodNs(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sleep
|
||||
|
||||
void P_SleepPrecise(i64 sleep_time_ns);
|
||||
void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Program exit
|
||||
|
||||
void P_OnExit(P_ExitFunc *func); /* Registers a function to be called during graceful shutdown (in reverse order) */
|
||||
void P_Exit(void); /* Signals the program to shut down gracefully and run exit callbacks */
|
||||
void P_Panic(String msg); /* Forcefully exits the program and displays `msg` to the user */
|
||||
|
||||
////////////////////////////////
|
||||
//~ Entry point
|
||||
|
||||
/* Must be defined by app */
|
||||
void P_AppStartup(String args_str);
|
||||
|
||||
@ -1,72 +1,55 @@
|
||||
struct log_event_callback {
|
||||
log_event_callback_func *func;
|
||||
struct log_event_callback *next;
|
||||
i32 level;
|
||||
};
|
||||
////////////////////////////////
|
||||
//~ Global state
|
||||
|
||||
/* ========================== *
|
||||
* Global state
|
||||
* ========================== */
|
||||
P_SharedLogCtx P_shared_log_ctx = ZI;
|
||||
|
||||
struct shared_log_ctx {
|
||||
Atomic32 initialized;
|
||||
|
||||
P_Mutex callbacks_mutex;
|
||||
Arena *callbacks_arena;
|
||||
struct log_event_callback *first_callback;
|
||||
struct log_event_callback *last_callback;
|
||||
|
||||
P_File file;
|
||||
b32 file_valid;
|
||||
};
|
||||
|
||||
GLOBAL struct shared_log_ctx g_shared_log_ctx = ZI;
|
||||
GLOBAL READONLY P_LogLevelSettings g_log_settings[LOG_LEVEL_COUNT] = {
|
||||
[LOG_LEVEL_CRITICAL] = {
|
||||
READONLY P_LogLevelSettings P_log_settings[P_LogLevel_Count] = {
|
||||
[P_LogLevel_Critical] = {
|
||||
LIT_NOCAST("CRITICAL"),
|
||||
COLOR_PURPLE
|
||||
},
|
||||
|
||||
[LOG_LEVEL_ERROR] = {
|
||||
[P_LogLevel_Error] = {
|
||||
LIT_NOCAST("ERROR"),
|
||||
COLOR_RED
|
||||
},
|
||||
|
||||
[LOG_LEVEL_WARNING] = {
|
||||
[P_LogLevel_Warning] = {
|
||||
LIT_NOCAST("WARNING"),
|
||||
COLOR_YELLOW
|
||||
},
|
||||
|
||||
[LOG_LEVEL_SUCCESS] = {
|
||||
[P_LogLevel_Success] = {
|
||||
LIT_NOCAST("SUCCESS"),
|
||||
COLOR_GREEN
|
||||
},
|
||||
|
||||
[LOG_LEVEL_INFO] = {
|
||||
[P_LogLevel_Info] = {
|
||||
LIT_NOCAST("INFO"),
|
||||
COLOR_WHITE
|
||||
},
|
||||
|
||||
[LOG_LEVEL_DEBUG] = {
|
||||
[P_LogLevel_Debug] = {
|
||||
LIT_NOCAST("DEBUG"),
|
||||
COLOR_BLUE
|
||||
}
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
void log_startup(String logfile_path)
|
||||
void P_LogStartup(String logfile_path)
|
||||
{
|
||||
__prof;
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
P_SharedLogCtx *ctx = &P_shared_log_ctx;
|
||||
ctx->callbacks_arena = arena_alloc(MEBI(8));
|
||||
if (logfile_path.len > 0) {
|
||||
if (logfile_path.len > 0)
|
||||
{
|
||||
/* Create / wipe log file */
|
||||
P_CloseFIle(P_OpenFileWrite(logfile_path));
|
||||
/* Keep log file open for appending */
|
||||
if (P_IsFile(logfile_path)) {
|
||||
if (P_IsFile(logfile_path))
|
||||
{
|
||||
ctx->file = P_OpenFileAppend(logfile_path);
|
||||
ctx->file_valid = 1;
|
||||
}
|
||||
@ -74,40 +57,42 @@ void log_startup(String logfile_path)
|
||||
atomic32_fetch_set(&ctx->initialized, 1);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Callback
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Callback registration
|
||||
|
||||
void log_register_callback(log_event_callback_func *func, i32 level)
|
||||
void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level)
|
||||
{
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
P_SharedLogCtx *ctx = &P_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
P_Lock lock = snc_lock_e(&ctx->callbacks_mutex);
|
||||
P_Lock lock = P_LockE(&ctx->callbacks_mutex);
|
||||
{
|
||||
struct log_event_callback *callback = arena_push(ctx->callbacks_arena, struct log_event_callback);
|
||||
LogEventCallback *callback = arena_push(ctx->callbacks_arena, LogEventCallback);
|
||||
callback->func = func;
|
||||
callback->level = level;
|
||||
if (ctx->last_callback) {
|
||||
if (ctx->last_callback)
|
||||
{
|
||||
ctx->last_callback->next = callback;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->first_callback = callback;
|
||||
}
|
||||
ctx->last_callback = callback;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Log
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Append
|
||||
|
||||
INTERNAL void append_to_logfile(String msg)
|
||||
void P__LogAppend(String msg)
|
||||
{
|
||||
__prof;
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
P_SharedLogCtx *ctx = &P_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
|
||||
if (ctx->file_valid) {
|
||||
if (ctx->file_valid)
|
||||
{
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
String msg_line = string_cat(scratch.arena, msg, LIT("\n"));
|
||||
P_WriteFile(ctx->file, msg_line);
|
||||
@ -115,45 +100,96 @@ INTERNAL void append_to_logfile(String msg)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Panic
|
||||
|
||||
/* Panic log function is separate to enforce zero side effects other than
|
||||
* writing to log file. */
|
||||
void _log_panic(String msg)
|
||||
void P__LogPanic(String msg)
|
||||
{
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
P_SharedLogCtx *ctx = &P_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
|
||||
if (ctx->file_valid) {
|
||||
if (ctx->file_valid)
|
||||
{
|
||||
P_WriteFile(ctx->file, LIT("******** PANICKING ********\n"));
|
||||
P_WriteFile(ctx->file, msg);
|
||||
P_WriteFile(ctx->file, LIT("\n***************************\n"));
|
||||
}
|
||||
}
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
void _log(i32 level, String file, u32 line, String msg)
|
||||
////////////////////////////////
|
||||
//~ Logfv
|
||||
|
||||
#if P_IncludeLogSourceLocation
|
||||
void P__LogFV(i32 level, String file, u32 line, String fmt, va_list args)
|
||||
#else
|
||||
void _log(i32 level, String msg)
|
||||
void P__LogFV(i32 level, String fmt, va_list args)
|
||||
#endif
|
||||
{
|
||||
P_SharedLogCtx *ctx = &P_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
String msg = string_formatv(scratch.arena, fmt, args);
|
||||
#if P_IncludeLogSourceLocation
|
||||
P__log(level, file, line, msg);
|
||||
#else
|
||||
P__log(level, msg);
|
||||
#endif
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Logf
|
||||
|
||||
#if P_IncludeLogSourceLocation
|
||||
void P__LogF(i32 level, String file, u32 line, String fmt, ...)
|
||||
#else
|
||||
void P__LogF(i32 level, String fmt, ...)
|
||||
#endif
|
||||
{
|
||||
P_SharedLogCtx *ctx = &P_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
#if P_IncludeLogSourceLocation
|
||||
P__LogFV(level, file, line, fmt, args);
|
||||
#else
|
||||
P__LogFV(level, fmt, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Log
|
||||
|
||||
#if P_IncludeLogSourceLocation
|
||||
void P__log(i32 level, String file, u32 line, String msg)
|
||||
#else
|
||||
void P__log(i32 level, String msg)
|
||||
#endif
|
||||
{
|
||||
__prof;
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
P_SharedLogCtx *ctx = &P_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
|
||||
if (level < 0 || level >= LOG_LEVEL_COUNT) {
|
||||
P_LogLevelSettings settings = P_log_settings[level];
|
||||
if (level < 0 || level >= P_LogLevel_Count)
|
||||
{
|
||||
P_Panic(LIT("Invalid log level"));
|
||||
}
|
||||
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
|
||||
P_DateTime datetime = P_LocalTime();
|
||||
i64 time_ns = P_TimeNs();
|
||||
|
||||
u32 tid = P_GetThreadId();
|
||||
|
||||
P_LogLevelSettings settings = g_log_settings[level];
|
||||
|
||||
//- Format message
|
||||
P_DateTime datetime = P_LocalTime();
|
||||
i64 time_ns = P_TimeNs();
|
||||
String shorthand = settings.shorthand;
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
#if P_IncludeLogSourceLocation
|
||||
String msg_formatted = string_format(
|
||||
scratch.arena,
|
||||
LIT("[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F"),
|
||||
@ -200,65 +236,30 @@ void _log(i32 level, String msg)
|
||||
#endif
|
||||
|
||||
__profmsg((char *)msg.text, msg.len, settings.color);
|
||||
append_to_logfile(msg_formatted);
|
||||
P__LogAppend(msg_formatted);
|
||||
|
||||
|
||||
/* Run callbacks */
|
||||
//- Run callbacks
|
||||
P_LogEvent event = ZI;
|
||||
event.level = level;
|
||||
event.msg = msg;
|
||||
event.datetime = datetime;
|
||||
event.time_ns = time_ns;
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
#if P_IncludeLogSourceLocation
|
||||
event.file = file;
|
||||
event.line = line;
|
||||
#endif
|
||||
{
|
||||
P_Lock lock = snc_lock_s(&ctx->callbacks_mutex);
|
||||
for (struct log_event_callback *callback = ctx->first_callback; callback; callback = callback->next) {
|
||||
if (level <= callback->level) {
|
||||
P_Lock lock = P_LockS(&ctx->callbacks_mutex);
|
||||
for (LogEventCallback *callback = ctx->first_callback; callback; callback = callback->next)
|
||||
{
|
||||
if (level <= callback->level)
|
||||
{
|
||||
__profn("Run log callback");
|
||||
callback->func(event);
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
void _logfv(i32 level, String file, u32 line, String fmt, va_list args)
|
||||
#else
|
||||
void _logfv(i32 level, String fmt, va_list args)
|
||||
#endif
|
||||
{
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
String msg = string_formatv(scratch.arena, fmt, args);
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
_log(level, file, line, msg);
|
||||
#else
|
||||
_log(level, msg);
|
||||
#endif
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
void _logf(i32 level, String file, u32 line, String fmt, ...)
|
||||
#else
|
||||
void _logf(i32 level, String fmt, ...)
|
||||
#endif
|
||||
{
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
_logfv(level, file, line, fmt, args);
|
||||
#else
|
||||
_logfv(level, fmt, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@ -1,40 +1,9 @@
|
||||
#define LOG_LEVEL(l) (l <= LOG_LEVEL_COMPTIME)
|
||||
////////////////////////////////
|
||||
//~ Log event types
|
||||
|
||||
/* Log level configuration */
|
||||
#ifndef LOG_LEVEL_COMPTIME
|
||||
# if RTC || PROFILING
|
||||
# define LOG_LEVEL_COMPTIME LOG_LEVEL_DEBUG
|
||||
# else
|
||||
# define LOG_LEVEL_COMPTIME LOG_LEVEL_INFO
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Source location configuration */
|
||||
#ifndef LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define LOG_INCLUDE_SOURCE_LOCATION (DEBINFO)
|
||||
#endif
|
||||
|
||||
#define LOG_LEVEL_NONE -1
|
||||
#define LOG_LEVEL_CRITICAL 0
|
||||
#define LOG_LEVEL_ERROR 1
|
||||
#define LOG_LEVEL_WARNING 2
|
||||
#define LOG_LEVEL_SUCCESS 3
|
||||
#define LOG_LEVEL_INFO 4
|
||||
#define LOG_LEVEL_DEBUG 5
|
||||
#define LOG_LEVEL_COUNT 6
|
||||
|
||||
/* ========================== *
|
||||
* Callback interface
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_LogLevelSettings P_LogLevelSettings;
|
||||
struct P_LogLevelSettings {
|
||||
String shorthand;
|
||||
u32 color;
|
||||
};
|
||||
|
||||
typedef struct P_LogEvent P_LogEvent;
|
||||
struct P_LogEvent {
|
||||
//- Event
|
||||
Struct(P_LogEvent)
|
||||
{
|
||||
/* Msg lifetime is only as long as callback duration */
|
||||
String msg;
|
||||
i32 level;
|
||||
@ -42,122 +11,193 @@ struct P_LogEvent {
|
||||
P_DateTime datetime;
|
||||
i64 time_ns;
|
||||
|
||||
/* These will be zeroed if LOG_INCLUDE_SOURCE_LOCATION is disabled */
|
||||
/* These will be zeroed if P_IncludeLogSourceLocation is disabled */
|
||||
String file;
|
||||
i32 line;
|
||||
};
|
||||
|
||||
#define LOG_EVENT_CALLBACK_FUNC_DEF(name, log_event_arg) void name(P_LogEvent log_event_arg)
|
||||
typedef LOG_EVENT_CALLBACK_FUNC_DEF(log_event_callback_func, log_event);
|
||||
//- Callback
|
||||
#define P_LogEventCallbackFuncDef(name, log_event_arg) void name(P_LogEvent log_event_arg)
|
||||
typedef P_LogEventCallbackFuncDef(P_LogEventCallbackFunc, log_event);
|
||||
|
||||
void log_register_callback(log_event_callback_func *func, i32 level);
|
||||
Struct(LogEventCallback)
|
||||
{
|
||||
P_LogEventCallbackFunc *func;
|
||||
LogEventCallback *next;
|
||||
i32 level;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Logging macros
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Logging levels
|
||||
|
||||
#define log_panic(msg) _log_panic(msg)
|
||||
#define P_LogLevel(l) (l <= P_LogLevel_CompTime)
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_CRITICAL)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_critical(msg) _log(LOG_LEVEL_CRITICAL, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_critical(fmt_lit, ...) _logf(LOG_LEVEL_CRITICAL, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
/* Log level configuration */
|
||||
#ifndef P_LogLevel_CompTime
|
||||
# if RTC || PROFILING
|
||||
# define P_LogLevel_CompTime P_LogLevel_Debug
|
||||
# else
|
||||
# define log_critical(msg) _log(LOG_LEVEL_CRITICAL, msg)
|
||||
# define logf_critical(fmt_lit, ...) _logf(LOG_LEVEL_CRITICAL, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# define P_LogLevel_CompTime P_LogLevel_Info
|
||||
# endif
|
||||
#else
|
||||
# define log_critical(msg)
|
||||
# define logf_critical(...)
|
||||
#endif
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_ERROR)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_error(msg) _log(LOG_LEVEL_ERROR, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_error(fmt_lit, ...) _logf(LOG_LEVEL_ERROR, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
# define log_error(msg) _log(LOG_LEVEL_ERROR, msg)
|
||||
# define logf_error(fmt_lit, ...) _logf(LOG_LEVEL_ERROR, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define log_error(msg)
|
||||
# define logf_error(...)
|
||||
/* Source location configuration */
|
||||
#ifndef P_IncludeLogSourceLocation
|
||||
# define P_IncludeLogSourceLocation (DEBINFO)
|
||||
#endif
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_WARNING)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_warning(msg) _log(LOG_LEVEL_WARNING, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_warning(fmt_lit, ...) _logf(LOG_LEVEL_WARNING, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
#define P_LogLevel_None -1
|
||||
#define P_LogLevel_Critical 0
|
||||
#define P_LogLevel_Error 1
|
||||
#define P_LogLevel_Warning 2
|
||||
#define P_LogLevel_Success 3
|
||||
#define P_LogLevel_Info 4
|
||||
#define P_LogLevel_Debug 5
|
||||
#define P_LogLevel_Count 6
|
||||
|
||||
////////////////////////////////
|
||||
//~ Shared state
|
||||
|
||||
//- Shared context
|
||||
Struct(P_SharedLogCtx)
|
||||
{
|
||||
Atomic32 initialized;
|
||||
|
||||
P_Mutex callbacks_mutex;
|
||||
Arena *callbacks_arena;
|
||||
LogEventCallback *first_callback;
|
||||
LogEventCallback *last_callback;
|
||||
|
||||
P_File file;
|
||||
b32 file_valid;
|
||||
};
|
||||
|
||||
extern P_SharedLogCtx P_shared_log_ctx;
|
||||
|
||||
//-- Log level settings
|
||||
Struct(P_LogLevelSettings)
|
||||
{
|
||||
String shorthand;
|
||||
u32 color;
|
||||
};
|
||||
|
||||
extern READONLY P_LogLevelSettings P_log_settings[P_LogLevel_Count];
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
void P_LogStartup(String logfile_path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Logging macros
|
||||
|
||||
#define log_panic(msg) P__LogPanic(msg)
|
||||
|
||||
#if P_LogLevel(P_LogLevel_Critical)
|
||||
# if P_IncludeLogSourceLocation
|
||||
# define P_LogCritical(msg) P__log(P_LogLevel_Critical, LIT(__FILE__), __LINE__, msg)
|
||||
# define P_LogCriticalF(fmt_lit, ...) P__LogF(P_LogLevel_Critical, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
# define log_warning(msg) _log(LOG_LEVEL_WARNING, msg)
|
||||
# define logf_warning(fmt_lit, ...) _logf(LOG_LEVEL_WARNING, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# define P_LogCritical(msg) P__log(P_LogLevel_Critical, msg)
|
||||
# define P_LogCriticalF(fmt_lit, ...) P__LogF(P_LogLevel_Critical, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define log_warning(msg)
|
||||
# define logf_warning(...)
|
||||
# define P_LogCritical(msg)
|
||||
# define P_LogCriticalF(...)
|
||||
#endif
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_SUCCESS)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_success(msg) _log(LOG_LEVEL_SUCCESS, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_success(fmt_lit, ...) _logf(LOG_LEVEL_SUCCESS, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
#if P_LogLevel(P_LogLevel_Error)
|
||||
# if P_IncludeLogSourceLocation
|
||||
# define P_LogError(msg) P__log(P_LogLevel_Error, LIT(__FILE__), __LINE__, msg)
|
||||
# define P_LogErrorF(fmt_lit, ...) P__LogF(P_LogLevel_Error, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
# define log_success(msg) _log(LOG_LEVEL_SUCCESS, msg)
|
||||
# define logf_success(fmt_lit, ...) _logf(LOG_LEVEL_SUCCESS, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# define P_LogError(msg) P__log(P_LogLevel_Error, msg)
|
||||
# define P_LogErrorF(fmt_lit, ...) P__LogF(P_LogLevel_Error, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define log_success(msg)
|
||||
# define logf_success(...)
|
||||
# define P_LogError(msg)
|
||||
# define P_LogErrorF(...)
|
||||
#endif
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_INFO)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_info(msg) _log(LOG_LEVEL_INFO, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_info(fmt_lit, ...) _logf(LOG_LEVEL_INFO, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
#if P_LogLevel(P_LogLevel_Warning)
|
||||
# if P_IncludeLogSourceLocation
|
||||
# define P_LogWarning(msg) P__log(P_LogLevel_Warning, LIT(__FILE__), __LINE__, msg)
|
||||
# define P_LogWarningF(fmt_lit, ...) P__LogF(P_LogLevel_Warning, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
# define log_info(msg) _log(LOG_LEVEL_INFO, msg)
|
||||
# define logf_info(fmt_lit, ...) _logf(LOG_LEVEL_INFO, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# define P_LogWarning(msg) P__log(P_LogLevel_Warning, msg)
|
||||
# define P_LogWarningF(fmt_lit, ...) P__LogF(P_LogLevel_Warning, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define log_info(msg)
|
||||
# define logf_info(...)
|
||||
# define P_LogWarning(msg)
|
||||
# define P_LogWarningF(...)
|
||||
#endif
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_DEBUG)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_debug(msg) _log(LOG_LEVEL_DEBUG, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_debug(fmt_lit, ...) _logf(LOG_LEVEL_DEBUG, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
#if P_LogLevel(P_LogLevel_Success)
|
||||
# if P_IncludeLogSourceLocation
|
||||
# define P_LogSuccess(msg) P__log(P_LogLevel_Success, LIT(__FILE__), __LINE__, msg)
|
||||
# define P_LogSuccessF(fmt_lit, ...) P__LogF(P_LogLevel_Success, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
# define log_debug(msg) _log(LOG_LEVEL_DEBUG, msg)
|
||||
# define logf_debug(fmt_lit, ...) _logf(LOG_LEVEL_DEBUG, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# define P_LogSuccess(msg) P__log(P_LogLevel_Success, msg)
|
||||
# define P_LogSuccessF(fmt_lit, ...) P__LogF(P_LogLevel_Success, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define log_debug(msg)
|
||||
# define logf_debug(...)
|
||||
# define P_LogSuccess(msg)
|
||||
# define P_LogSuccessF(...)
|
||||
#endif
|
||||
|
||||
/* ========================== *
|
||||
* Function declarations
|
||||
* ========================== */
|
||||
|
||||
void log_startup(String logfile_path);
|
||||
|
||||
void _log_panic(String msg);
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
void _log(i32 level, String file, u32 line, String msg);
|
||||
#if P_LogLevel(P_LogLevel_Info)
|
||||
# if P_IncludeLogSourceLocation
|
||||
# define P_LogInfo(msg) P__log(P_LogLevel_Info, LIT(__FILE__), __LINE__, msg)
|
||||
# define P_LogInfoF(fmt_lit, ...) P__LogF(P_LogLevel_Info, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
void _log(i32 level, String msg);
|
||||
# define P_LogInfo(msg) P__log(P_LogLevel_Info, msg)
|
||||
# define P_LogInfoF(fmt_lit, ...) P__LogF(P_LogLevel_Info, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define P_LogInfo(msg)
|
||||
# define P_LogInfoF(...)
|
||||
#endif
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
void _logfv(i32 level, String file, u32 line, String fmt, va_list args);
|
||||
#if P_LogLevel(P_LogLevel_Debug)
|
||||
# if P_IncludeLogSourceLocation
|
||||
# define P_LogDebug(msg) P__log(P_LogLevel_Debug, LIT(__FILE__), __LINE__, msg)
|
||||
# define P_LogDebugF(fmt_lit, ...) P__LogF(P_LogLevel_Debug, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
void _logfv(i32 level, String fmt, va_list args);
|
||||
# define P_LogDebug(msg) P__log(P_LogLevel_Debug, msg)
|
||||
# define P_LogDebugF(fmt_lit, ...) P__LogF(P_LogLevel_Debug, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define P_LogDebug(msg)
|
||||
# define P_LogDebugF(...)
|
||||
#endif
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
void _logf(i32 level, String file, u32 line, String fmt, ...);
|
||||
////////////////////////////////
|
||||
//~ Callback registration
|
||||
|
||||
void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Raw log operations
|
||||
|
||||
/* NOTE: Calling these functions rather than using the logging macros may result in logs that are compiled regardless of log level. */
|
||||
|
||||
void P__LogAppend(String msg);
|
||||
void P__LogPanic(String msg);
|
||||
|
||||
#if P_IncludeLogSourceLocation
|
||||
void P__LogFV(i32 level, String file, u32 line, String fmt, va_list args);
|
||||
#else
|
||||
void _logf(i32 level, String fmt, ...);
|
||||
void P__LogFV(i32 level, String fmt, va_list args);
|
||||
#endif
|
||||
|
||||
#if P_IncludeLogSourceLocation
|
||||
void P__LogF(i32 level, String file, u32 line, String fmt, ...);
|
||||
#else
|
||||
void P__LogF(i32 level, String fmt, ...);
|
||||
#endif
|
||||
|
||||
#if P_IncludeLogSourceLocation
|
||||
void P__log(i32 level, String file, u32 line, String msg);
|
||||
#else
|
||||
void P__log(i32 level, String msg);
|
||||
#endif
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
void sys_sleep_precise(i64 sleep_time_ns)
|
||||
{
|
||||
__prof;
|
||||
|
||||
i64 big_sleep = P_GetCurrentSchedulerPeriodNs();
|
||||
i64 tolerance = (f64)big_sleep * 0.5;
|
||||
//i64 tolerance = 1000000000;
|
||||
|
||||
i64 now_ns = P_TimeNs();
|
||||
i64 target_ns = now_ns + sleep_time_ns;
|
||||
|
||||
/* Sleep */
|
||||
while (now_ns < target_ns - big_sleep - tolerance) {
|
||||
__profn("Sleep part");
|
||||
P_Wait(0, 0, 0, big_sleep);
|
||||
now_ns = P_TimeNs();
|
||||
}
|
||||
|
||||
/* Spin */
|
||||
{
|
||||
__profn("Sleep spin");
|
||||
while (now_ns < target_ns) {
|
||||
ix_pause();
|
||||
now_ns = P_TimeNs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sys_sleep_frame(i64 last_frame_time_ns, i64 target_dt_ns)
|
||||
{
|
||||
if (last_frame_time_ns != 0 && target_dt_ns > 0) {
|
||||
i64 now_ns = P_TimeNs();
|
||||
i64 last_frame_dt_ns = now_ns - last_frame_time_ns;
|
||||
i64 sleep_time_ns = target_dt_ns - last_frame_dt_ns;
|
||||
if (sleep_time_ns > 0) {
|
||||
sys_sleep_precise(sleep_time_ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
void sys_sleep_precise(i64 sleep_time_ns);
|
||||
|
||||
void sys_sleep_frame(i64 last_frame_time_ns, i64 target_dt_ns);
|
||||
@ -1,44 +1,54 @@
|
||||
#define DEFAULT_MUTEX_SPIN 4000
|
||||
////////////////////////////////
|
||||
//~ Mutex
|
||||
|
||||
/* ========================== *
|
||||
* Mutex
|
||||
* ========================== */
|
||||
|
||||
P_Lock snc_lock_spin_e(P_Mutex *m, i32 spin)
|
||||
//- Exclusive mutex lock
|
||||
P_Lock P_LockSpinE(P_Mutex *m, i32 spin)
|
||||
{
|
||||
b32 locked = 0;
|
||||
i32 spin_cnt = 0;
|
||||
while (!locked) {
|
||||
while (!locked)
|
||||
{
|
||||
++spin_cnt;
|
||||
u32 v = atomic32_fetch_test_set(&m->v, 0, 0x80000000);
|
||||
if (v == 0) {
|
||||
if (v == 0)
|
||||
{
|
||||
locked = 1;
|
||||
} else if (v == 0x40000000) {
|
||||
}
|
||||
else if (v == 0x40000000)
|
||||
{
|
||||
/* Lock has pending bit set, try to lock */
|
||||
u32 swp = atomic32_fetch_test_set(&m->v, v, 0x80000000);
|
||||
while (swp != v && swp == 0x40000000) {
|
||||
while (swp != v && swp == 0x40000000)
|
||||
{
|
||||
v = swp;
|
||||
swp = atomic32_fetch_test_set(&m->v, v, 0x80000000);
|
||||
}
|
||||
v = swp;
|
||||
if (v == 0x40000000) {
|
||||
if (v == 0x40000000)
|
||||
{
|
||||
locked = 1;
|
||||
}
|
||||
}
|
||||
if (!locked && (v & 0xC0000000) == 0) {
|
||||
if (!locked && (v & 0xC0000000) == 0)
|
||||
{
|
||||
/* Lock has shared lockers and no pending waiter, set pending bit */
|
||||
u32 swp = atomic32_fetch_test_set(&m->v, v, v | 0x40000000);
|
||||
while (swp != v && (swp & 0xC0000000) == 0 && swp != 0) {
|
||||
while (swp != v && (swp & 0xC0000000) == 0 && swp != 0)
|
||||
{
|
||||
v = swp;
|
||||
swp = atomic32_fetch_test_set(&m->v, v, v | 0x40000000);
|
||||
}
|
||||
v = swp;
|
||||
}
|
||||
/* Pause or wait */
|
||||
if (!locked && v != 0 && v != 0x40000000) {
|
||||
if (spin_cnt < spin) {
|
||||
if (!locked && v != 0 && v != 0x40000000)
|
||||
{
|
||||
if (spin_cnt < spin)
|
||||
{
|
||||
ix_pause();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
P_Wait(&m->v, &v, 4, I64_MAX);
|
||||
spin_cnt = 0;
|
||||
}
|
||||
@ -55,27 +65,37 @@ P_Lock snc_lock_spin_e(P_Mutex *m, i32 spin)
|
||||
return lock;
|
||||
}
|
||||
|
||||
P_Lock snc_lock_spin_s(P_Mutex *m, i32 spin)
|
||||
//- Shared mutex lock
|
||||
P_Lock P_LockSpinS(P_Mutex *m, i32 spin)
|
||||
{
|
||||
b32 locked = 0;
|
||||
i32 spin_cnt = 0;
|
||||
while (!locked) {
|
||||
while (!locked)
|
||||
{
|
||||
++spin_cnt;
|
||||
u32 v = atomic32_fetch(&m->v);
|
||||
while (!locked && (v & 0xC0000000) == 0) {
|
||||
while (!locked && (v & 0xC0000000) == 0)
|
||||
{
|
||||
/* Lock has no exclusive or pending exclusive lock, increment shared count */
|
||||
u32 swp = atomic32_fetch_test_set(&m->v, v, v + 1);
|
||||
if (v == swp) {
|
||||
if (v == swp)
|
||||
{
|
||||
locked = 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
v = swp;
|
||||
}
|
||||
}
|
||||
/* Pause or wait */
|
||||
if (!locked) {
|
||||
if (spin_cnt < spin) {
|
||||
if (!locked)
|
||||
{
|
||||
if (spin_cnt < spin)
|
||||
{
|
||||
ix_pause();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
P_Wait(&m->v, &v, 4, I64_MAX);
|
||||
spin_cnt = 0;
|
||||
}
|
||||
@ -86,81 +106,88 @@ P_Lock snc_lock_spin_s(P_Mutex *m, i32 spin)
|
||||
return lock;
|
||||
}
|
||||
|
||||
P_Lock snc_lock_e(P_Mutex *m)
|
||||
//- Mutex lock wrappers
|
||||
P_Lock P_LockE(P_Mutex *m)
|
||||
{
|
||||
return snc_lock_spin_e(m, DEFAULT_MUTEX_SPIN);
|
||||
return P_LockSpinE(m, P_DefaultMutexSpin);
|
||||
}
|
||||
|
||||
P_Lock snc_lock_s(P_Mutex *m)
|
||||
P_Lock P_LockS(P_Mutex *m)
|
||||
{
|
||||
return snc_lock_spin_s(m, DEFAULT_MUTEX_SPIN);
|
||||
return P_LockSpinS(m, P_DefaultMutexSpin);
|
||||
}
|
||||
|
||||
void snc_unlock(P_Lock *l)
|
||||
void P_Unlock(P_Lock *l)
|
||||
{
|
||||
P_Mutex *m = l->mutex;
|
||||
if (l->exclusive) {
|
||||
if (l->exclusive)
|
||||
{
|
||||
#if RTC
|
||||
atomic32_fetch_set(&m->exclusive_fiber_id, 0);
|
||||
#endif
|
||||
atomic32_fetch_set(&m->v, 0);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
atomic32_fetch_add(&m->v, -1);
|
||||
}
|
||||
P_Wake(&m->v, I32_MAX);
|
||||
MEMZERO_STRUCT(l);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Condition variable
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Condition variable
|
||||
|
||||
void snc_cv_wait(P_Cv *cv, P_Lock *l)
|
||||
void P_WaitOnCv(P_Cv *cv, P_Lock *l)
|
||||
{
|
||||
snc_cv_wait_time(cv, l, I64_MAX);
|
||||
P_WaitOnCvTime(cv, l, I64_MAX);
|
||||
}
|
||||
|
||||
void snc_cv_wait_time(P_Cv *cv, P_Lock *l, i64 timeout_ns)
|
||||
void P_WaitOnCvTime(P_Cv *cv, P_Lock *l, i64 timeout_ns)
|
||||
{
|
||||
u64 old_wake_gen = atomic64_fetch(&cv->wake_gen);
|
||||
P_Mutex *mutex = l->mutex;
|
||||
b32 exclusive = l->exclusive;
|
||||
{
|
||||
snc_unlock(l);
|
||||
P_Unlock(l);
|
||||
{
|
||||
P_Wait(&cv->wake_gen, &old_wake_gen, sizeof(old_wake_gen), timeout_ns);
|
||||
}
|
||||
if (exclusive) {
|
||||
*l = snc_lock_e(mutex);
|
||||
} else {
|
||||
*l = snc_lock_s(mutex);
|
||||
if (exclusive)
|
||||
{
|
||||
*l = P_LockE(mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
*l = P_LockS(mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void snc_cv_signal(P_Cv *cv, i32 count)
|
||||
void P_SignalCv(P_Cv *cv, i32 count)
|
||||
{
|
||||
atomic64_fetch_add(&cv->wake_gen, 1);
|
||||
P_Wake(&cv->wake_gen, count);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Counter
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Counter
|
||||
|
||||
void snc_counter_add(P_Counter *counter, i64 x)
|
||||
void P_CounterAdd(P_Counter *counter, i64 x)
|
||||
{
|
||||
i64 old_v = atomic64_fetch_add(&counter->v, x);
|
||||
i64 new_v = old_v + x;
|
||||
if (old_v > 0 && new_v <= 0) {
|
||||
if (old_v > 0 && new_v <= 0)
|
||||
{
|
||||
P_Wake(&counter->v, I32_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void snc_counter_wait(P_Counter *counter)
|
||||
void P_WaitOnCounter(P_Counter *counter)
|
||||
{
|
||||
i64 v = atomic64_fetch(&counter->v);
|
||||
while (v > 0) {
|
||||
while (v > 0)
|
||||
{
|
||||
P_Wait(&counter->v, &v, sizeof(v), I64_MAX);
|
||||
v = atomic64_fetch(&counter->v);
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
/* ========================== *
|
||||
* Mutex
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Mutex types
|
||||
|
||||
typedef struct P_Mutex P_Mutex;
|
||||
struct alignas(64) P_Mutex {
|
||||
#define P_DefaultMutexSpin 4000
|
||||
|
||||
AlignedStruct(P_Mutex, 64)
|
||||
{
|
||||
/* Bit 31 = Exclusive lock is held
|
||||
* Bit 30 = Exclusive lock is pending
|
||||
* Bit 0-30 = Shared locks count
|
||||
@ -20,53 +21,63 @@ struct alignas(64) P_Mutex {
|
||||
STATIC_ASSERT(sizeof(P_Mutex) == 64); /* Padding validation */
|
||||
STATIC_ASSERT(alignof(P_Mutex) == 64); /* Prevent false sharing */
|
||||
|
||||
typedef struct P_Lock P_Lock;
|
||||
struct P_Lock {
|
||||
Struct(P_Lock)
|
||||
{
|
||||
P_Mutex *mutex;
|
||||
b32 exclusive;
|
||||
};
|
||||
|
||||
P_Lock snc_lock_spin_e(P_Mutex *m, i32 spin);
|
||||
P_Lock snc_lock_spin_s(P_Mutex *m, i32 spin);
|
||||
P_Lock snc_lock_e(P_Mutex *m);
|
||||
P_Lock snc_lock_s(P_Mutex *m);
|
||||
void snc_unlock(P_Lock *lock);
|
||||
////////////////////////////////
|
||||
//~ Condition variable types
|
||||
|
||||
#if RTC
|
||||
# define snc_assert_locked_e(l, m) ASSERT((l)->mutex == (m) && (l)->exclusive == 1)
|
||||
# define snc_assert_locked_e_or_s(l, m) ASSERT((l)->mutex == (m))
|
||||
#else
|
||||
# define snc_assert_locked_e(l, m) (UNUSED)l
|
||||
# define snc_assert_locked_e_or_s(l, m) (UNUSED)l
|
||||
#endif
|
||||
|
||||
/* ========================== *
|
||||
* Condition variable
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_Cv P_Cv;
|
||||
struct alignas(64) P_Cv {
|
||||
AlignedStruct(P_Cv, 64)
|
||||
{
|
||||
Atomic64 wake_gen;
|
||||
u8 _pad[56];
|
||||
};
|
||||
STATIC_ASSERT(sizeof(P_Cv) == 64); /* Padding validation */
|
||||
STATIC_ASSERT(alignof(P_Cv) == 64); /* Prevent false sharing */
|
||||
|
||||
void snc_cv_wait(P_Cv *cv, P_Lock *lock);
|
||||
void snc_cv_wait_time(P_Cv *cv, P_Lock *l, i64 timeout_ns);
|
||||
void snc_cv_signal(P_Cv *cv, i32 count);
|
||||
////////////////////////////////
|
||||
//~ Counter types
|
||||
|
||||
/* ========================== *
|
||||
* Counter
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_Counter P_Counter;
|
||||
struct alignas(64) P_Counter {
|
||||
AlignedStruct(P_Counter, 64)
|
||||
{
|
||||
Atomic64 v;
|
||||
u8 _pad[56];
|
||||
};
|
||||
STATIC_ASSERT(sizeof(P_Counter) == 64); /* Padding validation */
|
||||
STATIC_ASSERT(alignof(P_Counter) == 64); /* Prevent false sharing */
|
||||
|
||||
void snc_counter_add(P_Counter *counter, i64 x);
|
||||
void snc_counter_wait(P_Counter *counter);
|
||||
////////////////////////////////
|
||||
//~ Mutex operations
|
||||
|
||||
P_Lock P_LockSpinE(P_Mutex *m, i32 spin);
|
||||
P_Lock P_LockSpinS(P_Mutex *m, i32 spin);
|
||||
|
||||
P_Lock P_LockE(P_Mutex *m);
|
||||
P_Lock P_LockS(P_Mutex *m);
|
||||
|
||||
void P_Unlock(P_Lock *lock);
|
||||
|
||||
//- Lock assertion
|
||||
#if RTC
|
||||
# define P_AssertLockedE(l, m) ASSERT((l)->mutex == (m) && (l)->exclusive == 1)
|
||||
# define P_AssertLockedES(l, m) ASSERT((l)->mutex == (m))
|
||||
#else
|
||||
# define P_AssertLockedE(l, m) (UNUSED)l
|
||||
# define P_AssertLockedES(l, m) (UNUSED)l
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ Condition variable operations
|
||||
|
||||
void P_WaitOnCv(P_Cv *cv, P_Lock *lock);
|
||||
void P_WaitOnCvTime(P_Cv *cv, P_Lock *l, i64 timeout_ns);
|
||||
void P_SignalCv(P_Cv *cv, i32 count);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Counter operations
|
||||
|
||||
void P_CounterAdd(P_Counter *counter, i64 x);
|
||||
void P_WaitOnCounter(P_Counter *counter);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,63 +1,21 @@
|
||||
#pragma warning(push, 0)
|
||||
# define UNICODE
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <Windows.h>
|
||||
# include <WinSock2.h>
|
||||
# include <TlHelp32.h>
|
||||
# include <WS2tcpip.h>
|
||||
# include <windowsx.h>
|
||||
# include <ShlObj_core.h>
|
||||
# include <fileapi.h>
|
||||
# include <dwmapi.h>
|
||||
# include <bcrypt.h>
|
||||
# include <avrt.h>
|
||||
# include <shellapi.h>
|
||||
#pragma warning(pop)
|
||||
////////////////////////////////
|
||||
//~ Ticket mutex types
|
||||
|
||||
#define P_W32_WindowClassName L"power_play_window_class"
|
||||
|
||||
#define P_W32_ThreadStackSize KIBI(64)
|
||||
#define P_W32_FiberStackSize MEBI(4)
|
||||
|
||||
#define P_W32_ThreadDef(name, arg_name) void name(void *arg_name)
|
||||
typedef P_W32_ThreadDef(P_W32_ThreadFunc, data);
|
||||
|
||||
/* Assume scheduler cycle is 20hz at start to be conservative */
|
||||
#define P_W32_DefaultSchedulerPeriodNs 50000000
|
||||
#define P_W32_NumRollingSchedulerPeriods 1000
|
||||
|
||||
#define P_W32_FiberNamePrefixCstr "Fiber ["
|
||||
#define P_W32_FiberNameSuffixCstr "]"
|
||||
#define P_W32_FiberNameMaxSize 64
|
||||
|
||||
#define P_W32_NumWaitAddrBins 16384
|
||||
#define P_W32_NumWaitTimeBins 1024
|
||||
|
||||
#define P_W32_MaxOnExitFuncs 1024
|
||||
|
||||
/* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */
|
||||
#define P_W32_WakeAllThreshold 16
|
||||
|
||||
/* ========================== *
|
||||
* Ticket mutex
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_TicketMutex P_W32_TicketMutex;
|
||||
struct P_W32_TicketMutex {
|
||||
Struct(P_W32_TicketMutex)
|
||||
{
|
||||
Atomic64Padded ticket;
|
||||
Atomic64Padded serving;
|
||||
};
|
||||
|
||||
void P_W32_LockTicketMutex(P_W32_TicketMutex *tm);
|
||||
////////////////////////////////
|
||||
//~ Thread types
|
||||
|
||||
void P_W32_UnlockTicketMutex(P_W32_TicketMutex *tm);
|
||||
#define P_W32_ThreadStackSize KIBI(64)
|
||||
#define P_W32_ThreadDef(name, arg_name) void name(void *arg_name)
|
||||
typedef P_W32_ThreadDef(P_W32_ThreadFunc, data);
|
||||
|
||||
/* ========================== *
|
||||
* Thread
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_Thread P_W32_Thread;
|
||||
struct P_W32_Thread {
|
||||
Struct(P_W32_Thread)
|
||||
{
|
||||
P_W32_ThreadFunc *entry_point;
|
||||
void *thread_data;
|
||||
char thread_name_cstr[256];
|
||||
@ -70,22 +28,11 @@ struct P_W32_Thread {
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
DWORD WINAPI P_W32_Win32ThreadProc(LPVOID vt);
|
||||
////////////////////////////////
|
||||
//~ Wait list types
|
||||
|
||||
P_W32_Thread *P_W32_AllocThread(P_W32_ThreadFunc *entry_point, void *thread_data, String thread_name, i32 profiler_group);
|
||||
|
||||
b32 P_W32_TryReleaseThread(P_W32_Thread *thread, f32 timeout_seconds);
|
||||
|
||||
void P_W32_WaitReleaseThread(P_W32_Thread *thread);
|
||||
|
||||
/* ========================== *
|
||||
* Wait list
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_JobPool P_W32_JobPool;
|
||||
|
||||
typedef struct P_W32_WaitList P_W32_WaitList;
|
||||
struct alignas(64) P_W32_WaitList {
|
||||
AlignedStruct(P_W32_WaitList, 64)
|
||||
{
|
||||
u64 value;
|
||||
i16 first_waiter;
|
||||
i16 last_waiter;
|
||||
@ -95,8 +42,8 @@ struct alignas(64) P_W32_WaitList {
|
||||
};
|
||||
STATIC_ASSERT(alignof(P_W32_WaitList) == 64); /* Avoid false sharing */
|
||||
|
||||
typedef struct P_W32_WaitBin P_W32_WaitBin;
|
||||
struct alignas(64) P_W32_WaitBin {
|
||||
AlignedStruct(P_W32_WaitBin, 64)
|
||||
{
|
||||
P_W32_WaitList *first_wait_list;
|
||||
P_W32_WaitList *last_wait_list;
|
||||
P_W32_WaitList *first_free_wait_list;
|
||||
@ -104,30 +51,31 @@ struct alignas(64) P_W32_WaitBin {
|
||||
};
|
||||
STATIC_ASSERT(alignof(P_W32_WaitBin) == 64); /* Avoid false sharing */
|
||||
|
||||
typedef struct P_W32_Fiber P_W32_Fiber;
|
||||
void P_W32_WakeLockedFibers(i32 num_fibers, P_W32_Fiber **fibers);
|
||||
////////////////////////////////
|
||||
//~ Fiber types
|
||||
|
||||
void P_W32_WakeByAddress(void *addr, i32 count);
|
||||
#define P_W32_FiberStackSize MEBI(4)
|
||||
#define P_W32_FiberNamePrefixCstr "Fiber ["
|
||||
#define P_W32_FiberNameSuffixCstr "]"
|
||||
#define P_W32_FiberNameMaxSize 64
|
||||
|
||||
void P_W32_WakeByTime(u64 time);
|
||||
|
||||
/* ========================== *
|
||||
* Fiber
|
||||
* ========================== */
|
||||
|
||||
typedef enum P_W32_YieldKind {
|
||||
//- Yield param
|
||||
typedef i32 P_W32_YieldKind; enum
|
||||
{
|
||||
P_W32_YieldKind_None,
|
||||
P_W32_YieldKind_Done,
|
||||
P_W32_YieldKind_Wait,
|
||||
|
||||
P_W32_YieldKind_Count
|
||||
} P_W32_YieldKind;
|
||||
};
|
||||
|
||||
typedef struct P_W32_YieldParam P_W32_YieldParam;
|
||||
struct P_W32_YieldParam {
|
||||
Struct(P_W32_YieldParam)
|
||||
{
|
||||
P_W32_YieldKind kind;
|
||||
union {
|
||||
struct {
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
volatile void *addr;
|
||||
void *cmp;
|
||||
u32 size;
|
||||
@ -136,8 +84,9 @@ struct P_W32_YieldParam {
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct P_W32_Fiber P_W32_Fiber;
|
||||
struct alignas(64) P_W32_Fiber {
|
||||
//- Fiber
|
||||
AlignedStruct(P_W32_Fiber, 64)
|
||||
{
|
||||
/* ---------------------------------------------------- */
|
||||
void *addr; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
@ -181,30 +130,19 @@ STATIC_ASSERT(sizeof(P_W32_Fiber) == 128); /* Padding validation (increase if n
|
||||
STATIC_ASSERT(alignof(P_W32_Fiber) == 64); /* Avoid false sharing */
|
||||
STATIC_ASSERT(offsetof(P_W32_Fiber, wake_lock) % 4 == 0); /* Atomic must be aligned */
|
||||
|
||||
P_W32_Fiber *P_W32_AllocFiber(P_W32_JobPool *pool);
|
||||
////////////////////////////////
|
||||
//~ Job queue types
|
||||
|
||||
void P_W32_ReleaseFiber(P_W32_JobPool *pool, P_W32_Fiber *fiber);
|
||||
|
||||
FORCE_INLINE P_W32_Fiber *P_W32_FiberFromId(i16 id);
|
||||
|
||||
FORCE_NO_INLINE void P_W32_FiberResume(P_W32_Fiber *fiber);
|
||||
|
||||
void P_W32_YieldFiber(P_W32_Fiber *fiber, P_W32_Fiber *parent_fiber);
|
||||
|
||||
void P_W32_FiberEntryPoint(void *id_ptr);
|
||||
|
||||
/* ========================== *
|
||||
* Job queue
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_WorkerCtx P_W32_WorkerCtx;
|
||||
struct alignas(64) P_W32_WorkerCtx {
|
||||
//- Worker ctx
|
||||
AlignedStruct(P_W32_WorkerCtx, 64)
|
||||
{
|
||||
P_Pool pool_kind;
|
||||
i32 id;
|
||||
};
|
||||
|
||||
typedef struct P_W32_JobInfo P_W32_JobInfo;
|
||||
struct P_W32_JobInfo {
|
||||
//- Job info
|
||||
Struct(P_W32_JobInfo)
|
||||
{
|
||||
i32 num_dispatched;
|
||||
|
||||
i32 count;
|
||||
@ -217,8 +155,9 @@ struct P_W32_JobInfo {
|
||||
P_W32_JobInfo *next;
|
||||
};
|
||||
|
||||
typedef struct P_W32_JobQueue P_W32_JobQueue;
|
||||
struct alignas(64) P_W32_JobQueue {
|
||||
//- Job queue
|
||||
AlignedStruct(P_W32_JobQueue, 64)
|
||||
{
|
||||
P_W32_TicketMutex lock;
|
||||
Arena *arena;
|
||||
|
||||
@ -228,8 +167,9 @@ struct alignas(64) P_W32_JobQueue {
|
||||
P_W32_JobInfo *first_free;
|
||||
};
|
||||
|
||||
typedef struct P_W32_JobPool P_W32_JobPool;
|
||||
struct alignas(64) P_W32_JobPool {
|
||||
//- Job pool
|
||||
AlignedStruct(P_W32_JobPool, 64)
|
||||
{
|
||||
/* Jobs */
|
||||
P_W32_JobQueue job_queues[P_Priority_Count];
|
||||
|
||||
@ -250,37 +190,21 @@ struct alignas(64) P_W32_JobPool {
|
||||
P_W32_WorkerCtx *worker_contexts;
|
||||
};
|
||||
|
||||
P_W32_ThreadDef(P_W32_JobWorkerEntryFunc, worker_ctx_arg);
|
||||
////////////////////////////////
|
||||
//~ Window types
|
||||
|
||||
P_W32_ThreadDef(P_W32_JobSchedulerEntryFunc, _);
|
||||
|
||||
/* ========================== *
|
||||
* Time
|
||||
* ========================== */
|
||||
|
||||
P_DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st);
|
||||
|
||||
/* ========================== *
|
||||
* File system
|
||||
* ========================== */
|
||||
|
||||
String P_W32_StringFromWin32Path(Arena *arena, wchar_t *src);
|
||||
|
||||
/* ========================== *
|
||||
* Window
|
||||
* ========================== */
|
||||
|
||||
typedef enum P_W32_CursorFlag {
|
||||
typedef i32 P_W32_CursorFlag; enum
|
||||
{
|
||||
P_W32_CursorFlag_None = (0 << 0),
|
||||
P_W32_CursorFlag_Position = (1 << 0),
|
||||
P_W32_CursorFlag_Hide = (1 << 1),
|
||||
P_W32_CursorFlag_Show = (1 << 2),
|
||||
P_W32_CursorFlag_EnableClip = (1 << 3),
|
||||
P_W32_CursorFlag_DisableClip = (1 << 4)
|
||||
} P_W32_CursorFlag;
|
||||
};
|
||||
|
||||
typedef struct P_W32_Window P_W32_Window;
|
||||
struct P_W32_Window {
|
||||
Struct(P_W32_Window)
|
||||
{
|
||||
u32 flags;
|
||||
|
||||
HWND hwnd;
|
||||
@ -316,45 +240,26 @@ struct P_W32_Window {
|
||||
P_W32_Window *next_free;
|
||||
};
|
||||
|
||||
void P_W32_ProcessWindowEvent(P_W32_Window *window, P_WindowEvent event);
|
||||
////////////////////////////////
|
||||
//~ Watch types
|
||||
|
||||
HWND P_W32_InitWindow(P_W32_Window *window);
|
||||
|
||||
P_W32_ThreadDef(P_W32_WindowThreadEntryFunc, arg);
|
||||
|
||||
P_W32_Window *P_W32_AllocWindow(void);
|
||||
|
||||
void P_W32_ReleaseWindow(P_W32_Window *window);
|
||||
|
||||
void P_W32_UpdateWindowFromSystem(P_W32_Window *window);
|
||||
|
||||
void P_W32_UpdateWindowFromSettings(P_W32_Window *window, P_WindowSettings *settings);
|
||||
|
||||
void P_W32_WakeWindow(P_W32_Window *window);
|
||||
|
||||
LRESULT CALLBACK P_W32_Win32WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
/* ========================== *
|
||||
* Watch
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_Watch P_W32_Watch;
|
||||
struct P_W32_Watch {
|
||||
Struct(P_W32_Watch)
|
||||
{
|
||||
HANDLE dir_handle;
|
||||
HANDLE wake_handle;
|
||||
P_W32_Watch *next_free;
|
||||
u8 results_buff[KIBI(64)];
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Address
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Address types
|
||||
|
||||
typedef struct P_W32_Address P_W32_Address;
|
||||
struct P_W32_Address {
|
||||
Struct(P_W32_Address)
|
||||
{
|
||||
i32 size;
|
||||
i32 family;
|
||||
union {
|
||||
union
|
||||
{
|
||||
struct sockaddr_storage sas;
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
@ -362,40 +267,34 @@ struct P_W32_Address {
|
||||
};
|
||||
};
|
||||
|
||||
P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr);
|
||||
////////////////////////////////
|
||||
//~ Sock types
|
||||
|
||||
/* If supplied address has ip INADDR_ANY (0), convert ip to localhost */
|
||||
P_W32_Address P_W32_ConvertAnyaddrToLocalhost(P_W32_Address addr);
|
||||
|
||||
P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr);
|
||||
|
||||
/* ========================== *
|
||||
* Sock
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_Sock P_W32_Sock;
|
||||
struct P_W32_Sock {
|
||||
Struct(P_W32_Sock)
|
||||
{
|
||||
SOCKET sock;
|
||||
P_W32_Sock *next_free;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Entry
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Shared state
|
||||
|
||||
#define P_W32_WindowClassName L"power_play_window_class"
|
||||
|
||||
void P_W32_InitBtnTable(void);
|
||||
/* Assume scheduler cycle is 20hz at start to be conservative */
|
||||
#define P_W32_DefaultSchedulerPeriodNs 50000000
|
||||
#define P_W32_NumRollingSchedulerPeriods 1000
|
||||
|
||||
P_JobDef(P_W32_AppStartupJob, _);
|
||||
#define P_W32_NumWaitAddrBins 16384
|
||||
#define P_W32_NumWaitTimeBins 1024
|
||||
|
||||
P_JobDef(P_W32_AppShutdownJob, _);
|
||||
#define P_W32_MaxOnExitFuncs 1024
|
||||
|
||||
/* ========================== *
|
||||
* Global state
|
||||
* ========================== */
|
||||
/* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */
|
||||
#define P_W32_WakeAllThreshold 16
|
||||
|
||||
typedef struct P_W32_Ctx P_W32_Ctx;
|
||||
struct P_W32_Ctx {
|
||||
Struct(P_W32_SharedCtx)
|
||||
{
|
||||
SYSTEM_INFO info;
|
||||
i64 timer_start_qpc;
|
||||
i64 ns_per_qpc;
|
||||
@ -404,7 +303,7 @@ struct P_W32_Ctx {
|
||||
|
||||
wchar_t cmdline_args_wstr[8192];
|
||||
|
||||
/* Application control flow */
|
||||
//- Application control flow
|
||||
Atomic32 panicking;
|
||||
wchar_t panic_wstr[4096];
|
||||
HANDLE panic_event;
|
||||
@ -412,58 +311,136 @@ struct P_W32_Ctx {
|
||||
HANDLE exit_begin_event;
|
||||
HANDLE exit_end_event;
|
||||
|
||||
/* Key lookup table */
|
||||
//- Key lookup table
|
||||
P_Btn vk_btn_table[256];
|
||||
|
||||
/* Threads pool */
|
||||
//- Worker thread pool
|
||||
P_Mutex threads_mutex;
|
||||
Arena *threads_arena;
|
||||
P_W32_Thread *first_thread;
|
||||
P_W32_Thread *last_thread;
|
||||
P_W32_Thread *first_free_thread;
|
||||
|
||||
/* Watches pool */
|
||||
//- Watches pool
|
||||
P_Mutex watches_mutex;
|
||||
Arena *watches_arena;
|
||||
P_W32_Watch *watches_first_free;
|
||||
|
||||
/* Windows pool */
|
||||
//- Windows pool
|
||||
WNDCLASSEXW window_class;
|
||||
P_Mutex windows_mutex;
|
||||
Arena *windows_arena;
|
||||
P_W32_Window *first_free_window;
|
||||
|
||||
/* Sockets pool */
|
||||
//- Socket pool
|
||||
WSADATA wsa_data;
|
||||
Arena *socks_arena;
|
||||
P_Mutex socks_mutex;
|
||||
P_W32_Sock *first_free_sock;
|
||||
|
||||
/* Exit funcs */
|
||||
//- Exit funcs
|
||||
Atomic32 num_exit_funcs;
|
||||
P_ExitFunc *exit_funcs[P_W32_MaxOnExitFuncs];
|
||||
|
||||
/* Scheduler */
|
||||
//- Scheduler
|
||||
Atomic64Padded current_scheduler_cycle;
|
||||
Atomic64Padded current_scheduler_cycle_period_ns;
|
||||
|
||||
/* Fibers */
|
||||
//- Fibers
|
||||
P_W32_TicketMutex fibers_lock;
|
||||
i16 num_fibers;
|
||||
Arena *fiber_names_arena;
|
||||
P_W32_Fiber fibers[MAX_FIBERS];
|
||||
|
||||
/* Wait lists */
|
||||
//- Wait lists
|
||||
Atomic64Padded waiter_wake_gen;
|
||||
P_W32_TicketMutex wait_lists_arena_lock;
|
||||
Arena *wait_lists_arena;
|
||||
|
||||
/* Wait tables */
|
||||
//- Wait tables
|
||||
P_W32_WaitBin wait_addr_bins[P_W32_NumWaitAddrBins];
|
||||
P_W32_WaitBin wait_time_bins[P_W32_NumWaitTimeBins];
|
||||
|
||||
/* Job pools */
|
||||
//- Job pools
|
||||
P_W32_JobPool job_pools[P_Pool_Count];
|
||||
};
|
||||
|
||||
extern P_W32_Ctx P_W32_g_shared_ctx;
|
||||
extern P_W32_SharedCtx P_W32_shared_ctx;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Ticket mutex operations
|
||||
|
||||
void P_W32_LockTicketMutex(P_W32_TicketMutex *tm);
|
||||
void P_W32_UnlockTicketMutex(P_W32_TicketMutex *tm);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Thread operations
|
||||
|
||||
DWORD WINAPI P_W32_Win32ThreadProc(LPVOID vt);
|
||||
P_W32_Thread *P_W32_AllocThread(P_W32_ThreadFunc *entry_point, void *thread_data, String thread_name, i32 profiler_group);
|
||||
b32 P_W32_TryReleaseThread(P_W32_Thread *thread, f32 timeout_seconds);
|
||||
void P_W32_WaitReleaseThread(P_W32_Thread *thread);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Wait list operations
|
||||
|
||||
void P_W32_WakeLockedFibers(i32 num_fibers, P_W32_Fiber **fibers);
|
||||
void P_W32_WakeByAddress(void *addr, i32 count);
|
||||
void P_W32_WakeByTime(u64 time);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Fiber operations
|
||||
|
||||
P_W32_Fiber *P_W32_AllocFiber(P_W32_JobPool *pool);
|
||||
void P_W32_ReleaseFiber(P_W32_JobPool *pool, P_W32_Fiber *fiber);
|
||||
FORCE_INLINE P_W32_Fiber *P_W32_FiberFromId(i16 id);
|
||||
FORCE_NO_INLINE void P_W32_FiberResume(P_W32_Fiber *fiber);
|
||||
void P_W32_YieldFiber(P_W32_Fiber *fiber, P_W32_Fiber *parent_fiber);
|
||||
void P_W32_FiberEntryPoint(void *id_ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Workers
|
||||
|
||||
P_W32_ThreadDef(P_W32_JobWorkerEntryFunc, worker_ctx_arg);
|
||||
P_W32_ThreadDef(P_W32_JobSchedulerEntryFunc, _);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Time operations
|
||||
|
||||
P_DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st);
|
||||
|
||||
////////////////////////////////
|
||||
//~ File system operations
|
||||
|
||||
String P_W32_StringFromWin32Path(Arena *arena, wchar_t *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Window operations
|
||||
|
||||
P_W32_Window *P_W32_AllocWindow(void);
|
||||
void P_W32_ReleaseWindow(P_W32_Window *window);
|
||||
HWND P_W32_InitWindow(P_W32_Window *window);
|
||||
|
||||
//- Window settings
|
||||
void P_W32_UpdateWindowFromSystem(P_W32_Window *window);
|
||||
void P_W32_UpdateWindowFromSettings(P_W32_Window *window, P_WindowSettings *settings);
|
||||
|
||||
//- Window thread
|
||||
P_W32_ThreadDef(P_W32_WindowThreadEntryFunc, arg);
|
||||
void P_W32_ProcessWindowEvent(P_W32_Window *window, P_WindowEvent event);
|
||||
void P_W32_WakeWindow(P_W32_Window *window);
|
||||
LRESULT CALLBACK P_W32_Win32WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Address operations
|
||||
|
||||
P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr);
|
||||
P_W32_Address P_W32_ConvertAnyaddrToLocalhost(P_W32_Address addr);
|
||||
P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Entry point
|
||||
|
||||
void P_W32_InitBtnTable(void);
|
||||
P_JobDef(P_W32_AppStartupJob, _);
|
||||
P_JobDef(P_W32_AppShutdownJob, _);
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
typedef struct PB_StartupReceipt PB_StartupReceipt;
|
||||
struct PB_StartupReceipt { i32 _; };
|
||||
Struct(PB_StartupReceipt) { i32 _; };
|
||||
PB_StartupReceipt playback_startup(M_StartupReceipt *mixer_sr);
|
||||
|
||||
@ -62,7 +62,7 @@ INTERNAL P_ExitFuncDef(playback_shutdown)
|
||||
{
|
||||
__prof;
|
||||
atomic32_fetch_set(&G.shutdown, 1);
|
||||
snc_counter_wait(&G.playback_job_counter);
|
||||
P_WaitOnCounter(&G.playback_job_counter);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
|
||||
@ -3,8 +3,7 @@
|
||||
/* A resource contains data that can be retrieved globally by name.
|
||||
* If enabled during compilation, resource data is embedded in the
|
||||
* executable. Otherwise each resource represents a file on disk. */
|
||||
typedef struct R_Resource R_Resource;
|
||||
struct R_Resource {
|
||||
Struct(R_Resource) {
|
||||
String _data;
|
||||
b32 _exists;
|
||||
#if RESOURCES_EMBEDDED
|
||||
@ -21,8 +20,7 @@ struct R_Resource {
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
typedef struct R_StartupReceipt R_StartupReceipt;
|
||||
struct R_StartupReceipt { i32 _; };
|
||||
Struct(R_StartupReceipt) { i32 _; };
|
||||
R_StartupReceipt resource_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
|
||||
@ -37,7 +37,7 @@ GLOBAL struct {
|
||||
ClientStore *nil_client_store;
|
||||
Client *nil_client;
|
||||
Snapshot *nil_snapshot;
|
||||
struct sim_ent *nil_ent;
|
||||
Ent *nil_ent;
|
||||
} G = ZI, DEBUG_ALIAS(G, G_sim);
|
||||
|
||||
/* Accessed via `sim_client_store_nil()` */
|
||||
@ -50,7 +50,7 @@ READONLY Client **_g_sim_client_nil = &G.nil_client;
|
||||
READONLY Snapshot **_g_sim_snapshot_nil = &G.nil_snapshot;
|
||||
|
||||
/* Accessed via `sim_ent_nil()` */
|
||||
READONLY struct sim_ent **_g_sim_ent_nil = &G.nil_ent;
|
||||
READONLY Ent **_g_sim_ent_nil = &G.nil_ent;
|
||||
|
||||
SimStartupReceipt sim_startup(void)
|
||||
{
|
||||
@ -72,7 +72,7 @@ SimStartupReceipt sim_startup(void)
|
||||
G.nil_snapshot->client = sim_client_nil();
|
||||
|
||||
/* Nil ent */
|
||||
G.nil_ent = arena_push(G.nil_arena, struct sim_ent);
|
||||
G.nil_ent = arena_push(G.nil_arena, Ent);
|
||||
G.nil_ent->ss = sim_snapshot_nil();
|
||||
G.nil_ent->valid = 0;
|
||||
G.nil_ent->id = SIM_ENT_NIL_ID;
|
||||
@ -312,7 +312,7 @@ Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick)
|
||||
|
||||
/* Copy id lookup bins */
|
||||
ss->num_id_bins = src->num_id_bins > 0 ? src->num_id_bins : ID_LOOKUP_BINS;
|
||||
ss->id_bins = arena_push_array_no_zero(ss->arena, struct sim_ent_bin, ss->num_id_bins);
|
||||
ss->id_bins = arena_push_array_no_zero(ss->arena, EntBin, ss->num_id_bins);
|
||||
if (src->num_id_bins > 0) {
|
||||
for (u64 i = 0; i < src->num_id_bins; ++i) {
|
||||
ss->id_bins[i] = src->id_bins[i];
|
||||
@ -325,20 +325,20 @@ Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick)
|
||||
ss->first_free_ent = src->first_free_ent;
|
||||
ss->num_ents_allocated = src->num_ents_allocated;
|
||||
ss->num_ents_reserved = src->num_ents_reserved;
|
||||
ss->ents = arena_push_array_no_zero(ss->ents_arena, struct sim_ent, ss->num_ents_reserved);
|
||||
ss->ents = arena_push_array_no_zero(ss->ents_arena, Ent, ss->num_ents_reserved);
|
||||
if (ss->num_ents_reserved == 0) {
|
||||
/* Copying from nil snapshot, need to create blank & root entity */
|
||||
|
||||
/* Push blank ent at index 0 (because index 0 is never valid anyway since it maps to sim_ent_nil()) */
|
||||
{
|
||||
arena_push(ss->ents_arena, struct sim_ent);
|
||||
arena_push(ss->ents_arena, Ent);
|
||||
++ss->num_ents_allocated;
|
||||
++ss->num_ents_reserved;
|
||||
}
|
||||
|
||||
/* Push root ent with constant id */
|
||||
{
|
||||
struct sim_ent *root = arena_push_no_zero(ss->ents_arena, struct sim_ent);
|
||||
Ent *root = arena_push_no_zero(ss->ents_arena, Ent);
|
||||
*root = *sim_ent_nil();
|
||||
root->ss = ss;
|
||||
root->valid = 1;
|
||||
@ -351,8 +351,8 @@ Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick)
|
||||
}
|
||||
} else {
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *dst_ent = &ss->ents[i];
|
||||
struct sim_ent *src_ent = &src->ents[i];
|
||||
Ent *dst_ent = &ss->ents[i];
|
||||
Ent *src_ent = &src->ents[i];
|
||||
*dst_ent = *src_ent;
|
||||
dst_ent->ss = ss;
|
||||
}
|
||||
@ -594,9 +594,9 @@ void sim_snapshot_set_tile(Snapshot *ss, V2i32 world_tile_index, TileKind tile_k
|
||||
V2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
||||
|
||||
EntId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||
struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
Ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
if (!chunk_ent->valid) {
|
||||
struct sim_ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
Ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
chunk_ent = sim_ent_alloc_sync_src_with_id(root, chunk_id);
|
||||
sim_ent_enable_prop(chunk_ent, SEPROP_TILE_CHUNK);
|
||||
chunk_ent->tile_chunk_index = chunk_index;
|
||||
@ -645,9 +645,9 @@ Snapshot *sim_snapshot_alloc_from_lerp(Client *client, Snapshot *ss0, Snapshot *
|
||||
__profn("Lerp snapshot entities");
|
||||
u64 num_entities = min_u64(ss0->num_ents_reserved, ss1->num_ents_reserved);
|
||||
for (u64 i = 0; i < num_entities; ++i) {
|
||||
struct sim_ent *e = &ss->ents[i];
|
||||
struct sim_ent *e0 = &ss0->ents[i];
|
||||
struct sim_ent *e1 = &ss1->ents[i];
|
||||
Ent *e = &ss->ents[i];
|
||||
Ent *e0 = &ss0->ents[i];
|
||||
Ent *e1 = &ss1->ents[i];
|
||||
sim_ent_lerp(e, e0, e1, blend);
|
||||
}
|
||||
}
|
||||
@ -670,24 +670,24 @@ void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntId remot
|
||||
* - Determine new UUIDs for newly created ents
|
||||
*/
|
||||
|
||||
struct sim_ent *local_root = sim_ent_from_id(local_ss, SIM_ENT_ROOT_ID);
|
||||
struct sim_ent *remote_root = sim_ent_from_id(remote_ss, SIM_ENT_ROOT_ID);
|
||||
Ent *local_root = sim_ent_from_id(local_ss, SIM_ENT_ROOT_ID);
|
||||
Ent *remote_root = sim_ent_from_id(remote_ss, SIM_ENT_ROOT_ID);
|
||||
|
||||
/* Create new ents from remote */
|
||||
for (struct sim_ent *remote_top = sim_ent_from_id(remote_ss, remote_root->first); remote_top->valid; remote_top = sim_ent_from_id(remote_ss, remote_top->next)) {
|
||||
for (Ent *remote_top = sim_ent_from_id(remote_ss, remote_root->first); remote_top->valid; remote_top = sim_ent_from_id(remote_ss, remote_top->next)) {
|
||||
sim_ent_sync_alloc_tree(local_root, remote_top, remote_player);
|
||||
}
|
||||
|
||||
/* Sync ents with remote, skipping index 0 (nil) & index 1 (root) */
|
||||
for (u64 i = 2; i < local_ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *local_ent = &local_ss->ents[i];
|
||||
Ent *local_ent = &local_ss->ents[i];
|
||||
if (local_ent->valid && sim_ent_has_prop(local_ent, SEPROP_SYNC_DST)) {
|
||||
b32 should_sync = sim_ent_id_eq(local_ent->owner, remote_player) || sim_ent_id_is_nil(remote_player);
|
||||
if ((sync_flags & SIM_SYNC_FLAG_NOSYNC_PREDICTABLES) && sim_ent_id_eq(local_ent->predictor, local_ss->local_player)) {
|
||||
should_sync = 0;
|
||||
}
|
||||
if (should_sync) {
|
||||
struct sim_ent *remote_ent = sim_ent_from_id(remote_ss, local_ent->id);
|
||||
Ent *remote_ent = sim_ent_from_id(remote_ss, local_ent->id);
|
||||
if (remote_ent->valid) {
|
||||
/* Copy all ent data from remote */
|
||||
sim_ent_sync(local_ent, remote_ent);
|
||||
@ -741,11 +741,11 @@ void sim_snapshot_encode(BitbuffWriter *bw, Client *receiver, Snapshot *ss0, Sna
|
||||
u32 old_first = 0;
|
||||
u32 old_last = 0;
|
||||
if (i < ss0->num_id_bins) {
|
||||
struct sim_ent_bin *old_bin = &ss0->id_bins[i];
|
||||
EntBin *old_bin = &ss0->id_bins[i];
|
||||
old_first = old_bin->first;
|
||||
old_last = old_bin->last;
|
||||
}
|
||||
struct sim_ent_bin *bin = &ss1->id_bins[i];
|
||||
EntBin *bin = &ss1->id_bins[i];
|
||||
b32 first_diff = bin->first != old_first;
|
||||
b32 last_diff = bin->last != old_last;
|
||||
if (first_diff || last_diff) {
|
||||
@ -774,11 +774,11 @@ void sim_snapshot_encode(BitbuffWriter *bw, Client *receiver, Snapshot *ss0, Sna
|
||||
bw_write_dbg_marker(bw, STRING_FROM_STRUCT(&ss1->num_ents_reserved));
|
||||
|
||||
for (u64 i = 1; i < ss1->num_ents_reserved; ++i) {
|
||||
struct sim_ent *e0 = sim_ent_nil();
|
||||
Ent *e0 = sim_ent_nil();
|
||||
if (i < ss0->num_ents_reserved) {
|
||||
e0 = &ss0->ents[i];
|
||||
}
|
||||
struct sim_ent *e1 = &ss1->ents[i];
|
||||
Ent *e1 = &ss1->ents[i];
|
||||
sim_ent_encode(bw, e0, e1);
|
||||
}
|
||||
|
||||
@ -811,7 +811,7 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
while (bin_changed) {
|
||||
u32 bin_index = br_read_uv(br);
|
||||
if (bin_index < ss->num_id_bins) {
|
||||
struct sim_ent_bin *bin = &ss->id_bins[bin_index];
|
||||
EntBin *bin = &ss->id_bins[bin_index];
|
||||
if (br_read_bit(br)) {
|
||||
bin->first = br_read_uv(br);
|
||||
}
|
||||
@ -838,9 +838,9 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
ss->num_ents_reserved = br_read_uv(br);
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0) {
|
||||
arena_push_array_no_zero(ss->ents_arena, struct sim_ent, reserve_diff);
|
||||
arena_push_array_no_zero(ss->ents_arena, Ent, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *e = &ss->ents[i];
|
||||
Ent *e = &ss->ents[i];
|
||||
*e = *sim_ent_nil();
|
||||
e->ss = ss;
|
||||
}
|
||||
@ -854,7 +854,7 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
br_read_dbg_marker(br, LIT("SNAPSHOT ENTS"));
|
||||
br_read_dbg_marker(br, STRING_FROM_STRUCT(&ss->num_ents_reserved));
|
||||
for (u64 i = 1; i < ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *e = &ss->ents[i];
|
||||
Ent *e = &ss->ents[i];
|
||||
e->ss = ss;
|
||||
sim_ent_decode(br, e);
|
||||
}
|
||||
@ -901,7 +901,7 @@ void sim_snapshot_encode(BitbuffWriter *bw, Client *receiver, Snapshot *ss0, Sna
|
||||
|
||||
bw_align(bw);
|
||||
for (u64 i = 0; i < ss1->num_ents_reserved; ++i) {
|
||||
struct sim_ent *e0 = sim_ent_nil();
|
||||
Ent *e0 = sim_ent_nil();
|
||||
if (i < ss0->num_ents_reserved) {
|
||||
e0 = &ss0->ents[i];
|
||||
}
|
||||
@ -917,7 +917,7 @@ void sim_snapshot_encode(BitbuffWriter *bw, Client *receiver, Snapshot *ss0, Sna
|
||||
}
|
||||
|
||||
if (e1->valid) {
|
||||
struct sim_ent *e1 = &ss1->ents[i];
|
||||
Ent *e1 = &ss1->ents[i];
|
||||
sim_ent_encode(bw, e0, e1);
|
||||
}
|
||||
}
|
||||
@ -959,9 +959,9 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
ss->num_ents_reserved = br_read_uv(br);
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0) {
|
||||
arena_push_array_no_zero(ss->ents_arena, struct sim_ent, reserve_diff);
|
||||
arena_push_array_no_zero(ss->ents_arena, Ent, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *e = &ss->ents[i];
|
||||
Ent *e = &ss->ents[i];
|
||||
*e = *sim_ent_nil();
|
||||
e->ss = ss;
|
||||
}
|
||||
@ -982,7 +982,7 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
if (allocation_changed) {
|
||||
released = br_read_bit(br);
|
||||
if (released) {
|
||||
struct sim_ent *e = sim_ent_from_index(ss, e);
|
||||
Ent *e = sim_ent_from_index(ss, e);
|
||||
ASSERT(e->valid); /* An entity that we don't have allocated should never have been marked for release */
|
||||
if (e->valid) {
|
||||
sim_ent_enable_prop(e, SEPROP_RELEASE);
|
||||
@ -1019,11 +1019,11 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
|
||||
if (n->is_new) {
|
||||
u32 index = n->index;
|
||||
struct sim_ent *parent = sim_ent_from_index(ss, n->alloc_parent_index);
|
||||
Ent *parent = sim_ent_from_index(ss, n->alloc_parent_index);
|
||||
ASSERT(!sim_ent_from_index(ss, index)->valid && !sim_ent_from_id(ss, alloc_ent_id)->valid); /* An entity that we have allocated already should never be marked for allocation */
|
||||
ASSERT(parent->valid); /* Parent for new entity allocation should always be valid */
|
||||
if (parent->valid && index < ss->num_ents_reserved) {
|
||||
struct sim_ent *ent = &ss->ents[index];
|
||||
Ent *ent = &ss->ents[index];
|
||||
ent->valid = 1;
|
||||
sim_ent_set_id(ent, n->alloc_ent_id);
|
||||
sim_ent_link_parent(parent, ent);
|
||||
@ -1038,7 +1038,7 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
|
||||
BitbuffReader ent_br = n->br;
|
||||
u32 index = n->index;
|
||||
struct sim_ent *e = sim_ent_from_index(ss, index);
|
||||
Ent *e = sim_ent_from_index(ss, index);
|
||||
if (e->valid) {
|
||||
sim_ent_decode(&ent_br, e);
|
||||
} else {
|
||||
@ -1056,9 +1056,9 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
ss->num_ents_reserved = br_read_uv(br);
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0) {
|
||||
arena_push_array_no_zero(ss->ents_arena, struct sim_ent, reserve_diff);
|
||||
arena_push_array_no_zero(ss->ents_arena, Ent, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *e = &ss->ents[i];
|
||||
Ent *e = &ss->ents[i];
|
||||
*e = *sim_ent_nil();
|
||||
e->ss = ss;
|
||||
}
|
||||
@ -1077,7 +1077,7 @@ void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *e = &ss->ents[i];
|
||||
Ent *e = &ss->ents[i];
|
||||
e->ss = ss;
|
||||
|
||||
b32 valid_changed = br_read_bit(br);
|
||||
|
||||
@ -11,13 +11,11 @@
|
||||
#define SIM_LAYER_RELATIVE_DEFAULT (0)
|
||||
#define SIM_LAYER_RELATIVE_WEAPON (1)
|
||||
|
||||
typedef struct EntId EntId;
|
||||
struct EntId {
|
||||
Struct(EntId) {
|
||||
UID uid;
|
||||
};
|
||||
|
||||
typedef struct ClientHandle ClientHandle;
|
||||
struct ClientHandle {
|
||||
Struct(ClientHandle) {
|
||||
u32 idx;
|
||||
u32 gen;
|
||||
};
|
||||
@ -26,23 +24,19 @@ struct ClientHandle {
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
typedef struct SimStartupReceipt SimStartupReceipt;
|
||||
struct SimStartupReceipt { i32 _; };
|
||||
Struct(SimStartupReceipt) { i32 _; };
|
||||
SimStartupReceipt sim_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
* Client store
|
||||
* ========================== */
|
||||
|
||||
typedef struct ClientLookupBin ClientLookupBin;
|
||||
struct ClientLookupBin {
|
||||
ClientHandle first;
|
||||
ClientHandle last;
|
||||
Struct(ClientLookupBin) {
|
||||
struct ClientHandle first;
|
||||
struct ClientHandle last;
|
||||
};
|
||||
|
||||
typedef struct Client Client;
|
||||
typedef struct ClientStore ClientStore;
|
||||
struct ClientStore {
|
||||
Struct(ClientStore) {
|
||||
b32 valid;
|
||||
Arena *arena;
|
||||
|
||||
@ -52,7 +46,7 @@ struct ClientStore {
|
||||
|
||||
/* Clients */
|
||||
Arena *clients_arena;
|
||||
Client *clients;
|
||||
struct Client *clients;
|
||||
ClientHandle first_free_client;
|
||||
u64 num_clients_allocated;
|
||||
u64 num_clients_reserved;
|
||||
@ -71,15 +65,12 @@ void sim_client_store_release(ClientStore *store);
|
||||
* Client
|
||||
* ========================== */
|
||||
|
||||
typedef struct Snapshot Snapshot;
|
||||
typedef struct SnapshotLookupBin SnapshotLookupBin;
|
||||
struct SnapshotLookupBin {
|
||||
Snapshot *first;
|
||||
Snapshot *last;
|
||||
Struct(SnapshotLookupBin) {
|
||||
struct Snapshot *first;
|
||||
struct Snapshot *last;
|
||||
};
|
||||
|
||||
typedef struct Client Client;
|
||||
struct Client {
|
||||
Struct(Client) {
|
||||
b32 valid;
|
||||
ClientHandle handle;
|
||||
ClientStore *store;
|
||||
@ -114,7 +105,7 @@ struct Client {
|
||||
u64 first_tick;
|
||||
u64 last_tick;
|
||||
u64 num_ticks;
|
||||
Snapshot *first_free_snapshot;
|
||||
struct Snapshot *first_free_snapshot;
|
||||
|
||||
/* Tick -> snapshot lookup */
|
||||
u64 num_snapshot_lookup_bins;
|
||||
@ -143,11 +134,11 @@ Client *sim_client_from_handle(ClientStore *store, ClientHandle handle);
|
||||
* Snapshot
|
||||
* ========================== */
|
||||
|
||||
typedef enum SyncFlag {
|
||||
typedef i32 SyncFlag; enum {
|
||||
SIM_SYNC_FLAG_NOSYNC_PREDICTABLES = 1 << 0
|
||||
} SyncFlag;
|
||||
};
|
||||
|
||||
typedef enum ControlFlag {
|
||||
typedef i32 ControlFlag; enum {
|
||||
SIM_CONTROL_FLAG_FIRE = 1 << 0,
|
||||
SIM_CONTROL_FLAG_FIRE_ALT = 1 << 1,
|
||||
|
||||
@ -163,36 +154,32 @@ typedef enum ControlFlag {
|
||||
SIM_CONTROL_FLAG_TILE_TEST = 1 << 10,
|
||||
SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 11,
|
||||
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 12,
|
||||
} ControlFlag;
|
||||
};
|
||||
|
||||
typedef struct ControlData ControlData;
|
||||
struct ControlData {
|
||||
Struct(ControlData) {
|
||||
V2 move; /* Movement direction vector (speed of 0 -> 1) */
|
||||
V2 focus; /* Focus direction vector (where does the controller want to look) */
|
||||
V2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
typedef enum CmdKind {
|
||||
typedef i32 CmdKind; enum {
|
||||
SIM_CMD_KIND_INVALID,
|
||||
|
||||
SIM_CMD_KIND_CONTROL,
|
||||
SIM_CMD_KIND_CHAT
|
||||
} CmdKind;
|
||||
};
|
||||
|
||||
|
||||
typedef enum TileKind {
|
||||
typedef i32 TileKind; enum {
|
||||
SIM_TILE_KIND_NONE,
|
||||
SIM_TILE_KIND_WALL,
|
||||
|
||||
NUM_SIM_TILE_KINDS
|
||||
} TileKind;
|
||||
};
|
||||
STATIC_ASSERT(NUM_SIM_TILE_KINDS < 256); /* Tile kind must fit in 8 bits */
|
||||
|
||||
struct sim_ent_bin;
|
||||
|
||||
typedef struct Snapshot Snapshot;
|
||||
struct Snapshot {
|
||||
Struct(Snapshot) {
|
||||
b32 valid;
|
||||
u64 tick;
|
||||
Client *client;
|
||||
@ -218,12 +205,12 @@ struct Snapshot {
|
||||
EntId local_player;
|
||||
|
||||
/* Id lookup */
|
||||
struct sim_ent_bin *id_bins;
|
||||
struct EntBin *id_bins;
|
||||
u64 num_id_bins;
|
||||
|
||||
/* Entities */
|
||||
Arena *ents_arena;
|
||||
struct sim_ent *ents;
|
||||
struct Ent *ents;
|
||||
u32 first_free_ent;
|
||||
u32 num_ents_allocated;
|
||||
u32 num_ents_reserved;
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
#define SIM_ENT_COLLISION_DEBUG_BASIS_UID (MakeUID(0x302c01182013bb02, 0x570bd270399d11a5))
|
||||
#define SIM_ENT_TILE_CHUNK_BASIS_UID (MakeUID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
|
||||
|
||||
INTERNAL u32 index_from_ent(Snapshot *ss, struct sim_ent *ent)
|
||||
INTERNAL u32 index_from_ent(Snapshot *ss, Ent *ent)
|
||||
{
|
||||
return ent - ss->ents;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *ent_from_index(Snapshot *ss, u32 index)
|
||||
INTERNAL Ent *ent_from_index(Snapshot *ss, u32 index)
|
||||
{
|
||||
if (index > 0 && index < ss->num_ents_reserved) {
|
||||
return &ss->ents[index];
|
||||
@ -21,19 +21,19 @@ INTERNAL struct sim_ent *ent_from_index(Snapshot *ss, u32 index)
|
||||
* Ent allocation
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *sim_ent_alloc_raw(Snapshot *ss, struct sim_ent *parent, EntId id)
|
||||
Ent *sim_ent_alloc_raw(Snapshot *ss, Ent *parent, EntId id)
|
||||
{
|
||||
ASSERT(parent->valid);
|
||||
ASSERT(ss->valid);
|
||||
ASSERT(ss == parent->ss);
|
||||
struct sim_ent *ent;
|
||||
Ent *ent;
|
||||
if (ss->first_free_ent > 0 && ss->first_free_ent < ss->num_ents_reserved) {
|
||||
/* Reuse from free list */
|
||||
ent = &ss->ents[ss->first_free_ent];
|
||||
ss->first_free_ent = ent->next_free;
|
||||
} else {
|
||||
/* Make new */
|
||||
ent = arena_push_no_zero(ss->ents_arena, struct sim_ent);
|
||||
ent = arena_push_no_zero(ss->ents_arena, Ent);
|
||||
++ss->num_ents_reserved;
|
||||
}
|
||||
*ent = *sim_ent_nil();
|
||||
@ -50,58 +50,58 @@ struct sim_ent *sim_ent_alloc_raw(Snapshot *ss, struct sim_ent *parent, EntId id
|
||||
}
|
||||
|
||||
/* Allocates a new entity that will not sync */
|
||||
struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent)
|
||||
Ent *sim_ent_alloc_local(Ent *parent)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
struct sim_ent *sim_ent_alloc_local_with_id(struct sim_ent *parent, EntId id)
|
||||
Ent *sim_ent_alloc_local_with_id(Ent *parent, EntId id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Allocates a new entity to be synced to clients */
|
||||
struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent)
|
||||
Ent *sim_ent_alloc_sync_src(Ent *parent)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_SRC);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
struct sim_ent *sim_ent_alloc_sync_src_with_id(struct sim_ent *parent, EntId id)
|
||||
Ent *sim_ent_alloc_sync_src_with_id(Ent *parent, EntId id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_SRC);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Allocates a new entity that will sync with incoming net src ents containing id, and coming from the specified owner */
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, EntId ent_id, EntId owner_id)
|
||||
Ent *sim_ent_alloc_sync_dst(Ent *parent, EntId ent_id, EntId owner_id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, ent_id);
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, ent_id);
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_DST);
|
||||
e->owner = owner_id;
|
||||
return e;
|
||||
}
|
||||
|
||||
void sim_ent_release_raw(struct sim_ent *ent)
|
||||
void sim_ent_release_raw(Ent *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
/* Release children */
|
||||
struct sim_ent *child = sim_ent_from_id(ss, ent->first);
|
||||
Ent *child = sim_ent_from_id(ss, ent->first);
|
||||
while (child->valid) {
|
||||
struct sim_ent *next = sim_ent_from_id(ss, child->next);
|
||||
Ent *next = sim_ent_from_id(ss, child->next);
|
||||
sim_ent_release_raw(child);
|
||||
child = next;
|
||||
}
|
||||
@ -116,26 +116,26 @@ void sim_ent_release_raw(struct sim_ent *ent)
|
||||
--ss->num_ents_allocated;
|
||||
}
|
||||
|
||||
void sim_ent_release(struct sim_ent *ent)
|
||||
void sim_ent_release(Ent *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
if (parent->valid) {
|
||||
sim_ent_unlink_from_parent(ent);
|
||||
}
|
||||
sim_ent_release_raw(ent);
|
||||
}
|
||||
|
||||
void sim_ent_release_all_with_prop(Snapshot *ss, enum sim_ent_prop prop)
|
||||
void sim_ent_release_all_with_prop(Snapshot *ss, EntProp prop)
|
||||
{
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
|
||||
struct sim_ent **ents_to_release = arena_push_dry(scratch.arena, struct sim_ent *);
|
||||
Ent **ents_to_release = arena_push_dry(scratch.arena, Ent *);
|
||||
u64 ents_to_release_count = 0;
|
||||
for (u64 ent_index = 0; ent_index < ss->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &ss->ents[ent_index];
|
||||
Ent *ent = &ss->ents[ent_index];
|
||||
if (ent->valid && sim_ent_has_prop(ent, prop)) {
|
||||
*arena_push_no_zero(scratch.arena, struct sim_ent *) = ent;
|
||||
*arena_push_no_zero(scratch.arena, Ent *) = ent;
|
||||
++ents_to_release_count;
|
||||
}
|
||||
}
|
||||
@ -144,7 +144,7 @@ void sim_ent_release_all_with_prop(Snapshot *ss, enum sim_ent_prop prop)
|
||||
/* TODO: Breadth first iteration to only release parent entities (since
|
||||
* child entities will be released along with parent anyway) */
|
||||
for (u64 i = 0; i < ents_to_release_count; ++i) {
|
||||
struct sim_ent *ent = ents_to_release[i];
|
||||
Ent *ent = ents_to_release[i];
|
||||
if (ent->valid && !ent->is_root && !sim_ent_has_prop(ent, SEPROP_CMD) && !sim_ent_has_prop(ent, SEPROP_PLAYER)) {
|
||||
sim_ent_release(ent);
|
||||
}
|
||||
@ -157,7 +157,7 @@ void sim_ent_release_all_with_prop(Snapshot *ss, enum sim_ent_prop prop)
|
||||
* Activate
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_activate(struct sim_ent *ent, u64 current_tick)
|
||||
void sim_ent_activate(Ent *ent, u64 current_tick)
|
||||
{
|
||||
sim_ent_enable_prop(ent, SEPROP_ACTIVE);
|
||||
ent->activation_tick = current_tick;
|
||||
@ -168,26 +168,26 @@ void sim_ent_activate(struct sim_ent *ent, u64 current_tick)
|
||||
* Ent id
|
||||
* ========================== */
|
||||
|
||||
INTERNAL struct sim_ent_bin *bin_from_id(Snapshot *ss, EntId id)
|
||||
INTERNAL EntBin *bin_from_id(Snapshot *ss, EntId id)
|
||||
{
|
||||
return &ss->id_bins[id.uid.lo % ss->num_id_bins];
|
||||
}
|
||||
|
||||
/* NOTE: This should only really happen during ent allocation (it doesn't make sense for an allocated ent's id to change) */
|
||||
void sim_ent_set_id(struct sim_ent *ent, EntId id)
|
||||
void sim_ent_set_id(Ent *ent, EntId id)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
EntId old_id = ent->id;
|
||||
if (!sim_ent_id_eq(old_id, id)) {
|
||||
/* Release old from lookup */
|
||||
if (!sim_ent_id_is_nil(old_id)) {
|
||||
struct sim_ent_bin *bin = bin_from_id(ss, old_id);
|
||||
EntBin *bin = bin_from_id(ss, old_id);
|
||||
u32 prev_index = 0;
|
||||
u32 next_index = 0;
|
||||
u32 search_index = bin->first;
|
||||
struct sim_ent *prev = sim_ent_nil();
|
||||
struct sim_ent *next = sim_ent_nil();
|
||||
struct sim_ent *search = ent_from_index(ss, search_index);
|
||||
Ent *prev = sim_ent_nil();
|
||||
Ent *next = sim_ent_nil();
|
||||
Ent *search = ent_from_index(ss, search_index);
|
||||
while (search->valid) {
|
||||
next_index = search->next_in_id_bin;
|
||||
next = ent_from_index(ss, next_index);
|
||||
@ -220,15 +220,15 @@ void sim_ent_set_id(struct sim_ent *ent, EntId id)
|
||||
if (!sim_ent_id_is_nil(id)) {
|
||||
#if RTC
|
||||
{
|
||||
struct sim_ent *existing = sim_ent_from_id(ss, id);
|
||||
Ent *existing = sim_ent_from_id(ss, id);
|
||||
/* Collision should be extremely unlikely under normal circumstances, there's probably a logic error somewhere. */
|
||||
ASSERT(!existing->valid);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sim_ent_bin *bin = bin_from_id(ss, id);
|
||||
EntBin *bin = bin_from_id(ss, id);
|
||||
u32 ent_index = index_from_ent(ss, ent);
|
||||
struct sim_ent *last = ent_from_index(ss, bin->last);
|
||||
Ent *last = ent_from_index(ss, bin->last);
|
||||
if (last->valid) {
|
||||
last->next_in_id_bin = ent_index;
|
||||
ent->prev_in_id_bin = bin->last;
|
||||
@ -244,12 +244,12 @@ void sim_ent_set_id(struct sim_ent *ent, EntId id)
|
||||
|
||||
}
|
||||
|
||||
struct sim_ent *sim_ent_from_id(Snapshot *ss, EntId id)
|
||||
Ent *sim_ent_from_id(Snapshot *ss, EntId id)
|
||||
{
|
||||
struct sim_ent *res = sim_ent_nil();
|
||||
Ent *res = sim_ent_nil();
|
||||
if (!sim_ent_id_is_nil(id) && ss->valid) {
|
||||
struct sim_ent_bin *bin = bin_from_id(ss, id);
|
||||
for (struct sim_ent *e = ent_from_index(ss, bin->first); e->valid; e = ent_from_index(ss, e->next_in_id_bin)) {
|
||||
EntBin *bin = bin_from_id(ss, id);
|
||||
for (Ent *e = ent_from_index(ss, bin->first); e->valid; e = ent_from_index(ss, e->next_in_id_bin)) {
|
||||
if (sim_ent_id_eq(e->id, id)) {
|
||||
res = e;
|
||||
break;
|
||||
@ -301,12 +301,12 @@ EntId sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_index)
|
||||
* Ent query
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *sim_ent_find_first_match_one(Snapshot *ss, enum sim_ent_prop prop)
|
||||
Ent *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
struct sim_ent *entities = ss->ents;
|
||||
Ent *entities = ss->ents;
|
||||
for (u64 ent_index = 0; ent_index < count; ++ent_index) {
|
||||
struct sim_ent *ent = &entities[ent_index];
|
||||
Ent *ent = &entities[ent_index];
|
||||
if (ent->valid && sim_ent_has_prop(ent, prop)) {
|
||||
return ent;
|
||||
}
|
||||
@ -314,12 +314,12 @@ struct sim_ent *sim_ent_find_first_match_one(Snapshot *ss, enum sim_ent_prop pro
|
||||
return sim_ent_nil();
|
||||
}
|
||||
|
||||
struct sim_ent *sim_ent_find_first_match_all(Snapshot *ss, struct sim_ent_prop_array props)
|
||||
Ent *sim_ent_find_first_match_all(Snapshot *ss, EntPropArray props)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
struct sim_ent *entities = ss->ents;
|
||||
Ent *entities = ss->ents;
|
||||
for (u64 ent_index = 0; ent_index < count; ++ent_index) {
|
||||
struct sim_ent *ent = &entities[ent_index];
|
||||
Ent *ent = &entities[ent_index];
|
||||
if (ent->valid) {
|
||||
b32 all = 1;
|
||||
for (u64 i = 0; i < props.count; ++i) {
|
||||
@ -340,11 +340,11 @@ struct sim_ent *sim_ent_find_first_match_all(Snapshot *ss, struct sim_ent_prop_a
|
||||
* Ent tree
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent)
|
||||
void sim_ent_link_parent(Ent *ent, Ent *parent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
|
||||
struct sim_ent *old_parent = sim_ent_from_id(ss, ent->parent);
|
||||
Ent *old_parent = sim_ent_from_id(ss, ent->parent);
|
||||
if (old_parent->valid) {
|
||||
/* Unlink from current parent */
|
||||
sim_ent_unlink_from_parent(ent);
|
||||
@ -352,7 +352,7 @@ void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent)
|
||||
|
||||
EntId ent_id = ent->id;
|
||||
EntId last_child_id = parent->last;
|
||||
struct sim_ent *last_child = sim_ent_from_id(ss, last_child_id);
|
||||
Ent *last_child = sim_ent_from_id(ss, last_child_id);
|
||||
if (last_child->valid) {
|
||||
ent->prev = last_child_id;
|
||||
last_child->next = ent_id;
|
||||
@ -372,14 +372,14 @@ void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent)
|
||||
}
|
||||
|
||||
/* NOTE: Entity will be dangling after calling this, should re-link to root ent. */
|
||||
void sim_ent_unlink_from_parent(struct sim_ent *ent)
|
||||
void sim_ent_unlink_from_parent(Ent *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
|
||||
EntId parent_id = ent->parent;
|
||||
struct sim_ent *parent = sim_ent_from_id(ss, parent_id);
|
||||
struct sim_ent *prev = sim_ent_from_id(ss, ent->prev);
|
||||
struct sim_ent *next = sim_ent_from_id(ss, ent->next);
|
||||
Ent *parent = sim_ent_from_id(ss, parent_id);
|
||||
Ent *prev = sim_ent_from_id(ss, ent->prev);
|
||||
Ent *next = sim_ent_from_id(ss, ent->next);
|
||||
|
||||
/* Unlink from parent & siblings */
|
||||
if (prev->valid) {
|
||||
@ -400,9 +400,9 @@ void sim_ent_unlink_from_parent(struct sim_ent *ent)
|
||||
* Ent xform
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void sim_ent_mark_child_xforms_dirty(Snapshot *ss, struct sim_ent *ent)
|
||||
INTERNAL void sim_ent_mark_child_xforms_dirty(Snapshot *ss, Ent *ent)
|
||||
{
|
||||
for (struct sim_ent *child = sim_ent_from_id(ss, ent->first); child->valid; child = sim_ent_from_id(ss, child->next)) {
|
||||
for (Ent *child = sim_ent_from_id(ss, ent->first); child->valid; child = sim_ent_from_id(ss, child->next)) {
|
||||
if (child->_is_xform_dirty) {
|
||||
break;
|
||||
} else {
|
||||
@ -412,14 +412,14 @@ INTERNAL void sim_ent_mark_child_xforms_dirty(Snapshot *ss, struct sim_ent *ent)
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL Xform sim_ent_get_xform_internal(Snapshot *ss, struct sim_ent *ent)
|
||||
INTERNAL Xform sim_ent_get_xform_internal(Snapshot *ss, Ent *ent)
|
||||
{
|
||||
Xform xf;
|
||||
if (ent->_is_xform_dirty) {
|
||||
if (ent->is_top) {
|
||||
xf = ent->_local_xform;
|
||||
} else {
|
||||
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
xf = sim_ent_get_xform_internal(ss, parent);
|
||||
xf = xform_mul(xf, ent->_local_xform);
|
||||
ent->_xform = xf;
|
||||
@ -433,7 +433,7 @@ INTERNAL Xform sim_ent_get_xform_internal(Snapshot *ss, struct sim_ent *ent)
|
||||
return xf;
|
||||
}
|
||||
|
||||
Xform sim_ent_get_xform(struct sim_ent *ent)
|
||||
Xform sim_ent_get_xform(Ent *ent)
|
||||
{
|
||||
Xform xf;
|
||||
if (ent->_is_xform_dirty) {
|
||||
@ -441,7 +441,7 @@ Xform sim_ent_get_xform(struct sim_ent *ent)
|
||||
xf = ent->_local_xform;
|
||||
} else {
|
||||
Snapshot *ss = ent->ss;
|
||||
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
xf = sim_ent_get_xform_internal(ss, parent);
|
||||
xf = xform_mul(xf, ent->_local_xform);
|
||||
ent->_xform = xf;
|
||||
@ -455,12 +455,12 @@ Xform sim_ent_get_xform(struct sim_ent *ent)
|
||||
return xf;
|
||||
}
|
||||
|
||||
Xform sim_ent_get_local_xform(struct sim_ent *ent)
|
||||
Xform sim_ent_get_local_xform(Ent *ent)
|
||||
{
|
||||
return ent->_local_xform;
|
||||
}
|
||||
|
||||
void sim_ent_set_xform(struct sim_ent *ent, Xform xf)
|
||||
void sim_ent_set_xform(Ent *ent, Xform xf)
|
||||
{
|
||||
if (!xform_eq(xf, ent->_xform)) {
|
||||
Snapshot *ss = ent->ss;
|
||||
@ -468,7 +468,7 @@ void sim_ent_set_xform(struct sim_ent *ent, Xform xf)
|
||||
if (ent->is_top) {
|
||||
ent->_local_xform = xf;
|
||||
} else {
|
||||
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Xform parent_global = sim_ent_get_xform_internal(ss, parent);
|
||||
ent->_local_xform = xform_mul(xform_invert(parent_global), xf);
|
||||
}
|
||||
@ -478,7 +478,7 @@ void sim_ent_set_xform(struct sim_ent *ent, Xform xf)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_set_local_xform(struct sim_ent *ent, Xform xf)
|
||||
void sim_ent_set_local_xform(Ent *ent, Xform xf)
|
||||
{
|
||||
if (!xform_eq(xf, ent->_local_xform)) {
|
||||
ent->_local_xform = xf;
|
||||
@ -491,21 +491,21 @@ void sim_ent_set_local_xform(struct sim_ent *ent, Xform xf)
|
||||
* Ent movement
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_set_linear_velocity(struct sim_ent *ent, V2 velocity)
|
||||
void sim_ent_set_linear_velocity(Ent *ent, V2 velocity)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_KINEMATIC) || sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->linear_velocity = v2_clamp_len(velocity, SIM_MAX_LINEAR_VELOCITY);
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_set_angular_velocity(struct sim_ent *ent, f32 velocity)
|
||||
void sim_ent_set_angular_velocity(Ent *ent, f32 velocity)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_KINEMATIC) || sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->angular_velocity = clamp_f32(velocity, -SIM_MAX_ANGULAR_VELOCITY, SIM_MAX_ANGULAR_VELOCITY);
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_linear_impulse(struct sim_ent *ent, V2 impulse, V2 point)
|
||||
void sim_ent_apply_linear_impulse(Ent *ent, V2 impulse, V2 point)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -520,7 +520,7 @@ void sim_ent_apply_linear_impulse(struct sim_ent *ent, V2 impulse, V2 point)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, V2 impulse)
|
||||
void sim_ent_apply_linear_impulse_to_center(Ent *ent, V2 impulse)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -531,14 +531,14 @@ void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, V2 impulse)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_force_to_center(struct sim_ent *ent, V2 force)
|
||||
void sim_ent_apply_force_to_center(Ent *ent, V2 force)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->force = v2_add(ent->force, force);
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse)
|
||||
void sim_ent_apply_angular_impulse(Ent *ent, f32 impulse)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -548,7 +548,7 @@ void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque)
|
||||
void sim_ent_apply_torque(Ent *ent, f32 torque)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->torque += torque;
|
||||
@ -559,21 +559,21 @@ void sim_ent_apply_torque(struct sim_ent *ent, f32 torque)
|
||||
* Tile
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2i32 chunk_index)
|
||||
Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2i32 chunk_index)
|
||||
{
|
||||
EntId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||
struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
Ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
struct sim_ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2i32 world_tile_index)
|
||||
Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2i32 world_tile_index)
|
||||
{
|
||||
V2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
||||
struct sim_ent *chunk_ent = sim_tile_chunk_from_chunk_index(ss, chunk_index);
|
||||
Ent *chunk_ent = sim_tile_chunk_from_chunk_index(ss, chunk_index);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
TileKind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index)
|
||||
TileKind sim_get_chunk_tile(Ent *chunk_ent, V2i32 local_tile_index)
|
||||
{
|
||||
TileKind res = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
return res;
|
||||
@ -583,7 +583,7 @@ TileKind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index)
|
||||
* Ent lerp
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend)
|
||||
void sim_ent_lerp(Ent *e, Ent *e0, Ent *e1, f64 blend)
|
||||
{
|
||||
if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)
|
||||
&& sim_ent_id_eq(e0->id, e1->id)
|
||||
@ -624,7 +624,7 @@ void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64
|
||||
* ========================== */
|
||||
|
||||
/* Walks a local & remote ent tree and allocates any missing net dst ents from remote src ents */
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote, EntId remote_player)
|
||||
void sim_ent_sync_alloc_tree(Ent *local_parent, Ent *remote, EntId remote_player)
|
||||
{
|
||||
__prof;
|
||||
if (sim_ent_has_prop(remote, SEPROP_SYNC_SRC)) {
|
||||
@ -632,20 +632,20 @@ void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remot
|
||||
Snapshot *remote_ss = remote->ss;
|
||||
|
||||
EntId id = remote->id;
|
||||
struct sim_ent *local_ent = sim_ent_from_id(local_ss, id);
|
||||
Ent *local_ent = sim_ent_from_id(local_ss, id);
|
||||
if (!local_ent->valid) {
|
||||
local_ent = sim_ent_alloc_sync_dst(local_parent, id, remote_player);
|
||||
}
|
||||
for (struct sim_ent *remote_child = sim_ent_from_id(remote_ss, remote->first); remote_child->valid; remote_child = sim_ent_from_id(remote_ss, remote_child->next)) {
|
||||
for (Ent *remote_child = sim_ent_from_id(remote_ss, remote->first); remote_child->valid; remote_child = sim_ent_from_id(remote_ss, remote_child->next)) {
|
||||
sim_ent_sync_alloc_tree(local_ent, remote_child, remote_player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Copies data between two synced entities */
|
||||
void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
|
||||
void sim_ent_sync(Ent *local, Ent *remote)
|
||||
{
|
||||
struct sim_ent old = *local;
|
||||
Ent old = *local;
|
||||
MEMCPY_STRUCT(local, remote);
|
||||
|
||||
/* Why would 2 ents w/ different uids ever be synced? */
|
||||
@ -687,7 +687,7 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
|
||||
* Ent encode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||
void sim_ent_encode(BitbuffWriter *bw, Ent *e0, Ent *e1)
|
||||
{
|
||||
Snapshot *ss = e1->ss;
|
||||
/* FIXME: Things like xforms need to be retreived manually rather than memcopied. */
|
||||
@ -714,7 +714,7 @@ void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||
* Ent decode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||
void sim_ent_decode(BitbuffReader *br, Ent *e)
|
||||
{
|
||||
Snapshot *old_ss = e->ss;
|
||||
{
|
||||
@ -739,7 +739,7 @@ void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||
* Ent encode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||
void sim_ent_encode(BitbuffWriter *bw, Ent *e0, Ent *e1)
|
||||
{
|
||||
Snapshot *ss = e1->ss;
|
||||
|
||||
@ -772,9 +772,9 @@ void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||
* Ent decode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||
void sim_ent_decode(BitbuffReader *br, Ent *e)
|
||||
{
|
||||
struct sim_ent decoded = *e;
|
||||
Ent decoded = *e;
|
||||
{
|
||||
u64 pos = 0;
|
||||
while (pos < sizeof(decoded)) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#define SIM_ENT_NIL_ID ((EntId) { MakeUID(0, 0) })
|
||||
#define SIM_ENT_ROOT_ID ((EntId) { MakeUID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||
|
||||
enum sim_ent_prop {
|
||||
typedef i32 EntProp; enum {
|
||||
SEPROP_ACTIVE,
|
||||
SEPROP_RELEASE,
|
||||
|
||||
@ -60,7 +60,7 @@ enum sim_ent_prop {
|
||||
SEPROP_COUNT
|
||||
};
|
||||
|
||||
struct sim_ent {
|
||||
Struct(Ent) {
|
||||
Snapshot *ss;
|
||||
|
||||
/* ====================================================================== */
|
||||
@ -391,17 +391,17 @@ struct sim_ent {
|
||||
f32 shake;
|
||||
};
|
||||
|
||||
struct sim_ent_array {
|
||||
struct sim_ent *ents;
|
||||
Struct(EntArray) {
|
||||
Ent *ents;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
struct sim_ent_prop_array {
|
||||
enum sim_ent_prop *props;
|
||||
Struct(EntPropArray) {
|
||||
EntProp *props;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
struct sim_ent_bin {
|
||||
Struct(EntBin) {
|
||||
u32 first;
|
||||
u32 last;
|
||||
};
|
||||
@ -410,9 +410,9 @@ struct sim_ent_bin {
|
||||
* Nil
|
||||
* ========================== */
|
||||
|
||||
INLINE struct sim_ent *sim_ent_nil(void)
|
||||
INLINE Ent *sim_ent_nil(void)
|
||||
{
|
||||
extern READONLY struct sim_ent **_g_sim_ent_nil;
|
||||
extern READONLY Ent **_g_sim_ent_nil;
|
||||
return *_g_sim_ent_nil;
|
||||
}
|
||||
|
||||
@ -434,43 +434,43 @@ INLINE b32 sim_ent_id_is_nil(EntId id)
|
||||
* Property helpers
|
||||
* ========================== */
|
||||
|
||||
INLINE void sim_ent_enable_prop(struct sim_ent *ent, enum sim_ent_prop prop)
|
||||
INLINE void sim_ent_enable_prop(Ent *ent, EntProp prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
ent->props[index] |= ((u64)1 << bit);
|
||||
}
|
||||
|
||||
INLINE void sim_ent_disable_prop(struct sim_ent *ent, enum sim_ent_prop prop)
|
||||
INLINE void sim_ent_disable_prop(Ent *ent, EntProp prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
ent->props[index] &= ~((u64)1 << bit);
|
||||
}
|
||||
|
||||
INLINE b32 sim_ent_has_prop(struct sim_ent *ent, enum sim_ent_prop prop)
|
||||
INLINE b32 sim_ent_has_prop(Ent *ent, EntProp prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
return !!(ent->props[index] & ((u64)1 << bit));
|
||||
}
|
||||
|
||||
INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent)
|
||||
INLINE b32 sim_ent_is_valid_and_active(Ent *ent)
|
||||
{
|
||||
return ent->valid && sim_ent_has_prop(ent, SEPROP_ACTIVE);
|
||||
}
|
||||
|
||||
INLINE b32 sim_ent_should_predict(struct sim_ent *ent)
|
||||
INLINE b32 sim_ent_should_predict(Ent *ent)
|
||||
{
|
||||
return sim_ent_id_eq(ent->predictor, ent->ss->local_player);
|
||||
}
|
||||
|
||||
INLINE b32 sim_ent_is_owner(struct sim_ent *ent)
|
||||
INLINE b32 sim_ent_is_owner(Ent *ent)
|
||||
{
|
||||
return sim_ent_id_eq(ent->owner, ent->ss->local_player);
|
||||
}
|
||||
|
||||
INLINE b32 sim_ent_should_simulate(struct sim_ent *ent)
|
||||
INLINE b32 sim_ent_should_simulate(Ent *ent)
|
||||
{
|
||||
b32 res = 0;
|
||||
if (sim_ent_is_valid_and_active(ent)) {
|
||||
@ -488,63 +488,63 @@ INLINE b32 sim_ent_should_simulate(struct sim_ent *ent)
|
||||
* ========================== */
|
||||
|
||||
/* Alloc */
|
||||
struct sim_ent *sim_ent_alloc_raw(Snapshot *ss, struct sim_ent *parent, EntId id);
|
||||
struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent);
|
||||
struct sim_ent *sim_ent_alloc_local_with_id(struct sim_ent *parent, EntId id);
|
||||
struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent);
|
||||
struct sim_ent *sim_ent_alloc_sync_src_with_id(struct sim_ent *parent, EntId id);
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, EntId ent_id, EntId owner_id);
|
||||
Ent *sim_ent_alloc_raw(Snapshot *ss, Ent *parent, EntId id);
|
||||
Ent *sim_ent_alloc_local(Ent *parent);
|
||||
Ent *sim_ent_alloc_local_with_id(Ent *parent, EntId id);
|
||||
Ent *sim_ent_alloc_sync_src(Ent *parent);
|
||||
Ent *sim_ent_alloc_sync_src_with_id(Ent *parent, EntId id);
|
||||
Ent *sim_ent_alloc_sync_dst(Ent *parent, EntId ent_id, EntId owner_id);
|
||||
|
||||
void sim_ent_release_raw(struct sim_ent *ent);
|
||||
void sim_ent_release(struct sim_ent *ent);
|
||||
void sim_ent_release_all_with_prop(Snapshot *ss, enum sim_ent_prop prop);
|
||||
void sim_ent_release_raw(Ent *ent);
|
||||
void sim_ent_release(Ent *ent);
|
||||
void sim_ent_release_all_with_prop(Snapshot *ss, EntProp prop);
|
||||
|
||||
/* Activate */
|
||||
void sim_ent_activate(struct sim_ent *ent, u64 current_tick);
|
||||
void sim_ent_activate(Ent *ent, u64 current_tick);
|
||||
|
||||
/* Id */
|
||||
void sim_ent_set_id(struct sim_ent *ent, EntId id);
|
||||
struct sim_ent *sim_ent_from_id(Snapshot *ss, EntId id);
|
||||
void sim_ent_set_id(Ent *ent, EntId id);
|
||||
Ent *sim_ent_from_id(Snapshot *ss, EntId id);
|
||||
EntId sim_ent_random_id(void);
|
||||
EntId sim_ent_contact_constraint_id_from_contacting_ids(EntId player_id, EntId id0, EntId id1);
|
||||
EntId sim_ent_collision_debug_id_from_ids(EntId player_id, EntId id0, EntId id1);
|
||||
EntId sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_start);
|
||||
|
||||
/* Query */
|
||||
struct sim_ent *sim_ent_find_first_match_one(Snapshot *ss, enum sim_ent_prop prop);
|
||||
struct sim_ent *sim_ent_find_first_match_all(Snapshot *ss, struct sim_ent_prop_array props);
|
||||
Ent *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop);
|
||||
Ent *sim_ent_find_first_match_all(Snapshot *ss, EntPropArray props);
|
||||
|
||||
/* Tree */
|
||||
void sim_ent_link_parent(struct sim_ent *parent, struct sim_ent *child);
|
||||
void sim_ent_unlink_from_parent(struct sim_ent *ent);
|
||||
void sim_ent_link_parent(Ent *parent, Ent *child);
|
||||
void sim_ent_unlink_from_parent(Ent *ent);
|
||||
|
||||
/* Xform */
|
||||
Xform sim_ent_get_xform(struct sim_ent *ent);
|
||||
Xform sim_ent_get_local_xform(struct sim_ent *ent);
|
||||
void sim_ent_set_xform(struct sim_ent *ent, Xform xf);
|
||||
void sim_ent_set_local_xform(struct sim_ent *ent, Xform xf);
|
||||
Xform sim_ent_get_xform(Ent *ent);
|
||||
Xform sim_ent_get_local_xform(Ent *ent);
|
||||
void sim_ent_set_xform(Ent *ent, Xform xf);
|
||||
void sim_ent_set_local_xform(Ent *ent, Xform xf);
|
||||
|
||||
/* Movement */
|
||||
void sim_ent_set_linear_velocity(struct sim_ent *ent, V2 velocity);
|
||||
void sim_ent_set_angular_velocity(struct sim_ent *ent, f32 velocity);
|
||||
void sim_ent_apply_linear_impulse(struct sim_ent *ent, V2 impulse, V2 world_point);
|
||||
void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, V2 impulse);
|
||||
void sim_ent_apply_force_to_center(struct sim_ent *ent, V2 force);
|
||||
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse);
|
||||
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
|
||||
void sim_ent_set_linear_velocity(Ent *ent, V2 velocity);
|
||||
void sim_ent_set_angular_velocity(Ent *ent, f32 velocity);
|
||||
void sim_ent_apply_linear_impulse(Ent *ent, V2 impulse, V2 world_point);
|
||||
void sim_ent_apply_linear_impulse_to_center(Ent *ent, V2 impulse);
|
||||
void sim_ent_apply_force_to_center(Ent *ent, V2 force);
|
||||
void sim_ent_apply_angular_impulse(Ent *ent, f32 impulse);
|
||||
void sim_ent_apply_torque(Ent *ent, f32 torque);
|
||||
|
||||
/* Tile */
|
||||
struct sim_ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2i32 chunk_index);
|
||||
struct sim_ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2i32 world_tile_index);
|
||||
TileKind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index);
|
||||
Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2i32 chunk_index);
|
||||
Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2i32 world_tile_index);
|
||||
TileKind sim_get_chunk_tile(Ent *chunk_ent, V2i32 local_tile_index);
|
||||
|
||||
/* Lerp */
|
||||
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);
|
||||
void sim_ent_lerp(Ent *e, Ent *e0, Ent *e1, f64 blend);
|
||||
|
||||
/* Sync */
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote, EntId remote_player);
|
||||
void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote);
|
||||
void sim_ent_sync_alloc_tree(Ent *local_parent, Ent *remote, EntId remote_player);
|
||||
void sim_ent_sync(Ent *local, Ent *remote);
|
||||
|
||||
/* Encode / decode */
|
||||
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1);
|
||||
void sim_ent_decode(BitbuffReader *br, struct sim_ent *e);
|
||||
void sim_ent_encode(BitbuffWriter *bw, Ent *e0, Ent *e1);
|
||||
void sim_ent_decode(BitbuffReader *br, Ent *e);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* Contact
|
||||
* ========================== */
|
||||
|
||||
INTERNAL b32 can_contact(struct sim_ent *e0, struct sim_ent *e1)
|
||||
INTERNAL b32 can_contact(Ent *e0, Ent *e1)
|
||||
{
|
||||
b32 res = 0;
|
||||
res = e0 != e1 &&
|
||||
@ -23,11 +23,11 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
EntId local_player = ss->local_player;
|
||||
phys_collision_callback_func *collision_callback = ctx->collision_callback;
|
||||
|
||||
struct sim_ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
Ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
u64 tick = ss->tick;
|
||||
|
||||
for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) {
|
||||
struct sim_ent *check0 = &ss->ents[check0_index];
|
||||
Ent *check0 = &ss->ents[check0_index];
|
||||
if (!sim_ent_is_valid_and_active(check0)) continue;
|
||||
if (!(sim_ent_has_prop(check0, SEPROP_SOLID) || sim_ent_has_prop(check0, SEPROP_SENSOR))) continue;
|
||||
if (check0->local_collider.count <= 0) continue;
|
||||
@ -39,15 +39,15 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
SpaceIter iter = space_iter_begin_aabb(space, aabb);
|
||||
SpaceEntry *space_entry;
|
||||
while ((space_entry = space_iter_next(&iter)) != 0) {
|
||||
struct sim_ent *check1 = sim_ent_from_id(ss, space_entry->ent);
|
||||
Ent *check1 = sim_ent_from_id(ss, space_entry->ent);
|
||||
if (!sim_ent_is_valid_and_active(check1)) continue;
|
||||
if (!(sim_ent_has_prop(check1, SEPROP_SOLID) || sim_ent_has_prop(check1, SEPROP_SENSOR))) continue;
|
||||
if (check1->local_collider.count <= 0) continue;
|
||||
if (!can_contact(check0, check1)) continue;
|
||||
|
||||
/* Deterministic order based on entity id */
|
||||
struct sim_ent *e0;
|
||||
struct sim_ent *e1;
|
||||
Ent *e0;
|
||||
Ent *e1;
|
||||
Xform e0_xf;
|
||||
Xform e1_xf;
|
||||
CLD_Shape e0_collider;
|
||||
@ -69,7 +69,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
}
|
||||
|
||||
EntId constraint_id = sim_ent_contact_constraint_id_from_contacting_ids(local_player, e0->id, e1->id);
|
||||
struct sim_ent *constraint_ent = sim_ent_from_id(ss, constraint_id);
|
||||
Ent *constraint_ent = sim_ent_from_id(ss, constraint_id);
|
||||
|
||||
if (constraint_ent->valid) {
|
||||
if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) {
|
||||
@ -229,7 +229,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
#if COLLIDER_DEBUG && COLLIDER_DEBUG_DETAILED
|
||||
{
|
||||
EntId dbg_ent_id = sim_ent_collision_debug_id_from_ids(local_player, e0->id, e1->id);
|
||||
struct sim_ent *dbg_ent = sim_ent_from_id(ss, dbg_ent_id);
|
||||
Ent *dbg_ent = sim_ent_from_id(ss, dbg_ent_id);
|
||||
if (!dbg_ent->valid) {
|
||||
/* FIXME: Entity never released */
|
||||
dbg_ent = sim_ent_alloc_local_with_id(root, dbg_ent_id);
|
||||
@ -271,15 +271,15 @@ void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration)
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
u32 num_points = constraint->num_points;
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) {
|
||||
V2 normal = constraint->normal;
|
||||
V2 tangent = v2_perp(normal);
|
||||
@ -355,13 +355,13 @@ void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration)
|
||||
#if COLLIDER_DEBUG
|
||||
/* Remove collision debug ents */
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *dbg_ent = &ss->ents[sim_ent_index];
|
||||
Ent *dbg_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(dbg_ent)) continue;
|
||||
if (!sim_ent_has_prop(dbg_ent, SEPROP_COLLISION_DEBUG)) continue;
|
||||
|
||||
CollisionDebugData *dbg = &dbg_ent->collision_debug_data;
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, dbg->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, dbg->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, dbg->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, dbg->e1);
|
||||
|
||||
if (!(sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) ||
|
||||
!(sim_ent_has_prop(e0, SEPROP_SOLID) || sim_ent_has_prop(e0, SEPROP_SENSOR)) ||
|
||||
@ -380,15 +380,15 @@ void phys_warm_start_contacts(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
u32 num_points = constraint->num_points;
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
|
||||
if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve && !constraint->wrong_dir) {
|
||||
f32 inv_m0 = constraint->inv_m0;
|
||||
@ -432,14 +432,14 @@ void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
|
||||
V2 v0 = e0->linear_velocity;
|
||||
V2 v1 = e1->linear_velocity;
|
||||
@ -570,14 +570,14 @@ void phys_prepare_motor_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
MotorJoint *joint = &joint_ent->motor_joint_data;
|
||||
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
@ -634,14 +634,14 @@ void phys_warm_start_motor_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
MotorJoint *joint = &joint_ent->motor_joint_data;
|
||||
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
@ -666,14 +666,14 @@ void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
MotorJoint *joint = &joint_ent->motor_joint_data;
|
||||
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
@ -772,12 +772,12 @@ void phys_prepare_mouse_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
Ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
|
||||
@ -819,12 +819,12 @@ void phys_warm_start_mouse_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
Ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
f32 inv_m = joint->inv_m;
|
||||
f32 inv_i = joint->inv_i;
|
||||
@ -841,12 +841,12 @@ void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
Ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
V2 v = ent->linear_velocity;
|
||||
f32 w = ent->angular_velocity;
|
||||
@ -937,15 +937,15 @@ void phys_prepare_weld_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
/* TODO: Lookup and disable collision for any contacts between e0 & e1? */
|
||||
|
||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
@ -986,14 +986,14 @@ void phys_warm_start_weld_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||
|
||||
#if 0
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
if (sim_ent_should_simulate(e0)) {
|
||||
f32 inv_m = joint->inv_m0;
|
||||
f32 inv_i = joint->inv_i0;
|
||||
@ -1005,7 +1005,7 @@ void phys_warm_start_weld_joints(PhysStepCtx *ctx)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
if (sim_ent_should_simulate(e1)) {
|
||||
f32 inv_m = joint->inv_m1;
|
||||
f32 inv_i = joint->inv_i1;
|
||||
@ -1023,13 +1023,13 @@ void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
Xform xf0 = sim_ent_get_xform(e0);
|
||||
Xform xf1 = sim_ent_get_xform(e1);
|
||||
@ -1086,7 +1086,7 @@ void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt)
|
||||
* Integration
|
||||
* ========================== */
|
||||
|
||||
INTERNAL Xform get_derived_xform(struct sim_ent *ent, f32 dt)
|
||||
INTERNAL Xform get_derived_xform(Ent *ent, f32 dt)
|
||||
{
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
|
||||
@ -1103,7 +1103,7 @@ void phys_integrate_forces(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
b32 is_dynamic = sim_ent_has_prop(ent, SEPROP_DYNAMIC);
|
||||
@ -1145,7 +1145,7 @@ void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC) && !sim_ent_has_prop(ent, SEPROP_KINEMATIC)) continue;
|
||||
|
||||
@ -1166,7 +1166,7 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3
|
||||
f32 smallest_t = 1;
|
||||
|
||||
for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) {
|
||||
struct sim_ent *e0 = &ss->ents[e0_index];
|
||||
Ent *e0 = &ss->ents[e0_index];
|
||||
if (!sim_ent_should_simulate(e0)) continue;
|
||||
if (!(sim_ent_has_prop(e0, SEPROP_SOLID) || sim_ent_has_prop(e0, SEPROP_SENSOR))) continue;
|
||||
if (!sim_ent_has_prop(e0, SEPROP_TOI)) continue;
|
||||
@ -1184,7 +1184,7 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3
|
||||
SpaceIter iter = space_iter_begin_aabb(space, combined_aabb);
|
||||
SpaceEntry *entry;
|
||||
while ((entry = space_iter_next(&iter)) != 0) {
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, entry->ent);
|
||||
Ent *e1 = sim_ent_from_id(ss, entry->ent);
|
||||
if (!sim_ent_should_simulate(e1)) continue;
|
||||
if (!(sim_ent_has_prop(e1, SEPROP_SOLID) || sim_ent_has_prop(e1, SEPROP_SENSOR))) continue;
|
||||
if (e1->local_collider.count <= 0) continue;
|
||||
@ -1215,7 +1215,7 @@ void phys_update_aabbs(PhysStepCtx *ctx)
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
Space *space = ctx->sim_step_ctx->accel->space;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
if (ent->local_collider.count > 0) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
|
||||
@ -20,7 +20,7 @@ void sim_accel_reset(Snapshot *ss, SimAccel *accel)
|
||||
|
||||
/* Reset ent space handles */
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
if (ent->valid) {
|
||||
MEMZERO_STRUCT(&ent->space_handle);
|
||||
}
|
||||
@ -33,9 +33,9 @@ void sim_accel_reset(Snapshot *ss, SimAccel *accel)
|
||||
|
||||
/* TODO: Remove this */
|
||||
|
||||
INTERNAL struct sim_ent *test_spawn_smg(struct sim_ent *parent)
|
||||
INTERNAL Ent *test_spawn_smg(Ent *parent)
|
||||
{
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
e->sprite = sprite_tag_from_path(LIT("sprite/gun.ase"));
|
||||
|
||||
sim_ent_enable_prop(e, SEPROP_ATTACHED);
|
||||
@ -49,9 +49,9 @@ INTERNAL struct sim_ent *test_spawn_smg(struct sim_ent *parent)
|
||||
return e;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *test_spawn_launcher(struct sim_ent *parent)
|
||||
INTERNAL Ent *test_spawn_launcher(Ent *parent)
|
||||
{
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
e->sprite = sprite_tag_from_path(LIT("sprite/gun.ase"));
|
||||
|
||||
sim_ent_enable_prop(e, SEPROP_ATTACHED);
|
||||
@ -65,9 +65,9 @@ INTERNAL struct sim_ent *test_spawn_launcher(struct sim_ent *parent)
|
||||
return e;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *test_spawn_chucker(struct sim_ent *parent)
|
||||
INTERNAL Ent *test_spawn_chucker(Ent *parent)
|
||||
{
|
||||
struct sim_ent *chucker = sim_ent_alloc_sync_src(parent);
|
||||
Ent *chucker = sim_ent_alloc_sync_src(parent);
|
||||
chucker->sprite = sprite_tag_from_path(LIT("sprite/gun.ase"));
|
||||
|
||||
sim_ent_enable_prop(chucker, SEPROP_ATTACHED);
|
||||
@ -80,7 +80,7 @@ INTERNAL struct sim_ent *test_spawn_chucker(struct sim_ent *parent)
|
||||
|
||||
/* Chucker zone */
|
||||
{
|
||||
struct sim_ent *zone = sim_ent_alloc_sync_src(chucker);
|
||||
Ent *zone = sim_ent_alloc_sync_src(chucker);
|
||||
|
||||
sim_ent_enable_prop(zone, SEPROP_CHUCKER_ZONE);
|
||||
|
||||
@ -100,13 +100,13 @@ INTERNAL struct sim_ent *test_spawn_chucker(struct sim_ent *parent)
|
||||
return chucker;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *test_spawn_employee(struct sim_ent *parent)
|
||||
INTERNAL Ent *test_spawn_employee(Ent *parent)
|
||||
{
|
||||
/* Player */
|
||||
struct sim_ent *employee = sim_ent_nil();
|
||||
Ent *employee = sim_ent_nil();
|
||||
{
|
||||
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
V2 pos = V2FromXY(1, -1);
|
||||
|
||||
@ -174,7 +174,7 @@ INTERNAL struct sim_ent *test_spawn_employee(struct sim_ent *parent)
|
||||
(UNUSED)test_spawn_launcher;
|
||||
(UNUSED)test_spawn_chucker;
|
||||
|
||||
struct sim_ent *e = test_spawn_chucker(employee);
|
||||
Ent *e = test_spawn_chucker(employee);
|
||||
employee->equipped = e->id;
|
||||
|
||||
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
||||
@ -184,9 +184,9 @@ INTERNAL struct sim_ent *test_spawn_employee(struct sim_ent *parent)
|
||||
return employee;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *test_spawn_camera(struct sim_ent *parent, struct sim_ent *follow)
|
||||
INTERNAL Ent *test_spawn_camera(Ent *parent, Ent *follow)
|
||||
{
|
||||
struct sim_ent *camera_ent = sim_ent_nil();
|
||||
Ent *camera_ent = sim_ent_nil();
|
||||
if (follow->valid) {
|
||||
camera_ent = sim_ent_alloc_sync_src(parent);
|
||||
sim_ent_set_xform(camera_ent, XFORM_IDENT);
|
||||
@ -203,9 +203,9 @@ INTERNAL struct sim_ent *test_spawn_camera(struct sim_ent *parent, struct sim_en
|
||||
return camera_ent;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *test_spawn_explosion(struct sim_ent *parent, V2 pos, f32 strength, f32 radius)
|
||||
INTERNAL Ent *test_spawn_explosion(Ent *parent, V2 pos, f32 strength, f32 radius)
|
||||
{
|
||||
struct sim_ent *ent = sim_ent_alloc_sync_src(parent);
|
||||
Ent *ent = sim_ent_alloc_sync_src(parent);
|
||||
sim_ent_set_xform(ent, XFORM_POS(pos));
|
||||
|
||||
sim_ent_enable_prop(ent, SEPROP_EXPLOSION);
|
||||
@ -219,7 +219,7 @@ INTERNAL struct sim_ent *test_spawn_explosion(struct sim_ent *parent, V2 pos, f3
|
||||
return ent;
|
||||
}
|
||||
|
||||
INTERNAL void test_teleport(struct sim_ent *ent, V2 pos)
|
||||
INTERNAL void test_teleport(Ent *ent, V2 pos)
|
||||
{
|
||||
//++ent->continuity_gen;
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -227,28 +227,28 @@ INTERNAL void test_teleport(struct sim_ent *ent, V2 pos)
|
||||
sim_ent_set_xform(ent, xf);
|
||||
}
|
||||
|
||||
INTERNAL void test_spawn_entities1(struct sim_ent *parent, V2 pos)
|
||||
INTERNAL void test_spawn_entities1(Ent *parent, V2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Enemy */
|
||||
{
|
||||
struct sim_ent *e = test_spawn_employee(parent);
|
||||
Ent *e = test_spawn_employee(parent);
|
||||
Xform xf = sim_ent_get_xform(e);
|
||||
xf.og = pos;
|
||||
sim_ent_set_xform(e, xf);
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL void test_spawn_entities2(struct sim_ent *parent, V2 pos)
|
||||
INTERNAL void test_spawn_entities2(Ent *parent, V2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Small Box */
|
||||
#if 1
|
||||
{
|
||||
//struct sim_ent *e = sim_ent_alloc_local(parent);
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
//Ent *e = sim_ent_alloc_local(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 rot = 0;
|
||||
V2 size = V2FromXY(0.125, 0.125);
|
||||
@ -290,7 +290,7 @@ INTERNAL void test_spawn_entities2(struct sim_ent *parent, V2 pos)
|
||||
/* Tiny box */
|
||||
#if 0
|
||||
{
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 r = PI / 4;
|
||||
V2 size = V2FromXY(0.5, 0.25);
|
||||
@ -311,14 +311,14 @@ INTERNAL void test_spawn_entities2(struct sim_ent *parent, V2 pos)
|
||||
#endif
|
||||
}
|
||||
|
||||
INTERNAL void test_spawn_entities3(struct sim_ent *parent, V2 pos)
|
||||
INTERNAL void test_spawn_entities3(Ent *parent, V2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Heavy box */
|
||||
{
|
||||
//struct sim_ent *e = sim_ent_alloc_local(parent);
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
//Ent *e = sim_ent_alloc_local(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 r = 0;
|
||||
V2 size = V2FromXY(1, 1);
|
||||
@ -336,12 +336,12 @@ INTERNAL void test_spawn_entities3(struct sim_ent *parent, V2 pos)
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL void test_spawn_entities4(struct sim_ent *parent, V2 pos)
|
||||
INTERNAL void test_spawn_entities4(Ent *parent, V2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Light box */
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 r = 0;
|
||||
V2 size = V2FromXY(2, 1);
|
||||
@ -361,7 +361,7 @@ INTERNAL void test_spawn_entities4(struct sim_ent *parent, V2 pos)
|
||||
INTERNAL void test_spawn_tile(Snapshot *world, V2 world_pos)
|
||||
{
|
||||
#if 0
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
i32 sign_x = (world_pos.x >= 0) - (world_pos.x < 0);
|
||||
i32 sign_y = (world_pos.y >= 0) - (world_pos.y < 0);
|
||||
@ -408,8 +408,8 @@ INTERNAL void test_spawn_tile(Snapshot *world, V2 world_pos)
|
||||
INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort_x, arg_a, arg_b, udata)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
struct sim_ent *a = *(struct sim_ent **)arg_a;
|
||||
struct sim_ent *b = *(struct sim_ent **)arg_b;
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
i32 a_x = a->tile_chunk_index.x;
|
||||
i32 b_x = b->tile_chunk_index.x;
|
||||
|
||||
@ -421,8 +421,8 @@ INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort_x, arg_a, arg_b, udata)
|
||||
INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort_y, arg_a, arg_b, udata)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
struct sim_ent *a = *(struct sim_ent **)arg_a;
|
||||
struct sim_ent *b = *(struct sim_ent **)arg_b;
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
i32 a_y = a->tile_chunk_index.y;
|
||||
i32 b_y = b->tile_chunk_index.y;
|
||||
|
||||
@ -435,29 +435,29 @@ INTERNAL void test_generate_walls(Snapshot *world)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
|
||||
/* Release existing walls and gather tile chunks.
|
||||
* NOTE: We sort tile chunks before iterating so that chunk-edge tiles only
|
||||
* need to check for adjacent walls to merge with in one direction */
|
||||
struct sim_ent **x_sorted_tile_chunks = 0;
|
||||
struct sim_ent **y_sorted_tile_chunks = 0;
|
||||
Ent **x_sorted_tile_chunks = 0;
|
||||
Ent **y_sorted_tile_chunks = 0;
|
||||
u64 sorted_tile_chunks_count = 0;
|
||||
{
|
||||
x_sorted_tile_chunks = arena_push_dry(scratch.arena, struct sim_ent *);
|
||||
x_sorted_tile_chunks = arena_push_dry(scratch.arena, Ent *);
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!ent->valid) continue;
|
||||
if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) {
|
||||
/* Append chunk to array */
|
||||
*arena_push_no_zero(scratch.arena, struct sim_ent *) = ent;
|
||||
*arena_push_no_zero(scratch.arena, Ent *) = ent;
|
||||
++sorted_tile_chunks_count;
|
||||
} else if (sim_ent_has_prop(ent, SEPROP_WALL)) {
|
||||
/* Release existing wall */
|
||||
sim_ent_enable_prop(ent, SEPROP_RELEASE);
|
||||
}
|
||||
}
|
||||
y_sorted_tile_chunks = arena_push_array_no_zero(scratch.arena, struct sim_ent *, sorted_tile_chunks_count);
|
||||
y_sorted_tile_chunks = arena_push_array_no_zero(scratch.arena, Ent *, sorted_tile_chunks_count);
|
||||
MEMCPY(y_sorted_tile_chunks, x_sorted_tile_chunks, sizeof(*x_sorted_tile_chunks) * sorted_tile_chunks_count);
|
||||
|
||||
/* NOTE: We sort x & y separately because it's possible that a wall
|
||||
@ -482,10 +482,10 @@ INTERNAL void test_generate_walls(Snapshot *world)
|
||||
|
||||
/* Generate horizontal wall nodes */
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||
struct sim_ent *chunk = x_sorted_tile_chunks[sorted_index];
|
||||
Ent *chunk = x_sorted_tile_chunks[sorted_index];
|
||||
V2i32 chunk_index = chunk->tile_chunk_index;
|
||||
struct sim_ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y - 1));
|
||||
struct sim_ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y + 1));
|
||||
Ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y - 1));
|
||||
Ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y + 1));
|
||||
/* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
@ -571,10 +571,10 @@ INTERNAL void test_generate_walls(Snapshot *world)
|
||||
|
||||
/* Generate vertical wall nodes */
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||
struct sim_ent *chunk = y_sorted_tile_chunks[sorted_index];
|
||||
Ent *chunk = y_sorted_tile_chunks[sorted_index];
|
||||
V2i32 chunk_index = chunk->tile_chunk_index;
|
||||
struct sim_ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x - 1, chunk_index.y));
|
||||
struct sim_ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x + 1, chunk_index.y));
|
||||
Ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x - 1, chunk_index.y));
|
||||
Ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x + 1, chunk_index.y));
|
||||
/* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid;
|
||||
@ -661,7 +661,7 @@ INTERNAL void test_generate_walls(Snapshot *world)
|
||||
|
||||
/* Create wall entities */
|
||||
for (struct wall_node *node = first_wall; node; node = node->next) {
|
||||
struct sim_ent *wall_ent = sim_ent_alloc_sync_src(root);
|
||||
Ent *wall_ent = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_enable_prop(wall_ent, SEPROP_WALL);
|
||||
|
||||
V2 start = sim_pos_from_world_tile_index(node->start);
|
||||
@ -699,7 +699,7 @@ INTERNAL void test_clear_level(SimStepCtx *ctx)
|
||||
{
|
||||
Snapshot *world = ctx->world;
|
||||
for (u64 j = 0; j < world->num_ents_reserved; ++j) {
|
||||
struct sim_ent *ent = &world->ents[j];
|
||||
Ent *ent = &world->ents[j];
|
||||
if (ent->valid) {
|
||||
sim_ent_enable_prop(ent, SEPROP_RELEASE);
|
||||
}
|
||||
@ -713,9 +713,9 @@ INTERNAL void test_clear_level(SimStepCtx *ctx)
|
||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
{
|
||||
Snapshot *world = step_ctx->world;
|
||||
struct sim_ent *e0 = sim_ent_from_id(world, data->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(world, data->e1);
|
||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
Ent *e0 = sim_ent_from_id(world, data->e0);
|
||||
Ent *e1 = sim_ent_from_id(world, data->e1);
|
||||
Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
b32 skip_solve = 0;
|
||||
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
@ -724,16 +724,16 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
V2 normal = data->normal; /* Impact normal */
|
||||
V2 vrel = data->vrel; /* Impact velocity */
|
||||
|
||||
struct sim_ent *bullet = e0;
|
||||
struct sim_ent *target = e1;
|
||||
struct sim_ent *src = sim_ent_from_id(world, bullet->bullet_src);
|
||||
Ent *bullet = e0;
|
||||
Ent *target = e1;
|
||||
Ent *src = sim_ent_from_id(world, bullet->bullet_src);
|
||||
|
||||
/* Process collision if bullet already spent or * target share same top level parent */
|
||||
if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top) && sim_ent_has_prop(target, SEPROP_SOLID)) {
|
||||
V2 point = data->point;
|
||||
|
||||
/* Update tracer */
|
||||
struct sim_ent *tracer = sim_ent_from_id(world, bullet->bullet_tracer);
|
||||
Ent *tracer = sim_ent_from_id(world, bullet->bullet_tracer);
|
||||
if (sim_ent_should_simulate(tracer)) {
|
||||
Xform xf = sim_ent_get_xform(tracer);
|
||||
xf.og = point;
|
||||
@ -749,7 +749,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
/* TODO: Remove this */
|
||||
{
|
||||
Xform xf = XFORM_TRS(.t = point, .r = rand_f64_from_state(&step_ctx->rand, 0, TAU));
|
||||
struct sim_ent *decal = sim_ent_alloc_sync_src(root);
|
||||
Ent *decal = sim_ent_alloc_sync_src(root);
|
||||
decal->sprite = sprite_tag_from_path(LIT("sprite/blood.ase"));
|
||||
decal->sprite_tint = RGBA32_F(1, 1, 1, 0.25f);
|
||||
decal->layer = SIM_LAYER_FLOOR_DECALS;
|
||||
@ -783,8 +783,8 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
|
||||
/* Explosion blast collision */
|
||||
if (sim_ent_has_prop(e0, SEPROP_EXPLOSION)) {
|
||||
struct sim_ent *exp = e0;
|
||||
struct sim_ent *victim = e1;
|
||||
Ent *exp = e0;
|
||||
Ent *victim = e1;
|
||||
|
||||
Xform xf = sim_ent_get_xform(exp);
|
||||
|
||||
@ -862,7 +862,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
S_Scope *sprite_frame_scope = sprite_scope_begin();
|
||||
|
||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
root->owner = world->client->player_id;
|
||||
|
||||
/* ========================== *
|
||||
@ -874,7 +874,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) {
|
||||
Client *client = &client_store->clients[client_index];
|
||||
if (client->valid && client != master_client && client != world_client && client != publish_client) {
|
||||
struct sim_ent *player = sim_ent_from_id(world, client->player_id);
|
||||
Ent *player = sim_ent_from_id(world, client->player_id);
|
||||
|
||||
/* Create player if necessary */
|
||||
if (is_master && !player->valid) {
|
||||
@ -892,7 +892,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
player->owner = player->id;
|
||||
sim_ent_enable_prop(player, SEPROP_PLAYER_IS_MASTER);
|
||||
}
|
||||
logf_info("Created player with id %F for sim client %F. is_master: %F", FMT_UID(player->id.uid), FMT_HANDLE(client->handle), FMT_UINT(sim_ent_has_prop(player, SEPROP_PLAYER_IS_MASTER)));
|
||||
P_LogInfoF("Created player with id %F for sim client %F. is_master: %F", FMT_UID(player->id.uid), FMT_HANDLE(client->handle), FMT_UINT(sim_ent_has_prop(player, SEPROP_PLAYER_IS_MASTER)));
|
||||
}
|
||||
|
||||
/* Update rtt */
|
||||
@ -914,7 +914,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Mark all incoming ents as sync dsts */
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
struct sim_ent *ent = &world->ents[i];
|
||||
Ent *ent = &world->ents[i];
|
||||
if (ent->valid && sim_ent_has_prop(ent, SEPROP_SYNC_SRC) && !sim_ent_id_eq(ent->owner, world_client->player_id)) {
|
||||
sim_ent_disable_prop(ent, SEPROP_SYNC_SRC);
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_DST);
|
||||
@ -923,7 +923,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Mark incoming cmds with correct client */
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
struct sim_ent *ent = &world->ents[i];
|
||||
Ent *ent = &world->ents[i];
|
||||
if (ent->valid && sim_ent_has_prop(ent, SEPROP_CMD) && sim_ent_has_prop(ent, SEPROP_SYNC_DST)) {
|
||||
ent->cmd_player = ent->owner;
|
||||
}
|
||||
@ -932,7 +932,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
/* Mark any locally created CMDs as sync sources */
|
||||
if (!is_master) {
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
struct sim_ent *ent = &world->ents[i];
|
||||
Ent *ent = &world->ents[i];
|
||||
if (sim_ent_is_valid_and_active(ent) && sim_ent_has_prop(ent, SEPROP_CMD)) {
|
||||
if (!sim_ent_id_is_nil(ent->cmd_player) && sim_ent_id_eq(ent->cmd_player, world->local_player)) {
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_SRC);
|
||||
@ -954,7 +954,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!ent->valid) continue;
|
||||
if (sim_ent_has_prop(ent, SEPROP_SYNC_DST) && !sim_ent_is_owner(ent) && !sim_ent_should_predict(ent)) continue;
|
||||
|
||||
@ -971,11 +971,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *cmd_ent = &world->ents[ent_index];
|
||||
Ent *cmd_ent = &world->ents[ent_index];
|
||||
if (!is_master && !sim_ent_should_simulate(cmd_ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(cmd_ent, SEPROP_CMD)) {
|
||||
struct sim_ent *player = sim_ent_from_id(world, cmd_ent->cmd_player);
|
||||
Ent *player = sim_ent_from_id(world, cmd_ent->cmd_player);
|
||||
if (sim_ent_should_simulate(player)) {
|
||||
b32 persist_cmd = 0;
|
||||
if (!is_master && !sim_ent_id_eq(player->id, world->local_player)) {
|
||||
@ -1019,7 +1019,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_DELETE) {
|
||||
struct sim_ent *ent = sim_ent_from_id(world, player->player_hovered_ent);
|
||||
Ent *ent = sim_ent_from_id(world, player->player_hovered_ent);
|
||||
if (ent->valid) {
|
||||
sim_ent_enable_prop(ent, SEPROP_RELEASE);
|
||||
}
|
||||
@ -1028,7 +1028,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
test_clear_level(ctx);
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_SPAWN1_TEST) {
|
||||
logf_debug("Spawn test 1");
|
||||
P_LogDebugF("Spawn test 1");
|
||||
u32 count = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
@ -1038,7 +1038,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_SPAWN2_TEST) {
|
||||
logf_debug("Spawn test 2");
|
||||
P_LogDebugF("Spawn test 2");
|
||||
u32 count = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
@ -1048,7 +1048,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_SPAWN3_TEST) {
|
||||
logf_debug("Spawn test 3");
|
||||
P_LogDebugF("Spawn test 3");
|
||||
u32 count = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
@ -1058,7 +1058,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_SPAWN4_TEST) {
|
||||
logf_debug("Spawn test 4");
|
||||
P_LogDebugF("Spawn test 4");
|
||||
u32 count = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
@ -1071,7 +1071,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
test_generate_walls(world);
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) {
|
||||
logf_debug("Explosion test");
|
||||
P_LogDebugF("Explosion test");
|
||||
test_spawn_explosion(root, player->player_cursor_pos, 100, 2);
|
||||
}
|
||||
}
|
||||
@ -1090,7 +1090,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
struct sim_data_key msg_key = cmd_ent->cmd_chat_msg;
|
||||
String msg = sim_data_from_key(sim_data_store, msg_key);
|
||||
if (msg.len > 0) {
|
||||
struct sim_ent *chat_ent = sim_ent_alloc_sync_src(root);
|
||||
Ent *chat_ent = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_enable_prop(chat_ent, SEPROP_CHAT);
|
||||
chat_ent->chat_player = player->id;
|
||||
chat_ent->chat_msg = msg_key;
|
||||
@ -1118,11 +1118,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
struct sim_ent *player = sim_ent_from_id(world, ent->controlling_player);
|
||||
Ent *player = sim_ent_from_id(world, ent->controlling_player);
|
||||
if (player->valid) {
|
||||
ent->control = player->player_control;
|
||||
}
|
||||
@ -1135,11 +1135,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
if (is_master) {
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
struct sim_ent *ent = &world->ents[i];
|
||||
Ent *ent = &world->ents[i];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (sim_ent_has_prop(ent, SEPROP_PLAYER)) {
|
||||
/* FIXME: Ents never released when client disconnects */
|
||||
struct sim_ent *control_ent = sim_ent_from_id(world, ent->player_control_ent);
|
||||
Ent *control_ent = sim_ent_from_id(world, ent->player_control_ent);
|
||||
if (!control_ent->valid) {
|
||||
control_ent = test_spawn_employee(root);
|
||||
control_ent->predictor = ent->id;
|
||||
@ -1147,13 +1147,13 @@ void sim_step(SimStepCtx *ctx)
|
||||
ent->player_control_ent = control_ent->id;
|
||||
control_ent->controlling_player = ent->id;
|
||||
}
|
||||
struct sim_ent *camera_ent = sim_ent_from_id(world, ent->player_camera_ent);
|
||||
Ent *camera_ent = sim_ent_from_id(world, ent->player_camera_ent);
|
||||
if (!camera_ent->valid) {
|
||||
camera_ent = test_spawn_camera(root, control_ent);
|
||||
camera_ent->predictor = ent->id;
|
||||
ent->player_camera_ent = camera_ent->id;
|
||||
}
|
||||
struct sim_ent *camera_follow = sim_ent_from_id(world, camera_ent->camera_follow);
|
||||
Ent *camera_follow = sim_ent_from_id(world, camera_ent->camera_follow);
|
||||
if (!camera_follow->valid) {
|
||||
camera_ent->camera_follow = control_ent->id;
|
||||
}
|
||||
@ -1166,7 +1166,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (sprite_tag_is_nil(ent->sprite)) continue;
|
||||
|
||||
@ -1268,11 +1268,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_ATTACHED)) continue;
|
||||
|
||||
struct sim_ent *parent = sim_ent_from_id(world, ent->parent);
|
||||
Ent *parent = sim_ent_from_id(world, ent->parent);
|
||||
S_Tag parent_sprite = parent->sprite;
|
||||
S_Sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite);
|
||||
|
||||
@ -1293,20 +1293,20 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
ControlData *control = &ent->control;
|
||||
u32 flags = control->flags;
|
||||
if (flags & SIM_CONTROL_FLAG_FIRE) {
|
||||
struct sim_ent *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
Ent *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
if (equipped->valid) {
|
||||
++equipped->num_primary_triggers;
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_FIRE_ALT) {
|
||||
struct sim_ent *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
Ent *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
if (equipped->valid) {
|
||||
++equipped->num_secondary_triggers;
|
||||
}
|
||||
@ -1322,7 +1322,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
b32 primary_triggered = ent->num_primary_triggers > 0;
|
||||
@ -1359,7 +1359,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
V2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
||||
|
||||
/* Spawn bullet */
|
||||
struct sim_ent *bullet;
|
||||
Ent *bullet;
|
||||
{
|
||||
bullet = sim_ent_alloc_sync_src(root);
|
||||
|
||||
@ -1384,7 +1384,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Spawn tracer */
|
||||
{
|
||||
struct sim_ent *tracer = sim_ent_alloc_sync_src(root);
|
||||
Ent *tracer = sim_ent_alloc_sync_src(root);
|
||||
tracer->tracer_fade_duration = 0.025f;
|
||||
tracer->layer = SIM_LAYER_TRACERS;
|
||||
sim_ent_enable_prop(tracer, SEPROP_TRACER);
|
||||
@ -1406,7 +1406,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
V2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
||||
|
||||
/* Spawn bullet */
|
||||
struct sim_ent *bullet;
|
||||
Ent *bullet;
|
||||
{
|
||||
bullet = sim_ent_alloc_sync_src(root);
|
||||
|
||||
@ -1430,7 +1430,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Spawn tracer */
|
||||
{
|
||||
struct sim_ent *tracer = sim_ent_alloc_sync_src(root);
|
||||
Ent *tracer = sim_ent_alloc_sync_src(root);
|
||||
tracer->tracer_fade_duration = 0.025f;
|
||||
tracer->layer = SIM_LAYER_TRACERS;
|
||||
sim_ent_enable_prop(tracer, SEPROP_TRACER);
|
||||
@ -1445,12 +1445,12 @@ void sim_step(SimStepCtx *ctx)
|
||||
if (primary_triggered) {
|
||||
}
|
||||
if (secondary_triggered) {
|
||||
struct sim_ent *zone = sim_ent_from_id(world, ent->chucker_zone);
|
||||
struct sim_ent *target = sim_ent_from_id(world, zone->chucker_zone_ent);
|
||||
struct sim_ent *old_joint_ent = sim_ent_from_id(world, ent->chucker_joint);
|
||||
Ent *zone = sim_ent_from_id(world, ent->chucker_zone);
|
||||
Ent *target = sim_ent_from_id(world, zone->chucker_zone_ent);
|
||||
Ent *old_joint_ent = sim_ent_from_id(world, ent->chucker_joint);
|
||||
if (sim_ent_is_valid_and_active(target) && zone->chucker_zone_ent_tick == world->tick - 1) {
|
||||
if (!sim_ent_id_eq(old_joint_ent->weld_joint_data.e1, target->id)) {
|
||||
struct sim_ent *joint_ent = sim_ent_alloc_sync_src(root);
|
||||
Ent *joint_ent = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE);
|
||||
|
||||
Xform xf0 = sim_ent_get_xform(ent);
|
||||
@ -1483,11 +1483,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->move_joint);
|
||||
Ent *joint_ent = sim_ent_from_id(world, ent->move_joint);
|
||||
if (is_master && !sim_ent_is_valid_and_active(joint_ent)) {
|
||||
joint_ent = sim_ent_alloc_sync_src(root);
|
||||
joint_ent->predictor = ent->predictor;
|
||||
@ -1520,7 +1520,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
#if SIM_PLAYER_AIM
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
@ -1528,7 +1528,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
Xform sprite_xf = xform_mul(xf, ent->sprite_local_xform);
|
||||
|
||||
/* Retrieve / create aim joint */
|
||||
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->aim_joint);
|
||||
Ent *joint_ent = sim_ent_from_id(world, ent->aim_joint);
|
||||
if (is_master && !sim_ent_is_valid_and_active(joint_ent)) {
|
||||
joint_ent = sim_ent_alloc_sync_src(root);
|
||||
joint_ent->predictor = ent->predictor;
|
||||
@ -1618,11 +1618,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
#if 1
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC)) continue;
|
||||
|
||||
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->ground_friction_joint);
|
||||
Ent *joint_ent = sim_ent_from_id(world, ent->ground_friction_joint);
|
||||
|
||||
MotorJointDesc def = phys_motor_joint_def_init();
|
||||
def.e0 = root->id;
|
||||
@ -1649,7 +1649,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
if (is_master) {
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
struct sim_ent *player = &world->ents[i];
|
||||
Ent *player = &world->ents[i];
|
||||
if (!sim_ent_should_simulate(player)) continue;
|
||||
if (!sim_ent_has_prop(player, SEPROP_PLAYER)) continue;
|
||||
|
||||
@ -1657,8 +1657,8 @@ void sim_step(SimStepCtx *ctx)
|
||||
b32 start_dragging = player->player_dbg_drag_start;
|
||||
b32 stop_dragging = player->player_dbg_drag_stop;
|
||||
|
||||
struct sim_ent *joint_ent = sim_ent_from_id(world, player->player_dbg_drag_joint_ent);
|
||||
struct sim_ent *target_ent = sim_ent_from_id(world, joint_ent->mouse_joint_data.target);
|
||||
Ent *joint_ent = sim_ent_from_id(world, player->player_dbg_drag_joint_ent);
|
||||
Ent *target_ent = sim_ent_from_id(world, joint_ent->mouse_joint_data.target);
|
||||
|
||||
if (stop_dragging) {
|
||||
target_ent = sim_ent_nil();
|
||||
@ -1714,7 +1714,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_EXPLOSION)) continue;
|
||||
|
||||
@ -1727,7 +1727,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_TRACER)) continue;
|
||||
|
||||
@ -1751,12 +1751,12 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_BULLET)) continue;
|
||||
|
||||
if (ent->activation_tick == world->tick) {
|
||||
struct sim_ent *src = sim_ent_from_id(world, ent->bullet_src);
|
||||
Ent *src = sim_ent_from_id(world, ent->bullet_src);
|
||||
Xform src_xf = sim_ent_get_xform(src);
|
||||
|
||||
/* Activate collision */
|
||||
@ -1771,7 +1771,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
/* Add shooter velocity to bullet */
|
||||
{
|
||||
/* TODO: Add angular velocity as well? */
|
||||
struct sim_ent *top = sim_ent_from_id(ss_blended, src->top);
|
||||
Ent *top = sim_ent_from_id(ss_blended, src->top);
|
||||
impulse = v2_add(impulse, v2_mul(top->linear_velocity, dt));
|
||||
}
|
||||
#endif
|
||||
@ -1783,7 +1783,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
sim_ent_set_linear_velocity(ent, vel);
|
||||
|
||||
/* Initialize tracer */
|
||||
struct sim_ent *tracer = sim_ent_from_id(world, ent->bullet_tracer);
|
||||
Ent *tracer = sim_ent_from_id(world, ent->bullet_tracer);
|
||||
if (sim_ent_should_simulate(tracer)) {
|
||||
sim_ent_set_xform(tracer, xf);
|
||||
sim_ent_enable_prop(tracer, SEPROP_KINEMATIC);
|
||||
@ -1796,7 +1796,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Spawn quake */
|
||||
{
|
||||
struct sim_ent *quake = sim_ent_alloc_sync_src(root);
|
||||
Ent *quake = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_set_xform(quake, XFORM_POS(pos));
|
||||
quake->quake_intensity = 0.2f;
|
||||
quake->quake_fade = quake->quake_intensity / 0.1f;
|
||||
@ -1810,7 +1810,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_CAMERA)) continue;
|
||||
|
||||
@ -1818,7 +1818,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Camera follow */
|
||||
{
|
||||
struct sim_ent *follow = sim_ent_from_id(world, ent->camera_follow);
|
||||
Ent *follow = sim_ent_from_id(world, ent->camera_follow);
|
||||
|
||||
f32 aspect_ratio = 1.0;
|
||||
{
|
||||
@ -1851,7 +1851,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
/* TODO: Update based on distance to quake */
|
||||
ent->shake = 0;
|
||||
for (u64 quake_ent_index = 0; quake_ent_index < world->num_ents_reserved; ++quake_ent_index) {
|
||||
struct sim_ent *quake = &world->ents[quake_ent_index];
|
||||
Ent *quake = &world->ents[quake_ent_index];
|
||||
if (!sim_ent_should_simulate(quake)) continue;
|
||||
if (!sim_ent_has_prop(quake, SEPROP_QUAKE)) continue;
|
||||
ent->shake += quake->quake_intensity;
|
||||
@ -1866,7 +1866,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_QUAKE)) continue;
|
||||
|
||||
@ -1883,20 +1883,20 @@ void sim_step(SimStepCtx *ctx)
|
||||
{
|
||||
TempArena temp = arena_temp_begin(scratch.arena);
|
||||
|
||||
struct sim_ent **stack = arena_push_no_zero(temp.arena, struct sim_ent *);
|
||||
Ent **stack = arena_push_no_zero(temp.arena, Ent *);
|
||||
u64 stack_count = 1;
|
||||
*stack = root;
|
||||
|
||||
while (stack_count > 0) {
|
||||
struct sim_ent *parent;
|
||||
arena_pop(temp.arena, struct sim_ent *, &parent);
|
||||
Ent *parent;
|
||||
arena_pop(temp.arena, Ent *, &parent);
|
||||
--stack_count;
|
||||
|
||||
i32 parent_layer = parent->final_layer;
|
||||
for (struct sim_ent *child = sim_ent_from_id(world, parent->first); child->valid; child = sim_ent_from_id(world, child->next)) {
|
||||
for (Ent *child = sim_ent_from_id(world, parent->first); child->valid; child = sim_ent_from_id(world, child->next)) {
|
||||
if (sim_ent_should_simulate(child)) {
|
||||
child->final_layer = parent_layer + child->layer;
|
||||
*arena_push_no_zero(temp.arena, struct sim_ent *) = child;
|
||||
*arena_push_no_zero(temp.arena, Ent *) = child;
|
||||
++stack_count;
|
||||
}
|
||||
}
|
||||
@ -1924,7 +1924,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Mark all synced ents as both sync dsts & sync srcs */
|
||||
for (u64 ent_index = 2; ent_index < pub_world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &pub_world->ents[ent_index];
|
||||
Ent *ent = &pub_world->ents[ent_index];
|
||||
if (ent->valid) {
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_DST);
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_SRC);
|
||||
|
||||
@ -43,24 +43,24 @@ INTERNAL struct sound_task_params *sound_task_params_alloc(void)
|
||||
{
|
||||
struct sound_task_params *p = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = P_LockE(&G.params.mutex);
|
||||
if (G.params.head_free) {
|
||||
p = G.params.head_free;
|
||||
G.params.head_free = p->next_free;
|
||||
} else {
|
||||
p = arena_push(G.params.arena, struct sound_task_params);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
INTERNAL void sound_task_params_release(struct sound_task_params *p)
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = P_LockE(&G.params.mutex);
|
||||
p->next_free = G.params.head_free;
|
||||
G.params.head_free = p;
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -76,7 +76,7 @@ INTERNAL P_JobDef(sound_load_asset_job, job)
|
||||
AC_Asset *asset = params->asset;
|
||||
u32 flags = params->flags;
|
||||
|
||||
logf_info("Loading sound \"%F\"", FMT_STR(path));
|
||||
P_LogInfoF("Loading sound \"%F\"", FMT_STR(path));
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
String error_msg = LIT("Unknown error");
|
||||
@ -120,10 +120,10 @@ INTERNAL P_JobDef(sound_load_asset_job, job)
|
||||
sound->pcm.samples = samples;
|
||||
MEMCPY(sound->pcm.samples, decoded.pcm.samples, decoded.pcm.count * sizeof(*decoded.pcm.samples));
|
||||
|
||||
logf_success("Loaded sound \"%F\" in %F seconds", FMT_STR(path), FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)));
|
||||
P_LogSuccessF("Loaded sound \"%F\" in %F seconds", FMT_STR(path), FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)));
|
||||
asset_cache_mark_ready(asset, sound);
|
||||
} else {
|
||||
logf_error("Error loading sound \"%F\": %F", FMT_STR(path), FMT_STR(error_msg));
|
||||
P_LogErrorF("Error loading sound \"%F\": %F", FMT_STR(path), FMT_STR(error_msg));
|
||||
|
||||
/* Store */
|
||||
SND_Sound *sound = 0;
|
||||
|
||||
@ -245,13 +245,13 @@ INTERNAL P_ExitFuncDef(sprite_shutdown)
|
||||
__prof;
|
||||
/* Signal evictor shutdown */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.evictor_scheduler_mutex);
|
||||
P_Lock lock = P_LockE(&G.evictor_scheduler_mutex);
|
||||
G.evictor_scheduler_shutdown = 1;
|
||||
snc_cv_signal(&G.evictor_scheduler_shutdown_cv, I32_MAX);
|
||||
snc_unlock(&lock);
|
||||
P_SignalCv(&G.evictor_scheduler_shutdown_cv, I32_MAX);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
/* Wait for evictor shutdown */
|
||||
snc_counter_wait(&G.shutdown_counter);
|
||||
P_WaitOnCounter(&G.shutdown_counter);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -290,14 +290,14 @@ INTERNAL void push_load_job(struct cache_ref ref, S_Tag tag)
|
||||
{
|
||||
struct load_cmd *cmd = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.load_cmds_mutex);
|
||||
P_Lock lock = P_LockE(&G.load_cmds_mutex);
|
||||
if (G.first_free_load_cmd) {
|
||||
cmd = G.first_free_load_cmd;
|
||||
G.first_free_load_cmd = cmd->next_free;
|
||||
} else {
|
||||
cmd = arena_push_no_zero(G.load_cmds_arena, struct load_cmd);
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(cmd);
|
||||
|
||||
@ -324,7 +324,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, S_Tag tag)
|
||||
atomic32_fetch_set(&e->state, CACHE_ENTRY_STATE_WORKING);
|
||||
String path = tag.path;
|
||||
|
||||
logf_info("Loading sprite texture [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
P_LogInfoF("Loading sprite texture [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
b32 success = 0;
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
@ -343,7 +343,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, S_Tag tag)
|
||||
if (resource_exists(&texture_rs)) {
|
||||
decoded = ase_decode_image(scratch.arena, resource_get_data(&texture_rs));
|
||||
} else {
|
||||
logf_error("Sprite texture for \"%F\" not found", FMT_STR(path));
|
||||
P_LogErrorF("Sprite texture for \"%F\" not found", FMT_STR(path));
|
||||
}
|
||||
resource_close(&texture_rs);
|
||||
}
|
||||
@ -366,7 +366,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, S_Tag tag)
|
||||
atomic64_fetch_add(&G.cache.memory_usage.v, e->memory_usage);
|
||||
|
||||
if (success) {
|
||||
logf_success("Loaded sprite texture [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
P_LogSuccessF("Loaded sprite texture [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
FMT_HEX(e->hash.v),
|
||||
FMT_STR(path),
|
||||
FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)),
|
||||
@ -377,7 +377,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, S_Tag tag)
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
struct cache_bin *bin = &G.cache.bins[e->hash.v % CACHE_BINS_COUNT];
|
||||
P_Lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
||||
{
|
||||
for (struct cache_entry *old_entry = bin->first; old_entry; old_entry = old_entry->next_in_bin) {
|
||||
if (old_entry != e && old_entry->hash.v == e->hash.v) {
|
||||
@ -386,7 +386,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, S_Tag tag)
|
||||
}
|
||||
e->load_time_ns = P_TimeNs();
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
P_Unlock(&bin_lock);
|
||||
#endif
|
||||
|
||||
scratch_end(scratch);
|
||||
@ -647,7 +647,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
|
||||
atomic32_fetch_set(&e->state, CACHE_ENTRY_STATE_WORKING);
|
||||
String path = tag.path;
|
||||
|
||||
logf_info("Loading sprite sheet [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
P_LogInfoF("Loading sprite sheet [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
b32 success = 0;
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
@ -663,7 +663,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
|
||||
if (resource_exists(&sheet_rs)) {
|
||||
decoded = ase_decode_sheet(scratch.arena, resource_get_data(&sheet_rs));
|
||||
} else {
|
||||
logf_error("Sprite sheet for \"%F\" not found", FMT_STR(path));
|
||||
P_LogErrorF("Sprite sheet for \"%F\" not found", FMT_STR(path));
|
||||
}
|
||||
resource_close(&sheet_rs);
|
||||
}
|
||||
@ -687,7 +687,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
|
||||
atomic64_fetch_add(&G.cache.memory_usage.v, e->memory_usage);
|
||||
|
||||
if (success) {
|
||||
logf_success("Loaded sprite sheet [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
P_LogSuccessF("Loaded sprite sheet [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
FMT_HEX(e->hash.v),
|
||||
FMT_STR(path),
|
||||
FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)),
|
||||
@ -698,7 +698,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
struct cache_bin *bin = &G.cache.bins[e->hash.v % CACHE_BINS_COUNT];
|
||||
P_Lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
||||
{
|
||||
for (struct cache_entry *old_entry = bin->first; old_entry; old_entry = old_entry->next_in_bin) {
|
||||
if (old_entry != e && old_entry->hash.v == e->hash.v) {
|
||||
@ -707,7 +707,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
|
||||
}
|
||||
e->load_time_ns = P_TimeNs();
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
P_Unlock(&bin_lock);
|
||||
#endif
|
||||
|
||||
scratch_end(scratch);
|
||||
@ -771,7 +771,7 @@ INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_unsafe(S_Scope *scope,
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_from_entry(S_Scope *scope, struct cache_entry *e, P_Lock *bin_lock)
|
||||
{
|
||||
/* Guaranteed safe if caller has lock on entry's bin, since entry may not have an existing reference and could otherwise be evicted while ensuring this reference */
|
||||
snc_assert_locked_e_or_s(bin_lock, &G.cache.bins[e->hash.v % CACHE_BINS_COUNT].mutex);
|
||||
P_AssertLockedES(bin_lock, &G.cache.bins[e->hash.v % CACHE_BINS_COUNT].mutex);
|
||||
return scope_ensure_ref_unsafe(scope, e);
|
||||
}
|
||||
|
||||
@ -788,7 +788,7 @@ S_Scope *sprite_scope_begin(void)
|
||||
struct sprite_scope_cache_ref **bins = 0;
|
||||
struct sprite_scope_cache_ref *pool = 0;
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.scopes_mutex);
|
||||
P_Lock lock = P_LockE(&G.scopes_mutex);
|
||||
{
|
||||
if (G.first_free_scope) {
|
||||
res = G.first_free_scope;
|
||||
@ -801,7 +801,7 @@ S_Scope *sprite_scope_begin(void)
|
||||
pool = arena_push_array_no_zero(G.scopes_arena, struct sprite_scope_cache_ref, MAX_SCOPE_REFERENCES);
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
MEMZERO_STRUCT(res);
|
||||
MEMZERO(bins, sizeof(*bins) * CACHE_BINS_COUNT);
|
||||
@ -820,12 +820,12 @@ void sprite_scope_end(S_Scope *scope)
|
||||
}
|
||||
|
||||
/* Release scope */
|
||||
P_Lock lock = snc_lock_e(&G.scopes_mutex);
|
||||
P_Lock lock = P_LockE(&G.scopes_mutex);
|
||||
{
|
||||
scope->next_free = G.first_free_scope;
|
||||
G.first_free_scope = scope;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -837,7 +837,7 @@ INTERNAL struct sprite_scope_cache_ref *cache_lookup(S_Scope *scope, struct cach
|
||||
struct sprite_scope_cache_ref *scope_ref = 0;
|
||||
|
||||
struct cache_bin *bin = &G.cache.bins[hash.v % CACHE_BINS_COUNT];
|
||||
snc_assert_locked_e_or_s(bin_lock, &bin->mutex); /* Lock required for iterating bin */
|
||||
P_AssertLockedES(bin_lock, &bin->mutex); /* Lock required for iterating bin */
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
/* If resource reloading is enabled, then we want to find the
|
||||
@ -892,16 +892,16 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(S_Scope *scope, S_T
|
||||
|
||||
/* Search in cache */
|
||||
if (!force_new) {
|
||||
P_Lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
P_Lock bin_lock = P_LockS(&bin->mutex);
|
||||
{
|
||||
scope_ref = cache_lookup(scope, hash, &bin_lock);
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
P_Unlock(&bin_lock);
|
||||
}
|
||||
|
||||
/* If not in cache, allocate new entry */
|
||||
if (!scope_ref) {
|
||||
P_Lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
||||
{
|
||||
/* Search cache one more time in case an entry was allocated between locks */
|
||||
if (!force_new) {
|
||||
@ -912,14 +912,14 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(S_Scope *scope, S_T
|
||||
/* Cache entry still absent, allocate new entry */
|
||||
struct cache_entry *entry = 0;
|
||||
{
|
||||
P_Lock pool_lock = snc_lock_e(&G.cache.entry_pool_mutex);
|
||||
P_Lock pool_lock = P_LockE(&G.cache.entry_pool_mutex);
|
||||
if (G.cache.entry_pool_first_free) {
|
||||
entry = G.cache.entry_pool_first_free;
|
||||
G.cache.entry_pool_first_free = entry->next_free;
|
||||
} else {
|
||||
entry = arena_push_no_zero(G.cache.arena, struct cache_entry);
|
||||
}
|
||||
snc_unlock(&pool_lock);
|
||||
P_Unlock(&pool_lock);
|
||||
}
|
||||
MEMZERO_STRUCT(entry);
|
||||
|
||||
@ -941,7 +941,7 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(S_Scope *scope, S_T
|
||||
scope_ref = scope_ensure_ref_from_entry(scope, entry, &bin_lock);
|
||||
}
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
P_Unlock(&bin_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1126,13 +1126,13 @@ INTERNAL P_JobDef(sprite_load_job, job)
|
||||
}
|
||||
|
||||
/* Free cmd */
|
||||
P_Lock lock = snc_lock_e(&G.load_cmds_mutex);
|
||||
P_Lock lock = P_LockE(&G.load_cmds_mutex);
|
||||
{
|
||||
sprite_scope_end(cmd->scope);
|
||||
cmd->next_free = G.first_free_load_cmd;
|
||||
G.first_free_load_cmd = cmd;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -1146,14 +1146,14 @@ INTERNAL void reload_if_exists(S_Scope *scope, S_Tag tag, enum cache_entry_kind
|
||||
struct cache_entry_hash hash = cache_entry_hash_from_tag_hash(tag.hash, kind);
|
||||
struct cache_bin *bin = &G.cache.bins[hash.v % CACHE_BINS_COUNT];
|
||||
struct sprite_scope_cache_ref *existing_ref = 0;
|
||||
P_Lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
P_Lock bin_lock = P_LockS(&bin->mutex);
|
||||
{
|
||||
existing_ref = cache_lookup(scope, hash, &bin_lock);
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
P_Unlock(&bin_lock);
|
||||
|
||||
if (existing_ref) {
|
||||
logf_info("Sprite resource file \"%F\" has changed for sprite [%F].", FMT_STR(tag.path), FMT_HEX(hash.v));
|
||||
P_LogInfoF("Sprite resource file \"%F\" has changed for sprite [%F].", FMT_STR(tag.path), FMT_HEX(hash.v));
|
||||
struct sprite_scope_cache_ref *scope_ref = cache_entry_from_tag(scope, tag, kind, 1);
|
||||
push_load_job(scope_ref->ref, tag);
|
||||
}
|
||||
@ -1229,7 +1229,7 @@ INTERNAL P_JobDef(sprite_evictor_job, _)
|
||||
__profn("Evictor scan");
|
||||
for (u64 i = 0; i < CACHE_BINS_COUNT; ++i) {
|
||||
struct cache_bin *bin = &G.cache.bins[i];
|
||||
P_Lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
P_Lock bin_lock = P_LockS(&bin->mutex);
|
||||
{
|
||||
struct cache_entry *n = bin->first;
|
||||
while (n) {
|
||||
@ -1258,7 +1258,7 @@ INTERNAL P_JobDef(sprite_evictor_job, _)
|
||||
n = n->next_in_bin;
|
||||
}
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
P_Unlock(&bin_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1282,7 +1282,7 @@ INTERNAL P_JobDef(sprite_evictor_job, _)
|
||||
struct cache_entry *entry = en->cache_entry;
|
||||
i32 last_ref_cycle = en->last_ref_cycle;
|
||||
b32 cache_over_budget_target = atomic64_fetch(&G.cache.memory_usage.v) > (i64)CACHE_MEMORY_BUDGET_TARGET;
|
||||
P_Lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = P_LockE(&bin->mutex);
|
||||
{
|
||||
u64 refcount_uncast = atomic64_fetch(&entry->refcount_struct.v);
|
||||
struct cache_refcount refcount = *(struct cache_refcount *)&refcount_uncast;
|
||||
@ -1313,7 +1313,7 @@ INTERNAL P_JobDef(sprite_evictor_job, _)
|
||||
stop_evicting = 1;
|
||||
}
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
P_Unlock(&bin_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1333,13 +1333,13 @@ INTERNAL P_JobDef(sprite_evictor_job, _)
|
||||
/* Add evicted nodes to free list */
|
||||
{
|
||||
__profn("Evictor free list append");
|
||||
P_Lock pool_lock = snc_lock_e(&G.cache.entry_pool_mutex);
|
||||
P_Lock pool_lock = P_LockE(&G.cache.entry_pool_mutex);
|
||||
for (struct evict_node *en = first_evicted; en; en = en->next_evicted) {
|
||||
struct cache_entry *n = en->cache_entry;
|
||||
n->next_free = G.cache.entry_pool_first_free;
|
||||
G.cache.entry_pool_first_free = n;
|
||||
}
|
||||
snc_unlock(&pool_lock);
|
||||
P_Unlock(&pool_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1349,14 +1349,14 @@ INTERNAL P_JobDef(sprite_evictor_job, _)
|
||||
|
||||
/* Evictor sleep */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.evictor_scheduler_mutex);
|
||||
P_Lock lock = P_LockE(&G.evictor_scheduler_mutex);
|
||||
{
|
||||
if (!G.evictor_scheduler_shutdown) {
|
||||
snc_cv_wait_time(&G.evictor_scheduler_shutdown_cv, &lock, EVICTOR_CYCLE_INTERVAL_NS);
|
||||
P_WaitOnCvTime(&G.evictor_scheduler_shutdown_cv, &lock, EVICTOR_CYCLE_INTERVAL_NS);
|
||||
}
|
||||
shutdown = G.evictor_scheduler_shutdown;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ GLOBAL struct {
|
||||
Arena *console_logs_arena;
|
||||
struct console_log *first_console_log;
|
||||
struct console_log *last_console_log;
|
||||
i32 console_log_color_indices[LOG_LEVEL_COUNT];
|
||||
i32 console_log_color_indices[P_LogLevel_Count];
|
||||
f32 console_logs_height;
|
||||
b32 debug_console;
|
||||
|
||||
@ -174,7 +174,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[P_Btn_Count] = {
|
||||
* ========================== */
|
||||
|
||||
INTERNAL P_ExitFuncDef(user_shutdown);
|
||||
INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log);
|
||||
INTERNAL P_LogEventCallbackFuncDef(debug_console_log_callback, log);
|
||||
INTERNAL P_JobDef(user_update_job, _);
|
||||
INTERNAL P_JobDef(local_sim_job , _);
|
||||
|
||||
@ -225,8 +225,8 @@ struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
G.render_sig = gp_render_sig_alloc();
|
||||
|
||||
G.console_logs_arena = arena_alloc(GIBI(64));
|
||||
//log_register_callback(debug_console_log_callback, LOG_LEVEL_SUCCESS);
|
||||
log_register_callback(debug_console_log_callback, LOG_LEVEL_DEBUG);
|
||||
//P_RegisterLogCallback(debug_console_log_callback, P_LogLevel_Success);
|
||||
P_RegisterLogCallback(debug_console_log_callback, P_LogLevel_Debug);
|
||||
|
||||
G.window = P_AllocWindow();
|
||||
G.swapchain = gp_swapchain_alloc(G.window, V2i32FromXY(100, 100));
|
||||
@ -244,7 +244,7 @@ INTERNAL P_ExitFuncDef(user_shutdown)
|
||||
{
|
||||
__prof;
|
||||
atomic32_fetch_set(&G.shutdown, 1);
|
||||
snc_counter_wait(&G.shutdown_job_counters);
|
||||
P_WaitOnCounter(&G.shutdown_job_counters);
|
||||
P_ReleaseWindow(G.window);
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ INTERNAL void debug_draw_xform(Xform xf, u32 color_x, u32 color_y)
|
||||
//draw_quad(G.render_sig, quad, color);
|
||||
}
|
||||
|
||||
INTERNAL void debug_draw_movement(struct sim_ent *ent)
|
||||
INTERNAL void debug_draw_movement(Ent *ent)
|
||||
{
|
||||
f32 thickness = 2.f;
|
||||
f32 arrow_len = 15.f;
|
||||
@ -293,7 +293,7 @@ INTERNAL void debug_draw_movement(struct sim_ent *ent)
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL String get_ent_debug_text(Arena *arena, struct sim_ent *ent)
|
||||
INTERNAL String get_ent_debug_text(Arena *arena, Ent *ent)
|
||||
{
|
||||
TempArena scratch = scratch_begin(arena);
|
||||
Snapshot *ss = ent->ss;
|
||||
@ -363,7 +363,7 @@ INTERNAL String get_ent_debug_text(Arena *arena, struct sim_ent *ent)
|
||||
|
||||
/* Children */
|
||||
if (!sim_ent_id_is_nil(ent->first) || !sim_ent_id_is_nil(ent->last)) {
|
||||
struct sim_ent *child = sim_ent_from_id(ss, ent->first);
|
||||
Ent *child = sim_ent_from_id(ss, ent->first);
|
||||
if (!sim_ent_id_eq(ent->first, ent->last) || !child->valid) {
|
||||
res.len += string_format(arena, LIT("first child: [%F]\n"), FMT_UID(ent->first.uid)).len;
|
||||
res.len += string_format(arena, LIT("last child: [%F]\n"), FMT_UID(ent->last.uid)).len;
|
||||
@ -385,10 +385,10 @@ INTERNAL String get_ent_debug_text(Arena *arena, struct sim_ent *ent)
|
||||
* Debug console
|
||||
* ========================== */
|
||||
|
||||
INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log)
|
||||
INTERNAL P_LogEventCallbackFuncDef(debug_console_log_callback, log)
|
||||
{
|
||||
__prof;
|
||||
P_Lock lock = snc_lock_e(&G.console_logs_mutex);
|
||||
P_Lock lock = P_LockE(&G.console_logs_mutex);
|
||||
{
|
||||
struct console_log *clog = arena_push(G.console_logs_arena, struct console_log);
|
||||
clog->level = log.level;
|
||||
@ -408,7 +408,7 @@ INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log)
|
||||
}
|
||||
G.last_console_log = clog;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
INTERNAL void draw_debug_console(i32 level, b32 minimized)
|
||||
@ -422,14 +422,14 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
|
||||
f32 spacing = 0;
|
||||
f32 bg_margin = 5;
|
||||
|
||||
LOCAL_PERSIST u32 colors[LOG_LEVEL_COUNT][2] = ZI;
|
||||
LOCAL_PERSIST u32 colors[P_LogLevel_Count][2] = ZI;
|
||||
MEMSET(colors, 0xFF, sizeof(colors));
|
||||
#if 1
|
||||
colors[LOG_LEVEL_DEBUG][0] = RGB32_F(0.4, 0.1, 0.4); colors[LOG_LEVEL_DEBUG][1] = RGB32_F(0.5, 0.2, 0.5);
|
||||
colors[LOG_LEVEL_INFO][0] = RGB32_F(0.4, 0.4, 0.4); colors[LOG_LEVEL_INFO][1] = RGB32_F(0.5, 0.5, 0.5);
|
||||
colors[LOG_LEVEL_SUCCESS][0] = RGB32_F(0.1, 0.3, 0.1); colors[LOG_LEVEL_SUCCESS][1] = RGB32_F(0.2, 0.4, 0.2);
|
||||
colors[LOG_LEVEL_WARNING][0] = RGB32_F(0.4, 0.4, 0.1); colors[LOG_LEVEL_WARNING][1] = RGB32_F(0.5, 0.5, 0.2);
|
||||
colors[LOG_LEVEL_ERROR][0] = RGB32_F(0.4, 0.1, 0.1); colors[LOG_LEVEL_ERROR][1] = RGB32_F(0.5, 0.2, 0.2);
|
||||
colors[P_LogLevel_Debug][0] = RGB32_F(0.4, 0.1, 0.4); colors[P_LogLevel_Debug][1] = RGB32_F(0.5, 0.2, 0.5);
|
||||
colors[P_LogLevel_Info][0] = RGB32_F(0.4, 0.4, 0.4); colors[P_LogLevel_Info][1] = RGB32_F(0.5, 0.5, 0.5);
|
||||
colors[P_LogLevel_Success][0] = RGB32_F(0.1, 0.3, 0.1); colors[P_LogLevel_Success][1] = RGB32_F(0.2, 0.4, 0.2);
|
||||
colors[P_LogLevel_Warning][0] = RGB32_F(0.4, 0.4, 0.1); colors[P_LogLevel_Warning][1] = RGB32_F(0.5, 0.5, 0.2);
|
||||
colors[P_LogLevel_Error][0] = RGB32_F(0.4, 0.1, 0.1); colors[P_LogLevel_Error][1] = RGB32_F(0.5, 0.2, 0.2);
|
||||
#else
|
||||
u32 info_colors[2] = { RGB32_F(0.4, 0.4, 0.4), RGB32_F(0.5, 0.5, 0.5) };
|
||||
u32 success_colors[2] = { RGB32_F(0.1, 0.3, 0.1), RGB32_F(0.2, 0.4, 0.2) };
|
||||
@ -449,7 +449,7 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
|
||||
i64 now_ns = P_TimeNs();
|
||||
F_Font *font = font_load_async(LIT("font/fixedsys.ttf"), 12.0f);
|
||||
if (font) {
|
||||
P_Lock lock = snc_lock_e(&G.console_logs_mutex);
|
||||
P_Lock lock = P_LockE(&G.console_logs_mutex);
|
||||
{
|
||||
for (struct console_log *log = G.last_console_log; log; log = log->prev) {
|
||||
f32 opacity = 0.75;
|
||||
@ -496,7 +496,7 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
|
||||
}
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
if (bounds_top < F32_INFINITY && bounds_bottom > -F32_INFINITY) {
|
||||
G.console_logs_height = bounds_bottom - bounds_top;
|
||||
@ -511,8 +511,8 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
|
||||
INTERNAL SORT_COMPARE_FUNC_DEF(ent_draw_order_cmp, arg_a, arg_b, udata)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
struct sim_ent *a = *(struct sim_ent **)arg_a;
|
||||
struct sim_ent *b = *(struct sim_ent **)arg_b;
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
|
||||
i32 res = 0;
|
||||
|
||||
@ -570,7 +570,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
|
||||
{
|
||||
__profn("Pull snapshot");
|
||||
P_Lock lock = snc_lock_e(&G.local_to_user_client_mutex);
|
||||
P_Lock lock = P_LockE(&G.local_to_user_client_mutex);
|
||||
u64 old_last_tick = G.user_unblended_client->last_tick;
|
||||
u64 last_tick = G.local_to_user_client->last_tick;
|
||||
if (last_tick > old_last_tick) {
|
||||
@ -580,7 +580,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
G.average_local_to_user_snapshot_publish_dt_ns -= G.average_local_to_user_snapshot_publish_dt_ns / 50;
|
||||
G.average_local_to_user_snapshot_publish_dt_ns += G.local_to_user_client_publish_dt_ns / 50;
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -743,15 +743,15 @@ INTERNAL void user_update(P_Window *window)
|
||||
* Find local entities
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *local_player = sim_ent_from_id(G.ss_blended, G.ss_blended->local_player);
|
||||
struct sim_ent *local_control = sim_ent_from_id(G.ss_blended, local_player->player_control_ent);
|
||||
struct sim_ent *local_camera = sim_ent_from_id(G.ss_blended, local_player->player_camera_ent);
|
||||
Ent *local_player = sim_ent_from_id(G.ss_blended, G.ss_blended->local_player);
|
||||
Ent *local_control = sim_ent_from_id(G.ss_blended, local_player->player_control_ent);
|
||||
Ent *local_camera = sim_ent_from_id(G.ss_blended, local_player->player_camera_ent);
|
||||
|
||||
/* ========================== *
|
||||
* Find hovered entity
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *hovered_ent = sim_ent_nil();
|
||||
Ent *hovered_ent = sim_ent_nil();
|
||||
{
|
||||
Xform mouse_xf = xform_from_pos(G.world_cursor);
|
||||
CLD_Shape mouse_shape = ZI;
|
||||
@ -759,7 +759,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
mouse_shape.count = 1;
|
||||
mouse_shape.radius = 0.01f;
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &G.ss_blended->ents[ent_index];
|
||||
Ent *ent = &G.ss_blended->ents[ent_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
|
||||
CLD_Shape ent_collider = ent->local_collider;
|
||||
@ -794,7 +794,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
|
||||
if (G.bind_states[USER_BIND_KIND_DEBUG_TOGGLE_TOPMOST].num_presses > 0) {
|
||||
P_ToggleWindowTopmost(window);
|
||||
logf_success("Toggle topmost");
|
||||
P_LogSuccessF("Toggle topmost");
|
||||
}
|
||||
|
||||
if (G.bind_states[USER_BIND_KIND_DEBUG_CONSOLE].num_presses > 0) {
|
||||
@ -814,11 +814,11 @@ INTERNAL void user_update(P_Window *window)
|
||||
}
|
||||
}
|
||||
if (!sim_ent_id_is_nil(G.debug_following)) {
|
||||
struct sim_ent *follow_ent = sim_ent_from_id(G.ss_blended, G.debug_following);
|
||||
struct sim_ent *follow_camera = sim_ent_nil();
|
||||
Ent *follow_ent = sim_ent_from_id(G.ss_blended, G.debug_following);
|
||||
Ent *follow_camera = sim_ent_nil();
|
||||
for (u64 i = 0; i < G.ss_blended->num_ents_reserved; ++i) {
|
||||
struct sim_ent *ent = &G.ss_blended->ents[i];
|
||||
struct sim_ent *ent_camera_follow = sim_ent_from_id(G.ss_blended, ent->camera_follow);
|
||||
Ent *ent = &G.ss_blended->ents[i];
|
||||
Ent *ent_camera_follow = sim_ent_from_id(G.ss_blended, ent->camera_follow);
|
||||
if (ent_camera_follow->valid && ent_camera_follow == follow_ent) {
|
||||
follow_camera = ent;
|
||||
break;
|
||||
@ -837,7 +837,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &G.ss_blended->ents[ent_index];
|
||||
Ent *ent = &G.ss_blended->ents[ent_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
|
||||
/* How much time between camera shakes */
|
||||
@ -1042,7 +1042,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
/* Alloc entries from new sim chunks */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *chunk_ent = &G.ss_blended->ents[ent_index];
|
||||
Ent *chunk_ent = &G.ss_blended->ents[ent_index];
|
||||
if (sim_ent_is_valid_and_active(chunk_ent) && sim_ent_has_prop(chunk_ent, SEPROP_TILE_CHUNK)) {
|
||||
struct user_tile_cache_entry *entry = user_tile_cache_entry_from_chunk_pos(chunk_ent->tile_chunk_pos);
|
||||
if (!entry->valid) {
|
||||
@ -1056,7 +1056,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
for (u64 entry_index = 0; entry_index < G.tile_cache.num_reserved_entries; ++entry_index) {
|
||||
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
|
||||
if (entry->valid) {
|
||||
struct sim_ent *chunk_ent = sim_ent_from_chunk_pos(entry->pos);
|
||||
Ent *chunk_ent = sim_ent_from_chunk_pos(entry->pos);
|
||||
if (!chunk_ent->valid) {
|
||||
user_tile_cache_entry_release(entry);
|
||||
}
|
||||
@ -1071,7 +1071,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
|
||||
if (entry->valid) {
|
||||
V2i32 chunk_pos = entry->pos;
|
||||
struct sim_ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
Ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
if (entry->applied_dirty_gen != chunk_ent->dirty_gen) {
|
||||
entry->applied_dirty_gen = chunk_ent->dirty_gen;
|
||||
/* TODO: Autotiling */
|
||||
@ -1095,7 +1095,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
|
||||
if (entry->valid) {
|
||||
V2i32 chunk_pos = entry->pos;
|
||||
struct sim_ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
Ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
if (entry->applied_dirty_gen != chunk_ent->dirty_gen) {
|
||||
entry->applied_dirty_gen = chunk_ent->dirty_gen;
|
||||
|
||||
@ -1112,14 +1112,14 @@ INTERNAL void user_update(P_Window *window)
|
||||
V2i32 chunk_pos_bl = V2i32FromXY(chunk_pos.x - 1, chunk_pos.y + 1);
|
||||
V2i32 chunk_pos_b = V2i32FromXY(chunk_pos.x, chunk_pos.y + 1);
|
||||
V2i32 chunk_pos_br = V2i32FromXY(chunk_pos.x + 1, chunk_pos.y + 1);
|
||||
struct sim_ent *chunk_ent_tl = sim_ent_from_chunk_pos(chunk_pos_tl);
|
||||
struct sim_ent *chunk_ent_t = sim_ent_from_chunk_pos(chunk_pos_t);
|
||||
struct sim_ent *chunk_ent_tr = sim_ent_from_chunk_pos(chunk_pos_tr);
|
||||
struct sim_ent *chunk_ent_l = sim_ent_from_chunk_pos(chunk_pos_l);
|
||||
struct sim_ent *chunk_ent_r = sim_ent_from_chunk_pos(chunk_pos_r);
|
||||
struct sim_ent *chunk_ent_bl = sim_ent_from_chunk_pos(chunk_pos_bl);
|
||||
struct sim_ent *chunk_ent_b = sim_ent_from_chunk_pos(chunk_pos_b);
|
||||
struct sim_ent *chunk_ent_br = sim_ent_from_chunk_pos(chunk_pos_br);
|
||||
Ent *chunk_ent_tl = sim_ent_from_chunk_pos(chunk_pos_tl);
|
||||
Ent *chunk_ent_t = sim_ent_from_chunk_pos(chunk_pos_t);
|
||||
Ent *chunk_ent_tr = sim_ent_from_chunk_pos(chunk_pos_tr);
|
||||
Ent *chunk_ent_l = sim_ent_from_chunk_pos(chunk_pos_l);
|
||||
Ent *chunk_ent_r = sim_ent_from_chunk_pos(chunk_pos_r);
|
||||
Ent *chunk_ent_bl = sim_ent_from_chunk_pos(chunk_pos_bl);
|
||||
Ent *chunk_ent_b = sim_ent_from_chunk_pos(chunk_pos_b);
|
||||
Ent *chunk_ent_br = sim_ent_from_chunk_pos(chunk_pos_br);
|
||||
|
||||
String data = sim_ent_get_chunk_tile_data(chunk_ent);
|
||||
|
||||
@ -1134,16 +1134,16 @@ INTERNAL void user_update(P_Window *window)
|
||||
* Sort drawable entities
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent **sorted = arena_push_dry(scratch.arena, struct sim_ent *);
|
||||
Ent **sorted = arena_push_dry(scratch.arena, Ent *);
|
||||
u64 sorted_count = 0;
|
||||
{
|
||||
/* Copy valid entities */
|
||||
{
|
||||
__profn("Build ents list for sorting");
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &G.ss_blended->ents[ent_index];
|
||||
Ent *ent = &G.ss_blended->ents[ent_index];
|
||||
if (sim_ent_is_valid_and_active(ent)) {
|
||||
*arena_push_no_zero(scratch.arena, struct sim_ent *) = ent;
|
||||
*arena_push_no_zero(scratch.arena, Ent *) = ent;
|
||||
++sorted_count;
|
||||
}
|
||||
}
|
||||
@ -1162,13 +1162,13 @@ INTERNAL void user_update(P_Window *window)
|
||||
{
|
||||
__profn("Draw entities");
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) {
|
||||
struct sim_ent *ent = sorted[sorted_index];
|
||||
Ent *ent = sorted[sorted_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
//if (sprite_tag_is_nil(ent->sprite)) continue;
|
||||
|
||||
S_Tag sprite = ent->sprite;
|
||||
|
||||
struct sim_ent *parent = sim_ent_from_id(G.ss_blended, ent->parent);
|
||||
Ent *parent = sim_ent_from_id(G.ss_blended, ent->parent);
|
||||
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
Xform parent_xf = sim_ent_get_xform(parent);
|
||||
@ -1340,7 +1340,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
/* Draw weld joint */
|
||||
#if 0
|
||||
if (sim_ent_has_prop(ent, SEPROP_WELD_JOINT)) {
|
||||
struct sim_ent *e1 = sim_ent_from_id(G.ss_blended, ent->weld_joint_data.e1);
|
||||
Ent *e1 = sim_ent_from_id(G.ss_blended, ent->weld_joint_data.e1);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
|
||||
u32 color = COLOR_YELLOW;
|
||||
@ -1355,7 +1355,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
|
||||
/* Draw mouse joint */
|
||||
if (sim_ent_has_prop(ent, SEPROP_MOUSE_JOINT)) {
|
||||
struct sim_ent *target = sim_ent_from_id(G.ss_blended, ent->mouse_joint_data.target);
|
||||
Ent *target = sim_ent_from_id(G.ss_blended, ent->mouse_joint_data.target);
|
||||
Xform target_xf = sim_ent_get_xform(target);
|
||||
u32 color = COLOR_WHITE;
|
||||
V2 point_start = xform_mul_v2(target_xf, ent->mouse_joint_data.point_local_start);
|
||||
@ -1405,8 +1405,8 @@ INTERNAL void user_update(P_Window *window)
|
||||
/* Draw contact constraint */
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTACT_CONSTRAINT)) {
|
||||
ContactConstraint *data = &ent->contact_constraint_data;
|
||||
struct sim_ent *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
Ent *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
Ent *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
(UNUSED)e0;
|
||||
(UNUSED)e1;
|
||||
|
||||
@ -1475,8 +1475,8 @@ INTERNAL void user_update(P_Window *window)
|
||||
if (sim_ent_has_prop(ent, SEPROP_COLLISION_DEBUG)) {
|
||||
CollisionDebugData *data = &ent->collision_debug_data;
|
||||
CLD_CollisionResult collider_res = data->res;
|
||||
struct sim_ent *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
Ent *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
Ent *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
CLD_Shape e0_collider = e0->local_collider;
|
||||
CLD_Shape e1_collider = e1->local_collider;
|
||||
(UNUSED)e0_collider;
|
||||
@ -1848,7 +1848,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
|
||||
/* Set user sim control */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.user_sim_cmd_mutex);
|
||||
P_Lock lock = P_LockE(&G.user_sim_cmd_mutex);
|
||||
|
||||
/* Reset flags */
|
||||
if (G.user_sim_cmd_gen != G.last_user_sim_cmd_gen) {
|
||||
@ -1860,7 +1860,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
G.user_sim_cmd_control = control;
|
||||
G.user_sim_cmd_control.flags |= old_flags;
|
||||
G.user_hovered_ent = hovered_ent->id;
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1899,7 +1899,7 @@ INTERNAL void user_update(P_Window *window)
|
||||
* ========================== */
|
||||
|
||||
if (G.debug_draw && hovered_ent->valid) {
|
||||
struct sim_ent *ent = hovered_ent;
|
||||
Ent *ent = hovered_ent;
|
||||
|
||||
V2 pos = v2_add(G.ui_cursor, V2FromXY(15, 15));
|
||||
F_Font *font = font_load_async(LIT("font/fixedsys.ttf"), 12.0f);
|
||||
@ -2037,11 +2037,11 @@ INTERNAL void user_update(P_Window *window)
|
||||
{
|
||||
#if DEVELOPER
|
||||
b32 console_minimized = !G.debug_console;
|
||||
i32 console_level = console_minimized ? LOG_LEVEL_SUCCESS: LOG_LEVEL_DEBUG;
|
||||
i32 console_level = console_minimized ? P_LogLevel_Success: P_LogLevel_Debug;
|
||||
draw_debug_console(console_level, console_minimized);
|
||||
#else
|
||||
if (G.debug_draw) {
|
||||
draw_debug_console(LOG_LEVEL_INFO, 0);
|
||||
draw_debug_console(P_LogLevel_Info, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -2095,7 +2095,7 @@ INTERNAL P_JobDef(user_update_job, _)
|
||||
}
|
||||
{
|
||||
__profn("Frame limiter wait");
|
||||
sys_sleep_frame(time_ns, 1000000000 / FPS_LIMIT);
|
||||
P_SleepFrame(time_ns, 1000000000 / FPS_LIMIT);
|
||||
time_ns = P_TimeNs();
|
||||
}
|
||||
}
|
||||
@ -2121,9 +2121,9 @@ INTERNAL void generate_user_input_cmds(Client *user_input_client, u64 tick)
|
||||
{
|
||||
Snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick);
|
||||
Snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, tick);
|
||||
struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID);
|
||||
Ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID);
|
||||
/* Find / create local control cmd ent */
|
||||
struct sim_ent *control_cmd = sim_ent_find_first_match_one(user_input_ss, SEPROP_CMD);
|
||||
Ent *control_cmd = sim_ent_find_first_match_one(user_input_ss, SEPROP_CMD);
|
||||
if (!control_cmd->valid) {
|
||||
control_cmd = sim_ent_alloc_sync_src(user_input_root);
|
||||
control_cmd->cmd_kind = SIM_CMD_KIND_CONTROL;
|
||||
@ -2132,7 +2132,7 @@ INTERNAL void generate_user_input_cmds(Client *user_input_client, u64 tick)
|
||||
sim_ent_activate(control_cmd, user_input_ss->tick);
|
||||
}
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.user_sim_cmd_mutex);
|
||||
P_Lock lock = P_LockE(&G.user_sim_cmd_mutex);
|
||||
/* Update control cmd */
|
||||
{
|
||||
control_cmd->cmd_control = G.user_sim_cmd_control;
|
||||
@ -2141,13 +2141,13 @@ INTERNAL void generate_user_input_cmds(Client *user_input_client, u64 tick)
|
||||
#if 0
|
||||
/* Create chat cmd */
|
||||
if (G.user_sim_cmd_chat.len > 0) {
|
||||
struct sim_ent *chat_cmd = sim_ent_alloc_sync_src(user_input_root);
|
||||
Ent *chat_cmd = sim_ent_alloc_sync_src(user_input_root);
|
||||
chat_cmd->cmd_kind = SIM_CMD_KIND_CHAT;
|
||||
//chat_cmd->chat_msg = ZI
|
||||
}
|
||||
#endif
|
||||
++G.user_sim_cmd_gen;
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2260,7 +2260,7 @@ INTERNAL P_JobDef(local_sim_job, _)
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
{
|
||||
__profn("Sim sleep");
|
||||
sys_sleep_frame(real_time_ns, step_dt_ns * compute_timescale);
|
||||
P_SleepFrame(real_time_ns, step_dt_ns * compute_timescale);
|
||||
}
|
||||
{
|
||||
__profn("Sim update");
|
||||
@ -2406,7 +2406,7 @@ INTERNAL P_JobDef(local_sim_job, _)
|
||||
|
||||
/* Assume all incoming ents want to be sync srcs */
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
|
||||
struct sim_ent *ent = &ss->ents[i];
|
||||
Ent *ent = &ss->ents[i];
|
||||
if (ent->valid && sim_ent_has_prop(ent, SEPROP_SYNC_DST)) {
|
||||
sim_ent_disable_prop(ent, SEPROP_SYNC_DST);
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_SRC);
|
||||
@ -2590,25 +2590,25 @@ INTERNAL P_JobDef(local_sim_job, _)
|
||||
|
||||
#if 0
|
||||
DEBUGBREAKABLE;
|
||||
logf_debug("*************************************************");
|
||||
logf_debug("local_client->last_tick: %F", FMT_UINT(local_client->last_tick));
|
||||
logf_debug("master_sim_predicted_time_ns: %F", FMT_SINT(master_sim_predicted_time_ns));
|
||||
logf_debug("tick_progress: %F", FMT_FLOAT(tick_progress));
|
||||
logf_debug("sim_publish_timescale: %F", FMT_FLOAT(sim_publish_timescale));
|
||||
logf_debug("last_tick_from_master_received_at_ns: %F", FMT_SINT(last_tick_from_master_received_at_ns));
|
||||
logf_debug("average_master_receive_dt_ns: %F", FMT_SINT(average_master_receive_dt_ns));
|
||||
logf_debug("next_tick_expected_ns: %F", FMT_SINT(next_tick_expected_ns));
|
||||
logf_debug("master_blend_time_target_ns: %F", FMT_SINT(master_blend_time_target_ns));
|
||||
logf_debug("blend_time_target_diff_ns: %F", FMT_SINT(blend_time_target_diff_ns));
|
||||
logf_debug("master_blend_time_ns: %F", FMT_SINT(master_blend_time_ns));
|
||||
logf_debug("left_snapshot->tick: %F", FMT_UINT(left_snapshot->tick));
|
||||
logf_debug("right_snapshot->tick: %F", FMT_UINT(right_snapshot->tick));
|
||||
logf_debug("master_ss->tick: %F", FMT_UINT(master_ss->tick));
|
||||
P_LogDebugF("*************************************************");
|
||||
P_LogDebugF("local_client->last_tick: %F", FMT_UINT(local_client->last_tick));
|
||||
P_LogDebugF("master_sim_predicted_time_ns: %F", FMT_SINT(master_sim_predicted_time_ns));
|
||||
P_LogDebugF("tick_progress: %F", FMT_FLOAT(tick_progress));
|
||||
P_LogDebugF("sim_publish_timescale: %F", FMT_FLOAT(sim_publish_timescale));
|
||||
P_LogDebugF("last_tick_from_master_received_at_ns: %F", FMT_SINT(last_tick_from_master_received_at_ns));
|
||||
P_LogDebugF("average_master_receive_dt_ns: %F", FMT_SINT(average_master_receive_dt_ns));
|
||||
P_LogDebugF("next_tick_expected_ns: %F", FMT_SINT(next_tick_expected_ns));
|
||||
P_LogDebugF("master_blend_time_target_ns: %F", FMT_SINT(master_blend_time_target_ns));
|
||||
P_LogDebugF("blend_time_target_diff_ns: %F", FMT_SINT(blend_time_target_diff_ns));
|
||||
P_LogDebugF("master_blend_time_ns: %F", FMT_SINT(master_blend_time_ns));
|
||||
P_LogDebugF("left_snapshot->tick: %F", FMT_UINT(left_snapshot->tick));
|
||||
P_LogDebugF("right_snapshot->tick: %F", FMT_UINT(right_snapshot->tick));
|
||||
P_LogDebugF("master_ss->tick: %F", FMT_UINT(master_ss->tick));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (master_ss->valid) {
|
||||
struct sim_ent *master_player = sim_ent_find_first_match_one(master_ss, SEPROP_PLAYER_IS_MASTER);
|
||||
Ent *master_player = sim_ent_find_first_match_one(master_ss, SEPROP_PLAYER_IS_MASTER);
|
||||
|
||||
/* Update ent id from master */
|
||||
{
|
||||
@ -2750,7 +2750,7 @@ INTERNAL P_JobDef(local_sim_job, _)
|
||||
Snapshot *local_ss = sim_snapshot_from_tick(local_client, local_client->last_tick);
|
||||
if (local_ss->valid) {
|
||||
/* TODO: Double buffer */
|
||||
P_Lock lock = snc_lock_e(&G.local_to_user_client_mutex);
|
||||
P_Lock lock = P_LockE(&G.local_to_user_client_mutex);
|
||||
sim_snapshot_alloc(G.local_to_user_client, local_ss, local_ss->tick);
|
||||
i64 publish_ns = P_TimeNs();
|
||||
if (last_publish_to_user_ns == 0) {
|
||||
@ -2760,7 +2760,7 @@ INTERNAL P_JobDef(local_sim_job, _)
|
||||
G.local_to_user_client_publish_time_ns = publish_ns;
|
||||
last_publish_to_user_ns = publish_ns;
|
||||
sim_snapshot_release_ticks_in_range(G.local_to_user_client, 0, local_ss->tick - 1);
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -50,17 +50,17 @@ INTERNAL P_ExitFuncDef(watch_shutdown)
|
||||
atomic32_fetch_set(&G.watch_shutdown, 1);
|
||||
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
snc_cv_signal(&G.watch_dispatcher_cv, I32_MAX);
|
||||
P_Lock lock = P_LockE(&G.watch_dispatcher_mutex);
|
||||
P_SignalCv(&G.watch_dispatcher_cv, I32_MAX);
|
||||
P_WakeWatch(G.watch);
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
snc_counter_wait(&G.watch_jobs_counter);
|
||||
P_WaitOnCounter(&G.watch_jobs_counter);
|
||||
}
|
||||
|
||||
void watch_register_callback(watch_callback *callback)
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.watch_callbacks_mutex);
|
||||
P_Lock lock = P_LockE(&G.watch_callbacks_mutex);
|
||||
{
|
||||
if (G.num_watch_callbacks < countof(G.watch_callbacks)) {
|
||||
G.watch_callbacks[G.num_watch_callbacks++] = callback;
|
||||
@ -68,7 +68,7 @@ void watch_register_callback(watch_callback *callback)
|
||||
P_Panic(LIT("Max resource watch callbacks reached"));
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
INTERNAL P_JobDef(watch_monitor_job, _)
|
||||
@ -85,7 +85,7 @@ INTERNAL P_JobDef(watch_monitor_job, _)
|
||||
TempArena temp = arena_temp_begin(scratch.arena);
|
||||
P_WatchInfoList info_list = P_ReadWatchWait(temp.arena, G.watch);
|
||||
if (info_list.first && !atomic32_fetch(&G.watch_shutdown)) {
|
||||
P_Lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
P_Lock lock = P_LockE(&G.watch_dispatcher_mutex);
|
||||
{
|
||||
for (P_WatchInfo *info = info_list.first; info; info = info->next) {
|
||||
String name_src = info->name;
|
||||
@ -108,8 +108,8 @@ INTERNAL P_JobDef(watch_monitor_job, _)
|
||||
}
|
||||
}
|
||||
}
|
||||
snc_cv_signal(&G.watch_dispatcher_cv, I32_MAX);
|
||||
snc_unlock(&lock);
|
||||
P_SignalCv(&G.watch_dispatcher_cv, I32_MAX);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
arena_temp_end(temp);
|
||||
}
|
||||
@ -157,7 +157,7 @@ INTERNAL P_JobDef(watch_dispatcher_job, _)
|
||||
|
||||
/* Pull watch events from queue */
|
||||
{
|
||||
P_Lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
P_Lock lock = P_LockE(&G.watch_dispatcher_mutex);
|
||||
for (struct watch_event *src_event = G.first_watch_event; src_event; src_event = src_event->next) {
|
||||
struct watch_event *e = arena_push(scratch.arena, struct watch_event);
|
||||
e->name = string_copy(scratch.arena, src_event->name);
|
||||
@ -171,13 +171,13 @@ INTERNAL P_JobDef(watch_dispatcher_job, _)
|
||||
G.first_watch_event = 0;
|
||||
G.last_watch_event = 0;
|
||||
arena_reset(G.watch_events_arena);
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
|
||||
/* Build callbacks array */
|
||||
u64 num_callbacks = 0;
|
||||
watch_callback **callbacks = 0;
|
||||
P_Lock callbacks_lock = snc_lock_s(&G.watch_callbacks_mutex);
|
||||
P_Lock callbacks_lock = P_LockS(&G.watch_callbacks_mutex);
|
||||
{
|
||||
num_callbacks = G.num_watch_callbacks;
|
||||
callbacks = arena_push_array_no_zero(scratch.arena, watch_callback *, num_callbacks);
|
||||
@ -185,7 +185,7 @@ INTERNAL P_JobDef(watch_dispatcher_job, _)
|
||||
callbacks[i] = G.watch_callbacks[i];
|
||||
}
|
||||
}
|
||||
snc_unlock(&callbacks_lock);
|
||||
P_Unlock(&callbacks_lock);
|
||||
|
||||
/* Run callbacks */
|
||||
{
|
||||
@ -206,7 +206,7 @@ INTERNAL P_JobDef(watch_dispatcher_job, _)
|
||||
sig.callbacks = callbacks;
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_callbacks, watch_callback_job, &sig, P_Pool_Background, P_Priority_Low, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
P_WaitOnCounter(&counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,15 +215,15 @@ INTERNAL P_JobDef(watch_dispatcher_job, _)
|
||||
}
|
||||
|
||||
/* Wait for event */
|
||||
P_Lock lock = snc_lock_s(&G.watch_dispatcher_mutex);
|
||||
P_Lock lock = P_LockS(&G.watch_dispatcher_mutex);
|
||||
{
|
||||
shutdown = atomic32_fetch(&G.watch_shutdown);
|
||||
while (!shutdown && !G.first_watch_event) {
|
||||
snc_cv_wait(&G.watch_dispatcher_cv, &lock);
|
||||
P_WaitOnCv(&G.watch_dispatcher_cv, &lock);
|
||||
shutdown = atomic32_fetch(&G.watch_shutdown);
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
P_Unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user