refactor progress
This commit is contained in:
parent
8f96d89f35
commit
1a33021a52
2
build.c
2
build.c
@ -852,7 +852,7 @@ void OnBuild(StringList cli_args)
|
||||
D_GetDirContents(&perm, &src_files, src_dir, 0);
|
||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/base/base.c"), D_TagKind_File));
|
||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/prof/prof.cpp"), D_TagKind_File));
|
||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/sys/sys.c"), D_TagKind_File));
|
||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/platform/platform.c"), D_TagKind_File));
|
||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/gp/gp.c"), D_TagKind_File));
|
||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/resource/resource.c"), D_TagKind_File));
|
||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/watch/watch.c"), D_TagKind_File));
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define APP_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../ttf/ttf.h"
|
||||
#include "../gp/gp.h"
|
||||
#include "../sim/sim.h"
|
||||
|
||||
@ -12,7 +12,7 @@ INTERNAL String initialize_write_directory(Arena *arena, String write_dir)
|
||||
TempArena scratch = scratch_begin(arena);
|
||||
|
||||
/* Create write path */
|
||||
String base_write_dir = sys_get_write_path(scratch.arena);
|
||||
String base_write_dir = P_GetWritePath(scratch.arena);
|
||||
String write_path_fmt = base_write_dir.len > 0 ? LIT("%F/%F/") : LIT("%F%F/");
|
||||
String write_path = string_format(
|
||||
arena,
|
||||
@ -22,8 +22,8 @@ INTERNAL String initialize_write_directory(Arena *arena, String write_dir)
|
||||
);
|
||||
|
||||
/* Create write dir if not present */
|
||||
if (!sys_is_dir(write_path)) {
|
||||
sys_mkdir(write_path);
|
||||
if (!P_IsDir(write_path)) {
|
||||
P_MkDir(write_path);
|
||||
/* TODO: handle failure */
|
||||
}
|
||||
|
||||
@ -41,18 +41,18 @@ String app_write_path_cat(Arena *arena, String filename)
|
||||
* Default settings
|
||||
* ========================== */
|
||||
|
||||
INTERNAL struct sys_window_settings default_window_settings(struct sys_window *window)
|
||||
INTERNAL P_WindowSettings default_window_settings(P_Window *window)
|
||||
{
|
||||
__prof;
|
||||
|
||||
V2 monitor_size = sys_window_get_monitor_size(window);
|
||||
V2 monitor_size = P_GetWindowMonitorSize(window);
|
||||
|
||||
i32 width = 1280;
|
||||
i32 height = math_round_to_int(width / (f32)(DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT));
|
||||
i32 x = math_round_to_int(monitor_size.x / 2.f - width / 2);
|
||||
i32 y = math_round_to_int(monitor_size.y / 2.f - height / 2);
|
||||
|
||||
return (struct sys_window_settings) {
|
||||
return (P_WindowSettings) {
|
||||
.title = WINDOW_TITLE,
|
||||
.floating_x = x,
|
||||
.floating_y = y,
|
||||
@ -146,7 +146,7 @@ INTERNAL struct app_arg_list parse_args(Arena *arena, String args_str)
|
||||
* Entry point
|
||||
* ========================== */
|
||||
|
||||
void sys_app_startup(String args_str)
|
||||
void P_AppStartup(String args_str)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -198,7 +198,7 @@ void sys_app_startup(String args_str)
|
||||
|
||||
String logfile_dir = string_cat(temp.arena, G.write_path, LIT("logs/"));
|
||||
String logfile_path = string_cat(temp.arena, logfile_dir, logfile_name);
|
||||
sys_mkdir(logfile_dir);
|
||||
P_MkDir(logfile_dir);
|
||||
|
||||
log_startup(logfile_path);
|
||||
logf_info("Start of logs");
|
||||
@ -214,17 +214,17 @@ void sys_app_startup(String args_str)
|
||||
{
|
||||
TempArena temp = arena_temp_begin(scratch.arena);
|
||||
|
||||
struct sys_window_settings window_settings = ZI;
|
||||
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));
|
||||
if (sys_is_file(settings_path)) {
|
||||
if (P_IsFile(settings_path)) {
|
||||
logf_info("Settings file found");
|
||||
struct sys_file settings_file = sys_file_open_read(settings_path);
|
||||
String file_data = sys_file_read_all(temp.arena, settings_file);
|
||||
sys_file_close(settings_file);
|
||||
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));
|
||||
String error = ZI;
|
||||
struct sys_window_settings *res = settings_deserialize(temp.arena, file_data, &error);
|
||||
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));
|
||||
String msg = string_format(temp.arena,
|
||||
@ -237,7 +237,7 @@ void sys_app_startup(String args_str)
|
||||
),
|
||||
FMT_STR(settings_path),
|
||||
FMT_STR(error));
|
||||
sys_panic(msg);
|
||||
P_Panic(msg);
|
||||
}
|
||||
logf_info("Settings file loaded successfully");
|
||||
window_settings = *res;
|
||||
@ -246,7 +246,7 @@ void sys_app_startup(String args_str)
|
||||
window_settings = default_window_settings(window);
|
||||
}
|
||||
string_copy_to_string(STRING_FROM_ARRAY(window_settings.title), LIT(WINDOW_TITLE));
|
||||
sys_window_update_settings(window, &window_settings);
|
||||
P_UpdateWindowSettings(window, &window_settings);
|
||||
|
||||
arena_temp_end(temp);
|
||||
}
|
||||
@ -262,11 +262,11 @@ void sys_app_startup(String args_str)
|
||||
AC_StartupReceipt asset_cache_sr = asset_cache_startup();
|
||||
TTF_StartupReceipt ttf_sr = ttf_startup();
|
||||
F_StartupReceipt font_sr = font_startup(&asset_cache_sr, &ttf_sr);
|
||||
struct sprite_startup_receipt sprite_sr = sprite_startup();
|
||||
S_StartupReceipt sprite_sr = sprite_startup();
|
||||
M_StartupReceipt mixer_sr = mixer_startup();
|
||||
struct sound_startup_receipt sound_sr = sound_startup(&asset_cache_sr);
|
||||
SND_StartupReceipt sound_sr = sound_startup(&asset_cache_sr);
|
||||
D_StartupReceipt draw_sr = draw_startup(&font_sr);
|
||||
struct sim_startup_receipt sim_sr = sim_startup();
|
||||
SimStartupReceipt sim_sr = sim_startup();
|
||||
|
||||
/* Interface systems */
|
||||
PB_StartupReceipt playback_sr = playback_startup(&mixer_sr);
|
||||
@ -283,14 +283,14 @@ void sys_app_startup(String args_str)
|
||||
|
||||
String window_settings_path = app_write_path_cat(temp.arena, settings_file_name);
|
||||
|
||||
struct sys_window_settings settings = sys_window_get_settings(window);
|
||||
P_WindowSettings settings = P_GetWindowSettings(window);
|
||||
String str = settings_serialize(temp.arena, &settings);
|
||||
logf_info("Serialized window settings: %F", FMT_STR(str));
|
||||
|
||||
logf_info("Writing settings file to path \"%F\"", FMT_STR(window_settings_path));
|
||||
struct sys_file settings_file = sys_file_open_write(window_settings_path);
|
||||
sys_file_write(settings_file, str);
|
||||
sys_file_close(settings_file);
|
||||
P_File settings_file = P_OpenFileWrite(window_settings_path);
|
||||
P_WriteFile(settings_file, str);
|
||||
P_CloseFIle(settings_file);
|
||||
logf_info("Finished writing settings file");
|
||||
|
||||
arena_temp_end(temp);
|
||||
@ -298,7 +298,7 @@ void sys_app_startup(String args_str)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
sys_window_release(window);
|
||||
P_ReleaseWindow(window);
|
||||
#endif
|
||||
|
||||
//logf_info("Program exited normally");
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define ASSET_CACHE_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
|
||||
#include "asset_cache_core.h"
|
||||
|
||||
|
||||
@ -6,18 +6,18 @@
|
||||
#define ASSET_LOOKUP_TABLE_CAPACITY (MAX_ASSETS * 4)
|
||||
|
||||
GLOBAL struct {
|
||||
struct snc_mutex lookup_mutex;
|
||||
P_Mutex lookup_mutex;
|
||||
AC_Asset lookup[ASSET_LOOKUP_TABLE_CAPACITY];
|
||||
u64 num_assets;
|
||||
|
||||
struct snc_mutex store_mutex;
|
||||
P_Mutex store_mutex;
|
||||
Arena *store_arena;
|
||||
|
||||
#if RTC
|
||||
/* Array of len `num_assets` pointing into populated entries of `lookup`. */
|
||||
AC_Asset *dbg_table[ASSET_LOOKUP_TABLE_CAPACITY];
|
||||
u64 dbg_table_count;
|
||||
struct snc_mutex dbg_table_mutex;
|
||||
P_Mutex dbg_table_mutex;
|
||||
#endif
|
||||
} G = ZI, DEBUG_ALIAS(G, G_asset_cache);
|
||||
|
||||
@ -40,7 +40,7 @@ AC_StartupReceipt asset_cache_startup(void)
|
||||
INTERNAL void refresh_dbg_table(void)
|
||||
{
|
||||
#if RTC
|
||||
struct snc_lock lock = snc_lock_e(&G.dbg_table_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.dbg_table_mutex);
|
||||
MEMZERO_ARRAY(G.dbg_table);
|
||||
G.dbg_table_count = 0;
|
||||
for (u64 i = 0; i < countof(G.lookup); ++i) {
|
||||
@ -55,7 +55,7 @@ INTERNAL void refresh_dbg_table(void)
|
||||
|
||||
/* Returns first matching slot or first empty slot if not found.
|
||||
* Check returned slot->hash != 0 for presence. */
|
||||
INTERNAL AC_Asset *asset_cache_get_slot_locked(struct snc_lock *lock, String key, u64 hash)
|
||||
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);
|
||||
(UNUSED)lock;
|
||||
@ -101,7 +101,7 @@ AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch)
|
||||
|
||||
/* Lookup */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_s(&G.lookup_mutex);
|
||||
P_Lock lock = snc_lock_s(&G.lookup_mutex);
|
||||
asset = asset_cache_get_slot_locked(&lock, key, hash);
|
||||
snc_unlock(&lock);
|
||||
}
|
||||
@ -112,14 +112,14 @@ AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch)
|
||||
*is_first_touch = 0;
|
||||
}
|
||||
} else {
|
||||
struct snc_lock lock = snc_lock_e(&G.lookup_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.lookup_mutex);
|
||||
|
||||
/* Re-check asset presence in case it was inserted since lock */
|
||||
asset = asset_cache_get_slot_locked(&lock, key, hash);
|
||||
|
||||
if (!asset->hash) {
|
||||
if (G.num_assets >= MAX_ASSETS) {
|
||||
sys_panic(LIT("Max assets reached"));
|
||||
P_Panic(LIT("Max assets reached"));
|
||||
}
|
||||
String key_stored = ZI;
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.store_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.store_mutex);
|
||||
AC_Store store = {
|
||||
.lock = lock,
|
||||
.arena = G.store_arena
|
||||
|
||||
@ -13,7 +13,7 @@ struct AC_Asset {
|
||||
u64 hash;
|
||||
String key;
|
||||
|
||||
struct snc_counter counter;
|
||||
P_Counter counter;
|
||||
|
||||
/* Managed via asset_cache_mark_x functions */
|
||||
AC_Status status;
|
||||
@ -27,7 +27,7 @@ struct AC_Store {
|
||||
Arena *arena;
|
||||
|
||||
/* Internal */
|
||||
struct snc_lock lock;
|
||||
P_Lock lock;
|
||||
};
|
||||
|
||||
typedef struct AC_StartupReceipt AC_StartupReceipt;
|
||||
|
||||
@ -16,7 +16,7 @@ Arena *arena_alloc(u64 reserve)
|
||||
if (!base) {
|
||||
/* Hard fail on memory reserve failure for now */
|
||||
/* FIXME: Enable this */
|
||||
//sys_panic(LIT("Failed to reserve memory"));
|
||||
//P_Panic(LIT("Failed to reserve memory"));
|
||||
(*(volatile int *)0) = 0;
|
||||
}
|
||||
u64 reserved = reserve;
|
||||
@ -27,7 +27,7 @@ Arena *arena_alloc(u64 reserve)
|
||||
if (!base) {
|
||||
/* Hard fail on commit failure */
|
||||
/* FIXME: Enable this */
|
||||
//sys_panic(LIT("Failed to commit initial memory block: System may be out of memory"));
|
||||
//P_Panic(LIT("Failed to commit initial memory block: System may be out of memory"));
|
||||
(*(volatile int *)0) = 0;
|
||||
}
|
||||
|
||||
@ -83,14 +83,14 @@ void *arena_push_bytes_no_zero(Arena *arena, u64 size, u64 align)
|
||||
if (new_capacity > arena->reserved) {
|
||||
/* Hard fail if we overflow reserved memory for now */
|
||||
/* FIXME: Enable this */
|
||||
//sys_panic(LIT("Failed to commit new memory block: Overflow of reserved memory"));
|
||||
//P_Panic(LIT("Failed to commit new memory block: Overflow of reserved memory"));
|
||||
(*(volatile int *)0) = 0;
|
||||
}
|
||||
void *commit_address = base + arena->committed;
|
||||
if (!memory_commit(commit_address, commit_bytes)) {
|
||||
/* Hard fail on memory allocation failure for now */
|
||||
/* FIXME: Enable this */
|
||||
//sys_panic(LIT("Failed to commit new memory block: System may be out of memory"));
|
||||
//P_Panic(LIT("Failed to commit new memory block: System may be out of memory"));
|
||||
(*(volatile int *)0) = 0;
|
||||
}
|
||||
arena->committed += commit_bytes;
|
||||
|
||||
@ -54,7 +54,7 @@ String _incbin_get(_IncbinRcResource *inc)
|
||||
EnumResourceNamesW(0, RT_RCDATA, &enum_func, (LONG_PTR)¶ms);
|
||||
if (!params.found) {
|
||||
/* FIXME: enable this */
|
||||
//sys_panic(string_format(scratch.arena,
|
||||
//P_Panic(string_format(scratch.arena,
|
||||
// LIT("INCBIN include not found in RC file: \"%F\""),
|
||||
// FMT_STR(inc->rc_name)));
|
||||
(*(volatile int *)0) = 0;
|
||||
|
||||
@ -15,7 +15,7 @@ struct font_task_params {
|
||||
struct font_task_params_store {
|
||||
struct font_task_params *head_free;
|
||||
Arena *arena;
|
||||
struct snc_mutex mutex;
|
||||
P_Mutex mutex;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
@ -48,7 +48,7 @@ INTERNAL struct font_task_params *font_task_params_alloc(void)
|
||||
{
|
||||
struct font_task_params *p = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
if (G.params.head_free) {
|
||||
p = G.params.head_free;
|
||||
G.params.head_free = p->next_free;
|
||||
@ -62,7 +62,7 @@ INTERNAL struct font_task_params *font_task_params_alloc(void)
|
||||
|
||||
INTERNAL void font_task_params_release(struct font_task_params *p)
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
p->next_free = G.params.head_free;
|
||||
G.params.head_free = p;
|
||||
snc_unlock(&lock);
|
||||
@ -72,7 +72,7 @@ INTERNAL void font_task_params_release(struct font_task_params *p)
|
||||
* Load
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
||||
INTERNAL P_JobDef(font_load_asset_job, job)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -83,7 +83,7 @@ INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
||||
AC_Asset *asset = params->asset;
|
||||
|
||||
logf_info("Loading font \"%F\" (point size %F)", FMT_STR(path), FMT_FLOAT((f64)point_size));
|
||||
i64 start_ns = sys_time_ns();
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
ASSERT(string_ends_with(path, LIT(".ttf")));
|
||||
ASSERT(countof(g_font_codes) < LOOKUP_TABLE_SIZE);
|
||||
@ -92,7 +92,7 @@ INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
||||
R_Resource res = resource_open(path);
|
||||
if (!resource_exists(&res)) {
|
||||
/* FIME: Load baked font instead of panicking */
|
||||
sys_panic(string_format(scratch.arena,
|
||||
P_Panic(string_format(scratch.arena,
|
||||
LIT("Font \"%F\" not found"),
|
||||
FMT_STR(path)));
|
||||
}
|
||||
@ -121,7 +121,7 @@ INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
||||
|
||||
/* FIXME: Load baked font instead of panicking */
|
||||
if (font->glyphs_count <= 0) {
|
||||
sys_panic(string_format(scratch.arena,
|
||||
P_Panic(string_format(scratch.arena,
|
||||
LIT("Parsed 0 glyphs from font \"%F\"!"),
|
||||
FMT_STR(path)));
|
||||
}
|
||||
@ -138,7 +138,7 @@ INTERNAL SYS_JOB_DEF(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(sys_time_ns() - start_ns)));
|
||||
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)));
|
||||
asset_cache_mark_ready(asset, font);
|
||||
|
||||
scratch_end(scratch);
|
||||
@ -163,7 +163,7 @@ AC_Asset *font_load_asset(String path, f32 point_size, b32 wait)
|
||||
/* Assemble task params */
|
||||
struct font_task_params *params = font_task_params_alloc();
|
||||
if (path.len > (sizeof(params->path_cstr) - 1)) {
|
||||
sys_panic(string_format(scratch.arena,
|
||||
P_Panic(string_format(scratch.arena,
|
||||
LIT("Font path \"%F\" too long!"),
|
||||
FMT_STR(path)));
|
||||
}
|
||||
@ -174,7 +174,7 @@ AC_Asset *font_load_asset(String path, f32 point_size, b32 wait)
|
||||
|
||||
/* Push task */
|
||||
asset_cache_mark_loading(asset);
|
||||
sys_run(1, font_load_asset_job, params, SYS_POOL_BACKGROUND, SYS_PRIORITY_LOW, 0);
|
||||
P_Run(1, font_load_asset_job, params, P_Pool_Background, P_Priority_Low, 0);
|
||||
if (wait) {
|
||||
asset_cache_wait(asset);
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define GP_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../tar/tar.h"
|
||||
#include "../ase/ase.h"
|
||||
#include "../dxc/dxc.h"
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
struct sys_window;
|
||||
struct snc_counter;
|
||||
|
||||
typedef struct G_Indices G_Indices;
|
||||
struct G_Indices {
|
||||
u32 count;
|
||||
@ -138,7 +135,7 @@ G_MemoryInfo gp_query_memory_info(void);
|
||||
|
||||
typedef struct G_Swapchain G_Swapchain;
|
||||
|
||||
G_Swapchain *gp_swapchain_alloc(struct sys_window *window, V2i32 resolution);
|
||||
G_Swapchain *gp_swapchain_alloc(P_Window *window, V2i32 resolution);
|
||||
|
||||
void gp_swapchain_release(G_Swapchain *gp_swapchain);
|
||||
|
||||
|
||||
@ -124,7 +124,7 @@ struct command_queue {
|
||||
ID3D12CommandQueue *cq;
|
||||
Arena *arena;
|
||||
|
||||
struct snc_mutex submit_fence_mutex;
|
||||
P_Mutex submit_fence_mutex;
|
||||
u64 submit_fence_target;
|
||||
ID3D12Fence *submit_fence;
|
||||
|
||||
@ -138,7 +138,7 @@ struct command_queue {
|
||||
struct command_list_pool {
|
||||
struct command_queue *cq;
|
||||
Arena *arena;
|
||||
struct snc_mutex mutex;
|
||||
P_Mutex mutex;
|
||||
struct command_list *first_submitted_command_list;
|
||||
struct command_list *last_submitted_command_list;
|
||||
};
|
||||
@ -148,7 +148,7 @@ struct command_list {
|
||||
struct command_list_pool *pool;
|
||||
struct ID3D12CommandAllocator *ca;
|
||||
struct ID3D12GraphicsCommandList *cl;
|
||||
struct snc_lock global_record_lock;
|
||||
P_Lock global_record_lock;
|
||||
|
||||
struct pipeline *cur_pipeline;
|
||||
|
||||
@ -238,7 +238,7 @@ struct swapchain {
|
||||
struct cpu_descriptor_heap {
|
||||
enum D3D12_DESCRIPTOR_HEAP_TYPE type;
|
||||
Arena *arena;
|
||||
struct snc_mutex mutex;
|
||||
P_Mutex mutex;
|
||||
|
||||
u32 descriptor_size;
|
||||
u32 num_descriptors_reserved;
|
||||
@ -265,7 +265,7 @@ struct fenced_release_data {
|
||||
* Internal procs
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(gp_shutdown);
|
||||
INTERNAL P_ExitFuncDef(gp_shutdown);
|
||||
|
||||
INTERNAL void dx12_init_device(void);
|
||||
|
||||
@ -279,7 +279,7 @@ INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRI
|
||||
|
||||
INTERNAL void command_queue_release(struct command_queue *cq);
|
||||
|
||||
INTERNAL SYS_JOB_DEF(dx12_evictor_job, _);
|
||||
INTERNAL P_JobDef(dx12_evictor_job, _);
|
||||
|
||||
INTERNAL void fenced_release(void *data, enum fenced_release_kind kind);
|
||||
|
||||
@ -288,13 +288,13 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr
|
||||
INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh);
|
||||
|
||||
struct command_queue_alloc_job_sig { struct command_queue_desc *descs_in; struct command_queue **cqs_out; };
|
||||
INTERNAL SYS_JOB_DEF(command_queue_alloc_job, job);
|
||||
INTERNAL P_JobDef(command_queue_alloc_job, job);
|
||||
|
||||
struct pipeline_alloc_job_sig { struct pipeline_desc *descs_in; struct pipeline **pipelines_out; };
|
||||
INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job);
|
||||
INTERNAL P_JobDef(pipeline_alloc_job, job);
|
||||
|
||||
struct dx12_upload_job_sig { struct dx12_resource *resource; void *data; };
|
||||
INTERNAL SYS_JOB_DEF(dx12_upload_job, job);
|
||||
INTERNAL P_JobDef(dx12_upload_job, job);
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name);
|
||||
@ -308,23 +308,23 @@ GLOBAL struct {
|
||||
Atomic32 initialized;
|
||||
|
||||
/* Descriptor heaps pool */
|
||||
struct snc_mutex command_descriptor_heaps_mutex;
|
||||
P_Mutex command_descriptor_heaps_mutex;
|
||||
Arena *command_descriptor_heaps_arena;
|
||||
struct command_descriptor_heap *first_submitted_command_descriptor_heap;
|
||||
struct command_descriptor_heap *last_submitted_command_descriptor_heap;
|
||||
|
||||
/* Command buffers pool */
|
||||
struct snc_mutex command_buffers_mutex;
|
||||
P_Mutex command_buffers_mutex;
|
||||
Arena *command_buffers_arena;
|
||||
Dict *command_buffers_dict;
|
||||
|
||||
/* Resources pool */
|
||||
struct snc_mutex resources_mutex;
|
||||
P_Mutex resources_mutex;
|
||||
Arena *resources_arena;
|
||||
struct dx12_resource *first_free_resource;
|
||||
|
||||
/* Swapchains pool */
|
||||
struct snc_mutex swapchains_mutex;
|
||||
P_Mutex swapchains_mutex;
|
||||
Arena *swapchains_arena;
|
||||
struct swapchain *first_free_swapchain;
|
||||
|
||||
@ -332,7 +332,7 @@ GLOBAL struct {
|
||||
struct tar_archive dxc_archive;
|
||||
|
||||
/* Pipeline cache */
|
||||
struct snc_mutex pipelines_mutex;
|
||||
P_Mutex pipelines_mutex;
|
||||
Arena *pipelines_arena;
|
||||
struct pipeline *first_free_pipeline;
|
||||
Dict *pipeline_descs;
|
||||
@ -341,7 +341,7 @@ GLOBAL struct {
|
||||
struct pipeline_scope *first_free_pipeline_scope;
|
||||
|
||||
/* Fenced release queue */
|
||||
struct snc_mutex fenced_releases_mutex;
|
||||
P_Mutex fenced_releases_mutex;
|
||||
Arena *fenced_releases_arena;
|
||||
u64 fenced_release_targets[DX12_NUM_QUEUES];
|
||||
|
||||
@ -363,14 +363,14 @@ GLOBAL struct {
|
||||
struct cpu_descriptor_heap *rtv_heap;
|
||||
|
||||
/* Command queues */
|
||||
struct snc_mutex global_command_list_record_mutex;
|
||||
struct snc_mutex global_submit_mutex;
|
||||
P_Mutex global_command_list_record_mutex;
|
||||
P_Mutex global_submit_mutex;
|
||||
struct command_queue *command_queues[DX12_NUM_QUEUES];
|
||||
|
||||
/* Evictor job */
|
||||
struct snc_counter evictor_job_counter;
|
||||
struct snc_cv evictor_wake_cv;
|
||||
struct snc_mutex evictor_wake_mutex;
|
||||
P_Counter evictor_job_counter;
|
||||
P_Cv evictor_wake_cv;
|
||||
P_Mutex evictor_wake_mutex;
|
||||
i64 evictor_wake_gen;
|
||||
b32 evictor_shutdown;
|
||||
} G = ZI, DEBUG_ALIAS(G, G_gp_dx12);
|
||||
@ -383,7 +383,7 @@ void gp_startup(void)
|
||||
{
|
||||
__prof;
|
||||
if (atomic32_fetch_test_set(&G.initialized, 0, 1) != 0) {
|
||||
sys_panic(LIT("GP layer already initialized"));
|
||||
P_Panic(LIT("GP layer already initialized"));
|
||||
}
|
||||
|
||||
/* Initialize command descriptor heaps pool */
|
||||
@ -411,7 +411,7 @@ void gp_startup(void)
|
||||
/* Initialize embedded shader archive */
|
||||
String embedded_data = inc_dxc_tar();
|
||||
if (embedded_data.len <= 0) {
|
||||
sys_panic(LIT("No embedded shaders found"));
|
||||
P_Panic(LIT("No embedded shaders found"));
|
||||
}
|
||||
G.dxc_archive = tar_parse(G.pipelines_arena, embedded_data, LIT(""));
|
||||
|
||||
@ -426,13 +426,13 @@ void gp_startup(void)
|
||||
#if RESOURCE_RELOADING
|
||||
watch_register_callback(pipeline_watch_callback);
|
||||
#endif
|
||||
sys_on_exit(gp_shutdown);
|
||||
P_OnExit(gp_shutdown);
|
||||
|
||||
/* Start evictor job */
|
||||
sys_run(1, dx12_evictor_job, 0, SYS_POOL_BACKGROUND, SYS_PRIORITY_LOW, &G.evictor_job_counter);
|
||||
P_Run(1, dx12_evictor_job, 0, P_Pool_Background, P_Priority_Low, &G.evictor_job_counter);
|
||||
}
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(gp_shutdown)
|
||||
INTERNAL P_ExitFuncDef(gp_shutdown)
|
||||
{
|
||||
__prof;
|
||||
#if 0
|
||||
@ -448,7 +448,7 @@ INTERNAL SYS_EXIT_FUNC(gp_shutdown)
|
||||
#endif
|
||||
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
G.evictor_shutdown = 1;
|
||||
snc_cv_signal(&G.evictor_wake_cv, I32_MAX);
|
||||
snc_unlock(&lock);
|
||||
@ -464,7 +464,7 @@ INTERNAL void dx12_init_error(String error)
|
||||
{
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
String msg = string_format(scratch.arena, LIT("Failed to initialize DirectX 12.\n\n%F"), FMT_STR(error));
|
||||
sys_panic(msg);
|
||||
P_Panic(msg);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@ -658,8 +658,8 @@ INTERNAL void dx12_init_objects(void)
|
||||
sig.descs_in = params;
|
||||
sig.cqs_out = G.command_queues;
|
||||
{
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(DX12_NUM_QUEUES, command_queue_alloc_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
|
||||
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);
|
||||
}
|
||||
#if PROFILING
|
||||
@ -752,8 +752,8 @@ INTERNAL void dx12_init_pipelines(void)
|
||||
struct pipeline_alloc_job_sig sig = ZI;
|
||||
sig.descs_in = descs;
|
||||
sig.pipelines_out = pipelines;
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(num_pipelines, pipeline_alloc_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_pipelines, pipeline_alloc_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
for (u32 i = 0; i < num_pipelines; ++i) {
|
||||
@ -768,7 +768,7 @@ INTERNAL void dx12_init_pipelines(void)
|
||||
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);
|
||||
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
|
||||
P_MessageBox(P_MessageBoxKind_Warning, msg);
|
||||
}
|
||||
}
|
||||
pipeline_register(num_pipelines, pipelines);
|
||||
@ -793,7 +793,7 @@ INTERNAL void dx12_init_noise(void)
|
||||
if (resource_exists(&noise_res)) {
|
||||
String data = resource_get_data(&noise_res);
|
||||
if (data.len != expected_size) {
|
||||
sys_panic(string_format(scratch.arena,
|
||||
P_Panic(string_format(scratch.arena,
|
||||
LIT("Noise texture has unexpected size for a %Fx%Fx%F texture (expected %F, got %F)"),
|
||||
FMT_UINT(K_BLUE_NOISE_TEX_WIDTH), FMT_UINT(K_BLUE_NOISE_TEX_HEIGHT), FMT_UINT(K_BLUE_NOISE_TEX_DEPTH),
|
||||
FMT_UINT(expected_size), FMT_UINT(data.len)));
|
||||
@ -824,16 +824,16 @@ INTERNAL void dx12_init_noise(void)
|
||||
|
||||
/* Upload texture */
|
||||
{
|
||||
struct snc_counter counter = ZI;
|
||||
P_Counter counter = ZI;
|
||||
struct dx12_upload_job_sig sig = ZI;
|
||||
sig.resource = r;
|
||||
sig.data = data.text;
|
||||
sys_run(1, dx12_upload_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
|
||||
P_Run(1, dx12_upload_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sys_panic(string_format(scratch.arena, LIT("Noise resource \"%F\" not found"), FMT_STR(noise_res_name)));
|
||||
P_Panic(string_format(scratch.arena, LIT("Noise resource \"%F\" not found"), FMT_STR(noise_res_name)));
|
||||
}
|
||||
resource_close(&noise_res);
|
||||
}
|
||||
@ -867,7 +867,7 @@ struct shader_compile_job_sig {
|
||||
struct shader_compile_result *results;
|
||||
};
|
||||
|
||||
INTERNAL SYS_JOB_DEF(shader_compile_job, job)
|
||||
INTERNAL P_JobDef(shader_compile_job, job)
|
||||
{
|
||||
__prof;
|
||||
struct shader_compile_job_sig *sig = job.sig;
|
||||
@ -877,7 +877,7 @@ INTERNAL SYS_JOB_DEF(shader_compile_job, job)
|
||||
|
||||
TempArena scratch = scratch_begin(arena);
|
||||
{
|
||||
i64 start_ns = sys_time_ns();
|
||||
i64 start_ns = P_TimeNs();
|
||||
DXC_Result dxc_result = ZI;
|
||||
{
|
||||
__profn("Compile shader");
|
||||
@ -904,7 +904,7 @@ INTERNAL SYS_JOB_DEF(shader_compile_job, job)
|
||||
result->success = dxc_result.success;
|
||||
result->dxc = dxc_result.dxc;
|
||||
result->errors = dxc_result.errors;
|
||||
result->elapsed_ns = sys_time_ns() - start_ns;
|
||||
result->elapsed_ns = P_TimeNs() - start_ns;
|
||||
|
||||
}
|
||||
scratch_end(scratch);
|
||||
@ -916,7 +916,7 @@ INTERNAL SYS_JOB_DEF(shader_compile_job, job)
|
||||
* Pipeline
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job)
|
||||
INTERNAL P_JobDef(pipeline_alloc_job, job)
|
||||
{
|
||||
__prof;
|
||||
struct pipeline_alloc_job_sig *sig = job.sig;
|
||||
@ -925,7 +925,7 @@ INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job)
|
||||
|
||||
struct pipeline *pipeline = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
if (G.first_free_pipeline) {
|
||||
pipeline = G.first_free_pipeline;
|
||||
G.first_free_pipeline = pipeline->next;
|
||||
@ -942,7 +942,7 @@ INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job)
|
||||
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
{
|
||||
i64 start_ns = sys_time_ns();
|
||||
i64 start_ns = P_TimeNs();
|
||||
String pipeline_name = pipeline->name;
|
||||
logf_info("Loading pipeline \"%F\"", FMT_STR(pipeline_name));
|
||||
b32 success = 1;
|
||||
@ -1165,7 +1165,7 @@ INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job)
|
||||
|
||||
pipeline->pso = pso;
|
||||
pipeline->rootsig = rootsig;
|
||||
pipeline->compilation_time_ns = sys_time_ns() - start_ns;
|
||||
pipeline->compilation_time_ns = P_TimeNs() - start_ns;
|
||||
pipeline->success = success;
|
||||
pipeline->is_gfx = cs_dxc.len == 0;
|
||||
pipeline->error = error_str;
|
||||
@ -1192,7 +1192,7 @@ INTERNAL void pipeline_release_now(struct pipeline *pipeline)
|
||||
if (pipeline->pso) {
|
||||
ID3D12PipelineState_Release(pipeline->pso);
|
||||
}
|
||||
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
{
|
||||
pipeline->next = G.first_free_pipeline;
|
||||
G.first_free_pipeline = pipeline;
|
||||
@ -1209,7 +1209,7 @@ INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
|
||||
__prof;
|
||||
struct pipeline_scope *scope = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
if (G.first_free_pipeline_scope) {
|
||||
scope = G.first_free_pipeline_scope;
|
||||
G.first_free_pipeline_scope = scope->next_free;
|
||||
@ -1232,7 +1232,7 @@ INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
|
||||
INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
|
||||
{
|
||||
__prof;
|
||||
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
{
|
||||
for (DictEntry *entry = scope->refs->first; entry; entry = entry->next) {
|
||||
struct pipeline *pipeline = (struct pipeline *)entry->value;
|
||||
@ -1258,7 +1258,7 @@ INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, Strin
|
||||
res = tmp;
|
||||
} else {
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
tmp = (struct pipeline *)dict_get(G.top_successful_pipelines, hash);
|
||||
if (tmp) {
|
||||
++tmp->refcount;
|
||||
@ -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;
|
||||
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||
{
|
||||
for (u64 i = 0; i < num_pipelines; ++i) {
|
||||
struct pipeline *pipeline = pipelines[i];
|
||||
@ -1328,8 +1328,8 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
if (is_rs || is_cs) {
|
||||
logf_debug("Change detected in shader source file \"%F\", recompiling...", FMT_STR(name));
|
||||
success = 1;
|
||||
struct sys_file file = sys_file_open_read_wait(name);
|
||||
String data = sys_file_read_all(scratch.arena, file);
|
||||
P_File file = P_OpenFileReadWait(name);
|
||||
String data = P_ReadFile(scratch.arena, file);
|
||||
{
|
||||
friendly_name = name;
|
||||
StringArray split = string_split(scratch.arena, friendly_name, LIT("src/"));
|
||||
@ -1371,12 +1371,12 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
sig.descs[0].target = LIT("cs_6_6");
|
||||
}
|
||||
{
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(num_shaders, shader_compile_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_shaders, shader_compile_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
}
|
||||
sys_file_close(file);
|
||||
P_CloseFIle(file);
|
||||
}
|
||||
|
||||
|
||||
@ -1423,12 +1423,12 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
struct pipeline_alloc_job_sig sig = ZI;
|
||||
sig.descs_in = pipeline_descs;
|
||||
sig.pipelines_out = pipelines;
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(num_pipelines, pipeline_alloc_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_pipelines, pipeline_alloc_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
{
|
||||
struct snc_lock lock = snc_lock_s(&G.pipelines_mutex);
|
||||
P_Lock lock = snc_lock_s(&G.pipelines_mutex);
|
||||
for (u32 i = 0; i < num_pipelines; ++i) {
|
||||
struct pipeline *pipeline = pipelines[i];
|
||||
if (pipeline->success) {
|
||||
@ -1448,7 +1448,7 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||
/* If no previously successful pipeline exists, then show a message box rather than logging since logs may not be visible to user */
|
||||
String error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
||||
String msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
||||
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
|
||||
P_MessageBox(P_MessageBoxKind_Warning, msg);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1474,7 +1474,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
|
||||
u32 index = 0;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = ZI;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&dh->mutex);
|
||||
P_Lock lock = snc_lock_e(&dh->mutex);
|
||||
if (dh->first_free_descriptor) {
|
||||
d = dh->first_free_descriptor;
|
||||
dh->first_free_descriptor = d->next_free;
|
||||
@ -1482,7 +1482,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
|
||||
index = d->index;
|
||||
} else {
|
||||
if (dh->num_descriptors_reserved >= dh->num_descriptors_capacity) {
|
||||
sys_panic(LIT("Max descriptors reached in heap"));
|
||||
P_Panic(LIT("Max descriptors reached in heap"));
|
||||
}
|
||||
d = arena_push_no_zero(dh->arena, struct descriptor);
|
||||
index = dh->num_descriptors_reserved++;
|
||||
@ -1500,7 +1500,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
|
||||
INTERNAL void descriptor_release(struct descriptor *descriptor)
|
||||
{
|
||||
struct cpu_descriptor_heap *dh = descriptor->heap;
|
||||
struct snc_lock lock = snc_lock_e(&dh->mutex);
|
||||
P_Lock lock = snc_lock_e(&dh->mutex);
|
||||
{
|
||||
descriptor->next_free = dh->first_free_descriptor;
|
||||
dh->first_free_descriptor = descriptor;
|
||||
@ -1529,7 +1529,7 @@ INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRI
|
||||
descriptor_size = G.desc_sizes[type];
|
||||
}
|
||||
if (num_descriptors == 0 || descriptor_size == 0) {
|
||||
sys_panic(LIT("Unsupported CPU descriptor type"));
|
||||
P_Panic(LIT("Unsupported CPU descriptor type"));
|
||||
}
|
||||
dh->num_descriptors_capacity = num_descriptors;
|
||||
dh->descriptor_size = descriptor_size;
|
||||
@ -1539,7 +1539,7 @@ INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRI
|
||||
desc.NumDescriptors = num_descriptors;
|
||||
HRESULT hr = ID3D12Device_CreateDescriptorHeap(G.device, &desc, &IID_ID3D12DescriptorHeap, (void **)&dh->heap);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create CPU descriptor heap"));
|
||||
P_Panic(LIT("Failed to create CPU descriptor heap"));
|
||||
}
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(dh->heap, &dh->handle);
|
||||
|
||||
@ -1569,7 +1569,7 @@ 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];
|
||||
struct snc_lock lock = snc_lock_s(&cq->submit_fence_mutex);
|
||||
P_Lock lock = snc_lock_s(&cq->submit_fence_mutex);
|
||||
{
|
||||
fr_targets[i] = cq->submit_fence_target;
|
||||
}
|
||||
@ -1578,7 +1578,7 @@ INTERNAL void fenced_release(void *data, enum fenced_release_kind kind)
|
||||
|
||||
/* Push data to release queue */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.fenced_releases_mutex);
|
||||
P_Lock lock = snc_lock_e(&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));
|
||||
@ -1588,7 +1588,7 @@ INTERNAL void fenced_release(void *data, enum fenced_release_kind kind)
|
||||
|
||||
/* Wake evictor */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
{
|
||||
++G.evictor_wake_gen;
|
||||
snc_cv_signal(&G.evictor_wake_cv, I32_MAX);
|
||||
@ -1606,7 +1606,7 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr
|
||||
__prof;
|
||||
struct dx12_resource *r = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.resources_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.resources_mutex);
|
||||
if (G.first_free_resource) {
|
||||
r = G.first_free_resource;
|
||||
G.first_free_resource = r->next_free;
|
||||
@ -1622,7 +1622,7 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr
|
||||
HRESULT hr = ID3D12Device_CreateCommittedResource(G.device, &heap_props, heap_flags, &desc, initial_state, clear_value_ptr, &IID_ID3D12Resource, (void **)&r->resource);
|
||||
if (FAILED(hr)) {
|
||||
/* TODO: Don't panic */
|
||||
sys_panic(LIT("Failed to create resource"));
|
||||
P_Panic(LIT("Failed to create resource"));
|
||||
}
|
||||
|
||||
r->state = initial_state;
|
||||
@ -1657,7 +1657,7 @@ INTERNAL void dx12_resource_release_now(struct dx12_resource *t)
|
||||
ID3D12Resource_Release(t->resource);
|
||||
|
||||
/* Add to free list */
|
||||
struct snc_lock lock = snc_lock_e(&G.resources_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.resources_mutex);
|
||||
t->next_free = G.first_free_resource;
|
||||
G.first_free_resource = t;
|
||||
snc_unlock(&lock);
|
||||
@ -1729,7 +1729,7 @@ INTERNAL void dx12_resource_barriers(ID3D12GraphicsCommandList *cl, i32 num_desc
|
||||
|
||||
INTERNAL struct command_list_pool *command_list_pool_alloc(struct command_queue *cq);
|
||||
|
||||
INTERNAL SYS_JOB_DEF(command_queue_alloc_job, job)
|
||||
INTERNAL P_JobDef(command_queue_alloc_job, job)
|
||||
{
|
||||
__prof;
|
||||
struct command_queue_alloc_job_sig *sig = job.sig;
|
||||
@ -1749,12 +1749,12 @@ INTERNAL SYS_JOB_DEF(command_queue_alloc_job, job)
|
||||
dx12_desc.Priority = desc->priority;
|
||||
HRESULT hr = ID3D12Device_CreateCommandQueue(G.device, &dx12_desc, &IID_ID3D12CommandQueue, (void **)&cq->cq);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create command queue"));
|
||||
P_Panic(LIT("Failed to create command queue"));
|
||||
}
|
||||
|
||||
hr = ID3D12Device_CreateFence(G.device, 0, 0, &IID_ID3D12Fence, (void **)&cq->submit_fence);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create command queue fence"));
|
||||
P_Panic(LIT("Failed to create command queue fence"));
|
||||
}
|
||||
|
||||
cq->cl_pool = command_list_pool_alloc(cq);
|
||||
@ -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;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&pool->mutex);
|
||||
P_Lock lock = snc_lock_e(&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) {
|
||||
@ -1838,29 +1838,29 @@ INTERNAL struct command_list *command_list_open(struct command_list_pool *pool)
|
||||
} else {
|
||||
hr = ID3D12Device_CreateCommandAllocator(G.device, cq->desc.type, &IID_ID3D12CommandAllocator, (void **)&cl->ca);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create command allocator"));
|
||||
P_Panic(LIT("Failed to create command allocator"));
|
||||
}
|
||||
|
||||
hr = ID3D12Device_CreateCommandList(G.device, 0, cq->desc.type, cl->ca, 0, &IID_ID3D12GraphicsCommandList, (void **)&cl->cl);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create command list"));
|
||||
P_Panic(LIT("Failed to create command list"));
|
||||
}
|
||||
|
||||
hr = ID3D12GraphicsCommandList_Close(cl->cl);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to close command list during initialization"));
|
||||
P_Panic(LIT("Failed to close command list during initialization"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset */
|
||||
hr = ID3D12CommandAllocator_Reset(cl->ca);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to reset command allocator"));
|
||||
P_Panic(LIT("Failed to reset command allocator"));
|
||||
}
|
||||
|
||||
hr = ID3D12GraphicsCommandList_Reset(cl->cl, cl->ca, 0);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to reset command list"));
|
||||
P_Panic(LIT("Failed to reset command list"));
|
||||
}
|
||||
|
||||
return cl;
|
||||
@ -1879,7 +1879,7 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
HRESULT hr = ID3D12GraphicsCommandList_Close(cl->cl);
|
||||
if (FAILED(hr)) {
|
||||
/* TODO: Don't panic */
|
||||
sys_panic(LIT("Failed to close command list before execution"));
|
||||
P_Panic(LIT("Failed to close command list before execution"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1887,8 +1887,8 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
u64 submit_fence_target = 0;
|
||||
{
|
||||
__profn("Execute");
|
||||
struct snc_lock submit_lock = snc_lock_s(&G.global_submit_mutex);
|
||||
struct snc_lock fence_lock = snc_lock_e(&cq->submit_fence_mutex);
|
||||
P_Lock submit_lock = snc_lock_s(&G.global_submit_mutex);
|
||||
P_Lock fence_lock = snc_lock_e(&cq->submit_fence_mutex);
|
||||
{
|
||||
submit_fence_target = ++cq->submit_fence_target;
|
||||
ID3D12CommandQueue_ExecuteCommandLists(cq->cq, 1, (ID3D12CommandList **)&cl->cl);
|
||||
@ -1900,7 +1900,7 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
|
||||
/* Add descriptor heaps to submitted list */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.command_descriptor_heaps_mutex);
|
||||
P_Lock lock = snc_lock_e(&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;
|
||||
@ -1916,7 +1916,7 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
|
||||
/* Add command buffers to submitted list */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.command_buffers_mutex);
|
||||
P_Lock lock = snc_lock_e(&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;
|
||||
@ -1935,7 +1935,7 @@ INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
snc_unlock(&cl->global_record_lock);
|
||||
cl->submitted_fence_target = submit_fence_target;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&pool->mutex);
|
||||
P_Lock lock = snc_lock_e(&pool->mutex);
|
||||
if (pool->last_submitted_command_list) {
|
||||
pool->last_submitted_command_list->next_submitted = cl;
|
||||
} else {
|
||||
@ -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;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.command_descriptor_heaps_mutex);
|
||||
P_Lock lock = snc_lock_e(&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 */
|
||||
@ -2009,7 +2009,7 @@ INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struc
|
||||
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
HRESULT hr = ID3D12Device_CreateDescriptorHeap(G.device, &desc, &IID_ID3D12DescriptorHeap, (void **)&cdh->heap);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create GPU descriptor heap"));
|
||||
P_Panic(LIT("Failed to create GPU descriptor heap"));
|
||||
}
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_cpu_handle);
|
||||
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_gpu_handle);
|
||||
@ -2017,7 +2017,7 @@ INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struc
|
||||
|
||||
/* Copy CPU heap */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_s(&dh_cpu->mutex);
|
||||
P_Lock lock = snc_lock_s(&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);
|
||||
}
|
||||
@ -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;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.command_buffers_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.command_buffers_mutex);
|
||||
|
||||
{
|
||||
u64 group_hash = command_buffer_hash_from_size(size);
|
||||
@ -2163,7 +2163,7 @@ INTERNAL struct command_buffer *_command_list_push_buffer(struct command_list *c
|
||||
HRESULT hr = ID3D12Resource_Map(cb->resource->resource, 0, &read_range, &dst);
|
||||
if (FAILED(hr) || !dst) {
|
||||
/* TODO: Don't panic */
|
||||
sys_panic(LIT("Failed to map command buffer resource"));
|
||||
P_Panic(LIT("Failed to map command buffer resource"));
|
||||
}
|
||||
MEMCPY(dst, data, data_len);
|
||||
ID3D12Resource_Unmap(cb->resource->resource, 0, 0);
|
||||
@ -2185,7 +2185,7 @@ struct dx12_wait_fence_job_sig {
|
||||
u64 target;
|
||||
};
|
||||
|
||||
INTERNAL SYS_JOB_DEF(dx12_wait_fence_job, job)
|
||||
INTERNAL P_JobDef(dx12_wait_fence_job, job)
|
||||
{
|
||||
__prof;
|
||||
struct dx12_wait_fence_job_sig *sig = job.sig;
|
||||
@ -2208,7 +2208,7 @@ G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void
|
||||
{
|
||||
__prof;
|
||||
if (size.x <= 0 || size.y <= 0) {
|
||||
sys_panic(LIT("Tried to create texture with dimension <= 0"));
|
||||
P_Panic(LIT("Tried to create texture with dimension <= 0"));
|
||||
}
|
||||
LOCAL_PERSIST const DXGI_FORMAT formats[] = {
|
||||
[GP_TEXTURE_FORMAT_R8_UNORM] = DXGI_FORMAT_R8_UNORM,
|
||||
@ -2222,7 +2222,7 @@ G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void
|
||||
dxgi_format = formats[format];
|
||||
}
|
||||
if (format == 0) {
|
||||
sys_panic(LIT("Tried to create texture with unknown format"));
|
||||
P_Panic(LIT("Tried to create texture with unknown format"));
|
||||
}
|
||||
|
||||
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
|
||||
@ -2260,11 +2260,11 @@ G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void
|
||||
/* Upload texture */
|
||||
if (initial_data) {
|
||||
/* TODO: Make wait optional */
|
||||
struct snc_counter counter = ZI;
|
||||
P_Counter counter = ZI;
|
||||
struct dx12_upload_job_sig sig = ZI;
|
||||
sig.resource = r;
|
||||
sig.data = initial_data;
|
||||
sys_run(1, dx12_upload_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
|
||||
P_Run(1, dx12_upload_job, &sig, P_Pool_Inherit, P_Priority_Inherit, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
|
||||
@ -2281,7 +2281,7 @@ V2i32 gp_texture_get_size(G_Resource *resource)
|
||||
* Upload
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(dx12_upload_job, job)
|
||||
INTERNAL P_JobDef(dx12_upload_job, job)
|
||||
{
|
||||
struct dx12_upload_job_sig *sig = job.sig;
|
||||
struct dx12_resource *r = sig->resource;
|
||||
@ -2335,7 +2335,7 @@ INTERNAL SYS_JOB_DEF(dx12_upload_job, job)
|
||||
HRESULT hr = ID3D12Resource_Map(upload->resource, 0, &read_range, &mapped);
|
||||
if (FAILED(hr) || !mapped) {
|
||||
/* TODO: Don't panic */
|
||||
sys_panic(LIT("Failed to map texture upload resource"));
|
||||
P_Panic(LIT("Failed to map texture upload resource"));
|
||||
}
|
||||
u8 *dst = (u8 *)mapped + placed_footprint.Offset;
|
||||
u8 *src = data;
|
||||
@ -2375,8 +2375,8 @@ INTERNAL SYS_JOB_DEF(dx12_upload_job, job)
|
||||
struct dx12_wait_fence_job_sig wait_sig = ZI;
|
||||
wait_sig.fence = cq->submit_fence;
|
||||
wait_sig.target = fence_target;
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(1, dx12_wait_fence_job, &wait_sig, SYS_POOL_FLOATING, SYS_PRIORITY_LOW, &counter);
|
||||
P_Counter counter = ZI;
|
||||
P_Run(1, dx12_wait_fence_job, &wait_sig, P_Pool_Floating, P_Priority_Low, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
|
||||
@ -3189,7 +3189,7 @@ INTERNAL void swapchain_init_resources(struct swapchain *swapchain)
|
||||
HRESULT hr = IDXGISwapChain3_GetBuffer(swapchain->swapchain, i, &IID_ID3D12Resource, (void **)&resource);
|
||||
if (FAILED(hr)) {
|
||||
/* TODO: Don't panic */
|
||||
sys_panic(LIT("Failed to get swapchain buffer"));
|
||||
P_Panic(LIT("Failed to get swapchain buffer"));
|
||||
}
|
||||
struct swapchain_buffer *sb = &swapchain->buffers[i];
|
||||
MEMZERO_STRUCT(sb);
|
||||
@ -3201,15 +3201,15 @@ INTERNAL void swapchain_init_resources(struct swapchain *swapchain)
|
||||
}
|
||||
}
|
||||
|
||||
G_Swapchain *gp_swapchain_alloc(struct sys_window *window, V2i32 resolution)
|
||||
G_Swapchain *gp_swapchain_alloc(P_Window *window, V2i32 resolution)
|
||||
{
|
||||
HRESULT hr = 0;
|
||||
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
|
||||
HWND hwnd = (HWND)P_GetInternalWindowHandle(window);
|
||||
struct command_queue *cq = G.command_queues[DX12_QUEUE_DIRECT];
|
||||
|
||||
struct swapchain *swapchain = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.swapchains_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.swapchains_mutex);
|
||||
if (G.first_free_swapchain) {
|
||||
swapchain = G.first_free_swapchain;
|
||||
G.first_free_swapchain = swapchain->next_free;
|
||||
@ -3236,14 +3236,14 @@ G_Swapchain *gp_swapchain_alloc(struct sys_window *window, V2i32 resolution)
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
hr = IDXGIFactory2_CreateSwapChainForHwnd(G.factory, (IUnknown *)cq->cq, hwnd, &desc, 0, 0, &swapchain1);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create IDXGISwapChain1"));
|
||||
P_Panic(LIT("Failed to create IDXGISwapChain1"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Upgrade to swapchain3 */
|
||||
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain->swapchain);
|
||||
if (FAILED(hr)) {
|
||||
sys_panic(LIT("Failed to create IDXGISwapChain3"));
|
||||
P_Panic(LIT("Failed to create IDXGISwapChain3"));
|
||||
}
|
||||
|
||||
/* Create waitable object */
|
||||
@ -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 */
|
||||
struct snc_lock lock = snc_lock_e(&cq->submit_fence_mutex);
|
||||
P_Lock lock = snc_lock_e(&cq->submit_fence_mutex);
|
||||
//DEBUGBREAKABLE;
|
||||
//struct snc_lock lock = snc_lock_e(&G.global_command_list_record_mutex);
|
||||
//P_Lock lock = snc_lock_e(&G.global_command_list_record_mutex);
|
||||
{
|
||||
/* Flush direct queue */
|
||||
//ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, ++cq->submit_fence_target);
|
||||
@ -3317,7 +3317,7 @@ INTERNAL struct swapchain_buffer *update_swapchain(struct swapchain *swapchain,
|
||||
hr = IDXGISwapChain_ResizeBuffers(swapchain->swapchain, 0, resolution.x, resolution.y, DXGI_FORMAT_UNKNOWN, DX12_SWAPCHAIN_FLAGS);
|
||||
if (FAILED(hr)) {
|
||||
/* TODO: Don't panic */
|
||||
sys_panic(LIT("Failed to resize swapchain"));
|
||||
P_Panic(LIT("Failed to resize swapchain"));
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
@ -3464,7 +3464,7 @@ 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 */
|
||||
struct snc_lock lock = snc_lock_e(&G.global_command_list_record_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.global_command_list_record_mutex);
|
||||
for (u32 i = 0; i < countof(G.command_queues); ++i) {
|
||||
{
|
||||
struct command_queue *cq = G.command_queues[i];
|
||||
@ -3487,7 +3487,7 @@ void gp_present(G_Swapchain *gp_swapchain, V2i32 backbuffer_resolution, G_Resour
|
||||
* Evictor thread
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(dx12_evictor_job, _)
|
||||
INTERNAL P_JobDef(dx12_evictor_job, _)
|
||||
{
|
||||
(UNUSED)_;
|
||||
|
||||
@ -3505,7 +3505,7 @@ INTERNAL SYS_JOB_DEF(dx12_evictor_job, _)
|
||||
struct fenced_release_data *fenced_releases = 0;
|
||||
{
|
||||
__profn("Copy queued releases");
|
||||
struct snc_lock lock = snc_lock_e(&G.fenced_releases_mutex);
|
||||
P_Lock lock = snc_lock_e(&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);
|
||||
@ -3528,8 +3528,8 @@ INTERNAL SYS_JOB_DEF(dx12_evictor_job, _)
|
||||
sig.fence = cq->submit_fence;
|
||||
sig.target = targets[i];
|
||||
{
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(1, dx12_wait_fence_job, &sig, SYS_POOL_FLOATING, SYS_PRIORITY_LOW, &counter);
|
||||
P_Counter counter = ZI;
|
||||
P_Run(1, dx12_wait_fence_job, &sig, P_Pool_Floating, P_Priority_Low, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
}
|
||||
@ -3563,7 +3563,7 @@ INTERNAL SYS_JOB_DEF(dx12_evictor_job, _)
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
struct snc_lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.evictor_wake_mutex);
|
||||
{
|
||||
while (!G.evictor_shutdown && G.evictor_wake_gen == 0) {
|
||||
snc_cv_wait(&G.evictor_wake_cv, &lock);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define MIXER_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../sound/sound.h"
|
||||
|
||||
#include "mixer_core.h"
|
||||
|
||||
@ -26,7 +26,7 @@ struct mix {
|
||||
|
||||
M_TrackDesc desc;
|
||||
struct effect_data effect_data;
|
||||
struct sound *source;
|
||||
SND_Sound *source;
|
||||
u64 source_pos;
|
||||
};
|
||||
|
||||
@ -34,7 +34,7 @@ struct track {
|
||||
u64 gen;
|
||||
|
||||
/* Controlled via interface */
|
||||
struct sound *sound;
|
||||
SND_Sound *sound;
|
||||
M_TrackDesc desc;
|
||||
|
||||
/* Internal */
|
||||
@ -45,7 +45,7 @@ struct track {
|
||||
};
|
||||
|
||||
GLOBAL struct {
|
||||
struct snc_mutex mutex;
|
||||
P_Mutex mutex;
|
||||
|
||||
/* Listener */
|
||||
V2 listener_pos;
|
||||
@ -94,7 +94,7 @@ INTERNAL struct track *track_from_handle(M_Handle handle)
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL struct track *track_alloc_locked(struct snc_lock *lock, struct sound *sound)
|
||||
INTERNAL struct track *track_alloc_locked(P_Lock *lock, SND_Sound *sound)
|
||||
{
|
||||
snc_assert_locked_e(lock, &G.mutex);
|
||||
(UNUSED)lock;
|
||||
@ -133,7 +133,7 @@ INTERNAL struct track *track_alloc_locked(struct snc_lock *lock, struct sound *s
|
||||
return track;
|
||||
}
|
||||
|
||||
INTERNAL void track_release_locked(struct snc_lock *lock, struct track *track)
|
||||
INTERNAL void track_release_locked(P_Lock *lock, struct track *track)
|
||||
{
|
||||
snc_assert_locked_e(lock, &G.mutex);
|
||||
(UNUSED)lock;
|
||||
@ -172,16 +172,16 @@ INTERNAL void track_release_locked(struct snc_lock *lock, struct track *track)
|
||||
/* TODO: Rework interface to take "mixer_cmd"s instead of
|
||||
* directly modifying tracks. */
|
||||
|
||||
M_Handle mixer_play(struct sound *sound)
|
||||
M_Handle mixer_play(SND_Sound *sound)
|
||||
{
|
||||
return mixer_play_ex(sound, MIXER_DESC());
|
||||
}
|
||||
|
||||
M_Handle mixer_play_ex(struct sound *sound, M_TrackDesc desc)
|
||||
M_Handle mixer_play_ex(SND_Sound *sound, M_TrackDesc desc)
|
||||
{
|
||||
struct track *track;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
{
|
||||
track = track_alloc_locked(&lock, sound);
|
||||
track->desc = desc;
|
||||
@ -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 */
|
||||
struct snc_lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
{
|
||||
/* Confirm handle is still valid now that we're locked */
|
||||
track = track_from_handle(handle);
|
||||
@ -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 */
|
||||
struct snc_lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
{
|
||||
/* Confirm handle is still valid now that we're locked */
|
||||
track = track_from_handle(handle);
|
||||
@ -233,7 +233,7 @@ void mixer_track_set(M_Handle handle, M_TrackDesc desc)
|
||||
|
||||
void mixer_set_listener(V2 pos, V2 dir)
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
{
|
||||
G.listener_pos = pos;
|
||||
G.listener_dir = v2_norm(dir);
|
||||
@ -245,7 +245,7 @@ void mixer_set_listener(V2 pos, V2 dir)
|
||||
* Update
|
||||
* ========================== */
|
||||
|
||||
INTERNAL i16 sample_sound(struct sound *sound, u64 sample_pos, b32 wrap)
|
||||
INTERNAL i16 sample_sound(SND_Sound *sound, u64 sample_pos, b32 wrap)
|
||||
{
|
||||
if (wrap) {
|
||||
return sound->pcm.samples[sample_pos % sound->pcm.count];
|
||||
@ -274,7 +274,7 @@ M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||
struct mix **mixes = 0;
|
||||
u64 mixes_count = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
|
||||
/* Read listener info */
|
||||
listener_pos = G.listener_pos;
|
||||
@ -301,7 +301,7 @@ M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||
continue;
|
||||
}
|
||||
|
||||
struct sound *source = mix->source;
|
||||
SND_Sound *source = mix->source;
|
||||
M_TrackDesc desc = mix->desc;
|
||||
struct effect_data *effect_data = &mix->effect_data;
|
||||
b32 source_is_stereo = source->flags & SOUND_FLAG_STEREO;
|
||||
@ -462,7 +462,7 @@ M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||
|
||||
{
|
||||
__profn("Update track effect data");
|
||||
struct snc_lock lock = snc_lock_e(&G.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.mutex);
|
||||
for (u64 i = 0; i < mixes_count; ++i) {
|
||||
struct mix *mix = mixes[i];
|
||||
struct track *track = track_from_handle(mix->track_handle);
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
struct sound;
|
||||
|
||||
#define MIXER_FLAG_NONE 0x0
|
||||
#define MIXER_FLAG_SPATIALIZE 0x1
|
||||
|
||||
@ -44,8 +42,8 @@ struct M_StartupReceipt { i32 _; };
|
||||
M_StartupReceipt mixer_startup(void);
|
||||
|
||||
/* Interface */
|
||||
M_Handle mixer_play(struct sound *sound);
|
||||
M_Handle mixer_play_ex(struct sound *sound, M_TrackDesc desc);
|
||||
M_Handle mixer_play(SND_Sound *sound);
|
||||
M_Handle mixer_play_ex(SND_Sound *sound, M_TrackDesc desc);
|
||||
M_TrackDesc mixer_track_get(M_Handle handle);
|
||||
void mixer_track_set(M_Handle handle, M_TrackDesc desc);
|
||||
void mixer_set_listener(V2 pos, V2 dir);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define NET_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
|
||||
#include "net_core.h"
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ struct host_channel {
|
||||
|
||||
struct host_channel *next_free;
|
||||
|
||||
struct sys_address address;
|
||||
P_Address address;
|
||||
u64 address_hash;
|
||||
struct host_channel *next_address_hash;
|
||||
struct host_channel *prev_address_hash;
|
||||
@ -76,7 +76,7 @@ struct host_channel_list {
|
||||
|
||||
struct host_rcv_packet {
|
||||
struct sock *sock;
|
||||
struct sys_address address;
|
||||
P_Address address;
|
||||
String data;
|
||||
struct host_rcv_packet *next;
|
||||
};
|
||||
@ -159,14 +159,14 @@ N_Host *host_alloc(u16 listen_port)
|
||||
host->num_msg_assembler_lookup_bins = N_NumMsgAssemblerLookupBins;
|
||||
host->msg_assembler_lookup_bins = arena_push_array(host->arena, struct host_msg_assembler_lookup_bin, host->num_msg_assembler_lookup_bins);
|
||||
|
||||
host->sock = sys_sock_alloc(listen_port, MEBI(2), MEBI(2));
|
||||
host->sock = P_AllocSock(listen_port, MEBI(2), MEBI(2));
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
void host_release(N_Host *host)
|
||||
{
|
||||
sys_sock_release(host->sock);
|
||||
P_ReleaseSock(host->sock);
|
||||
|
||||
buddy_ctx_release(host->buddy);
|
||||
arena_release(host->rcv_buffer_write->arena);
|
||||
@ -180,17 +180,17 @@ void host_release(N_Host *host)
|
||||
* Channel
|
||||
* ========================== */
|
||||
|
||||
INTERNAL u64 hash_from_address(struct sys_address address)
|
||||
INTERNAL u64 hash_from_address(P_Address address)
|
||||
{
|
||||
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&address));
|
||||
}
|
||||
|
||||
INTERNAL struct host_channel *host_channel_from_address(N_Host *host, struct sys_address address)
|
||||
INTERNAL struct host_channel *host_channel_from_address(N_Host *host, P_Address address)
|
||||
{
|
||||
u64 hash = hash_from_address(address);
|
||||
N_ChannelLookupBin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins];
|
||||
for (struct host_channel *channel = bin->first; channel; channel = channel->next_address_hash) {
|
||||
if (channel->address_hash == hash && sys_address_eq(channel->address, address)) {
|
||||
if (channel->address_hash == hash && P_AddressIsEqual(channel->address, address)) {
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
@ -238,7 +238,7 @@ INTERNAL struct host_channel_list host_channels_from_id(Arena *arena, N_Host *ho
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERNAL struct host_channel *host_channel_alloc(N_Host *host, struct sys_address address)
|
||||
INTERNAL struct host_channel *host_channel_alloc(N_Host *host, P_Address address)
|
||||
{
|
||||
N_ChannelId id = ZI;
|
||||
struct host_channel *channel;
|
||||
@ -546,7 +546,7 @@ INTERNAL N_Cmd *host_cmd_alloc_and_append(N_Host *host)
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void host_queue_connect_to_address(N_Host *host, struct sys_address connect_address)
|
||||
void host_queue_connect_to_address(N_Host *host, P_Address connect_address)
|
||||
{
|
||||
struct host_channel *channel = host_channel_from_address(host, connect_address);
|
||||
if (!channel->valid) {
|
||||
@ -602,7 +602,7 @@ N_EventList host_update_begin(Arena *arena, N_Host *host)
|
||||
TempArena scratch = scratch_begin(arena);
|
||||
|
||||
N_EventList events = ZI;
|
||||
i64 now_ns = sys_time_ns();
|
||||
i64 now_ns = P_TimeNs();
|
||||
{
|
||||
__profn("Read packets");
|
||||
|
||||
@ -611,10 +611,10 @@ N_EventList host_update_begin(Arena *arena, N_Host *host)
|
||||
struct host_rcv_packet *last_packet = 0;
|
||||
{
|
||||
__profn("Read socket");
|
||||
struct sys_sock *sock = host->sock;
|
||||
struct sys_sock_read_result res = ZI;
|
||||
while ((res = sys_sock_read(scratch.arena, sock)).valid) {
|
||||
struct sys_address address = res.address;
|
||||
P_Sock *sock = host->sock;
|
||||
P_SockReadResult res = ZI;
|
||||
while ((res = P_ReadSock(scratch.arena, sock)).valid) {
|
||||
P_Address address = res.address;
|
||||
String data = res.data;
|
||||
if (data.len > 0) {
|
||||
struct host_rcv_packet *packet = arena_push(scratch.arena, struct host_rcv_packet);
|
||||
@ -635,7 +635,7 @@ N_EventList host_update_begin(Arena *arena, N_Host *host)
|
||||
__profn("Process host packets");
|
||||
for (struct host_rcv_packet *packet = first_packet; packet; packet = packet->next) {
|
||||
//struct sock *sock = packet->sock;
|
||||
struct sys_address address = packet->address;
|
||||
P_Address address = packet->address;
|
||||
Bitbuff bb = bitbuff_from_string(packet->data);
|
||||
BitbuffReader br = br_from_bitbuff(&bb);
|
||||
u32 magic = br_read_ubits(&br, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
@ -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(sys_string_from_address(scratch.arena, address)));
|
||||
logf_info("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(sys_string_from_address(scratch.arena, address)));
|
||||
logf_info("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(sys_string_from_address(scratch.arena, address)));
|
||||
logf_info("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;
|
||||
@ -981,19 +981,19 @@ void host_update_end(N_Host *host)
|
||||
{
|
||||
__profn("Send host packets");
|
||||
for (u64 i = 0; i < host->num_channels_reserved; ++i) {
|
||||
struct sys_sock *sock = host->sock;
|
||||
P_Sock *sock = host->sock;
|
||||
struct host_channel *channel = &host->channels[i];
|
||||
u64 total_sent = 0;
|
||||
if (channel->valid) {
|
||||
struct sys_address address = channel->address;
|
||||
P_Address address = channel->address;
|
||||
/* Send reliable packets to channel */
|
||||
for (N_SndPacket *packet = channel->first_reliable_packet; packet; packet = packet->next) {
|
||||
sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
|
||||
P_WriteSock(sock, address, STRING(packet->data_len, packet->data));
|
||||
total_sent += packet->data_len;
|
||||
}
|
||||
/* Send unreliable packets to channel */
|
||||
for (N_SndPacket *packet = channel->first_unreliable_packet; packet; packet = packet->next) {
|
||||
sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
|
||||
P_WriteSock(sock, address, STRING(packet->data_len, packet->data));
|
||||
total_sent += packet->data_len;
|
||||
}
|
||||
/* Release unreliable packets */
|
||||
|
||||
@ -94,7 +94,7 @@ typedef struct N_Host N_Host;
|
||||
struct N_Host {
|
||||
Arena *arena;
|
||||
|
||||
struct sys_sock *sock;
|
||||
P_Sock *sock;
|
||||
|
||||
BuddyCtx *buddy; /* For storing msg assembler data */
|
||||
|
||||
@ -118,7 +118,7 @@ struct N_Host {
|
||||
u64 num_msg_assembler_lookup_bins;
|
||||
|
||||
/* Double buffer for incoming data */
|
||||
struct snc_mutex rcv_buffer_write_mutex;
|
||||
P_Mutex rcv_buffer_write_mutex;
|
||||
N_RcvBuffer *rcv_buffer_read;
|
||||
N_RcvBuffer *rcv_buffer_write;
|
||||
|
||||
@ -146,7 +146,7 @@ void host_release(N_Host *host);
|
||||
* Queue
|
||||
* ========================== */
|
||||
|
||||
void host_queue_connect_to_address(N_Host *host, struct sys_address connect_address);
|
||||
void host_queue_connect_to_address(N_Host *host, P_Address connect_address);
|
||||
|
||||
void host_queue_disconnect(N_Host *host, N_ChannelId channel_id);
|
||||
|
||||
|
||||
11
src/platform/platform.c
Normal file
11
src/platform/platform.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include "platform.h"
|
||||
|
||||
#include "platform_snc.c"
|
||||
#include "platform_sleep.c"
|
||||
#include "platform_log.c"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
# include "platform_win32.c"
|
||||
#else
|
||||
# error Platform core not implemented
|
||||
#endif
|
||||
15
src/platform/platform.h
Normal file
15
src/platform/platform.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include "../base/base.h"
|
||||
|
||||
#include "platform_snc.h"
|
||||
#include "platform_sleep.h"
|
||||
#include "platform_core.h"
|
||||
#include "platform_log.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
# include "platform_win32.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
482
src/platform/platform_core.h
Normal file
482
src/platform/platform_core.h
Normal file
@ -0,0 +1,482 @@
|
||||
/* ========================== *
|
||||
* 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
|
||||
* ========================== */
|
||||
|
||||
/* 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 {
|
||||
P_Pool_Inherit = -1,
|
||||
|
||||
/* The floating pool contains a large number of lower priority threads that have affinity over the entire CPU.
|
||||
* Other pools should push jobs that only block and do no work here so that they can yield on the blocking job rather than blocking themselves. */
|
||||
P_Pool_Floating = 0,
|
||||
|
||||
P_Pool_Background = 1,
|
||||
P_Pool_Audio = 2,
|
||||
P_Pool_User = 3,
|
||||
P_Pool_Sim = 4,
|
||||
|
||||
P_Pool_Count
|
||||
} P_Pool;
|
||||
|
||||
/* Job execution order within a pool is based on priority. */
|
||||
typedef enum P_Priority {
|
||||
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 {
|
||||
i32 id;
|
||||
void *sig;
|
||||
};
|
||||
|
||||
#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
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_DateTime P_DateTime;
|
||||
struct P_DateTime {
|
||||
u32 year;
|
||||
u32 month;
|
||||
u32 day_of_week;
|
||||
u32 day;
|
||||
u32 hour;
|
||||
u32 minute;
|
||||
u32 second;
|
||||
u32 milliseconds;
|
||||
};
|
||||
|
||||
P_DateTime P_LocalTime(void);
|
||||
|
||||
i64 P_TimeNs(void);
|
||||
|
||||
/* ========================== *
|
||||
* File system
|
||||
*
|
||||
* NOTE: File paths use forward slash '/' as delimiter
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_File P_File;
|
||||
struct P_File {
|
||||
u64 handle;
|
||||
b32 valid;
|
||||
};
|
||||
|
||||
typedef struct P_FileTime 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 {
|
||||
String mapped_memory;
|
||||
u64 handle;
|
||||
b32 valid;
|
||||
};
|
||||
|
||||
P_FileMap P_OpenFileMap(P_File file);
|
||||
|
||||
void P_CloseFileMap(P_FileMap map);
|
||||
|
||||
String P_GetFileMapData(P_FileMap map);
|
||||
|
||||
/* ========================== *
|
||||
* Watch
|
||||
* ========================== */
|
||||
|
||||
typedef enum P_WatchInfoKind {
|
||||
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 {
|
||||
P_WatchInfoKind kind;
|
||||
String name;
|
||||
P_WatchInfo *next;
|
||||
P_WatchInfo *prev;
|
||||
};
|
||||
|
||||
typedef struct P_WatchInfoList P_WatchInfoList;
|
||||
struct P_WatchInfoList {
|
||||
P_WatchInfo *first;
|
||||
P_WatchInfo *last;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
typedef struct P_Watch P_Watch;
|
||||
|
||||
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 {
|
||||
P_Btn_None,
|
||||
|
||||
P_Btn_M1,
|
||||
P_Btn_M2,
|
||||
P_Btn_M3,
|
||||
P_Btn_M4,
|
||||
P_Btn_M5,
|
||||
|
||||
P_Btn_MWheelUp,
|
||||
P_Btn_MWheelDown,
|
||||
|
||||
P_Btn_ESC,
|
||||
P_Btn_F1,
|
||||
P_Btn_F2,
|
||||
P_Btn_F3,
|
||||
P_Btn_F4,
|
||||
P_Btn_F5,
|
||||
P_Btn_F6,
|
||||
P_Btn_F7,
|
||||
P_Btn_F8,
|
||||
P_Btn_F9,
|
||||
P_Btn_F10,
|
||||
P_Btn_F11,
|
||||
P_Btn_F12,
|
||||
P_Btn_F13,
|
||||
P_Btn_F14,
|
||||
P_Btn_F15,
|
||||
P_Btn_F16,
|
||||
P_Btn_F17,
|
||||
P_Btn_F18,
|
||||
P_Btn_F19,
|
||||
P_Btn_F20,
|
||||
P_Btn_F21,
|
||||
P_Btn_F22,
|
||||
P_Btn_F23,
|
||||
P_Btn_F24,
|
||||
P_Btn_GraveAccent,
|
||||
P_Btn_0,
|
||||
P_Btn_1,
|
||||
P_Btn_2,
|
||||
P_Btn_3,
|
||||
P_Btn_4,
|
||||
P_Btn_5,
|
||||
P_Btn_6,
|
||||
P_Btn_7,
|
||||
P_Btn_8,
|
||||
P_Btn_9,
|
||||
P_Btn_Minus,
|
||||
P_Btn_Equal,
|
||||
P_Btn_Backspace,
|
||||
P_Btn_Delete,
|
||||
P_Btn_Tab,
|
||||
P_Btn_A,
|
||||
P_Btn_B,
|
||||
P_Btn_C,
|
||||
P_Btn_D,
|
||||
P_Btn_E,
|
||||
P_Btn_F,
|
||||
P_Btn_G,
|
||||
P_Btn_H,
|
||||
P_Btn_I,
|
||||
P_Btn_J,
|
||||
P_Btn_K,
|
||||
P_Btn_L,
|
||||
P_Btn_M,
|
||||
P_Btn_N,
|
||||
P_Btn_O,
|
||||
P_Btn_P,
|
||||
P_Btn_Q,
|
||||
P_Btn_R,
|
||||
P_Btn_S,
|
||||
P_Btn_T,
|
||||
P_Btn_U,
|
||||
P_Btn_V,
|
||||
P_Btn_W,
|
||||
P_Btn_X,
|
||||
P_Btn_Y,
|
||||
P_Btn_Z,
|
||||
P_Btn_Space,
|
||||
P_Btn_Enter,
|
||||
P_Btn_Ctrl,
|
||||
P_Btn_Shift,
|
||||
P_Btn_Alt,
|
||||
P_Btn_Up,
|
||||
P_Btn_Left,
|
||||
P_Btn_Down,
|
||||
P_Btn_Right,
|
||||
P_Btn_PageUp,
|
||||
P_Btn_PageDown,
|
||||
P_Btn_Home,
|
||||
P_Btn_End,
|
||||
P_Btn_ForwardSlash,
|
||||
P_Btn_Period,
|
||||
P_Btn_Comma,
|
||||
P_Btn_Quote,
|
||||
P_Btn_LeftBracket,
|
||||
P_Btn_RightBracket,
|
||||
P_Btn_Insert,
|
||||
P_Btn_Semicolon,
|
||||
|
||||
P_Btn_Count
|
||||
} P_Btn;
|
||||
|
||||
typedef enum P_WindowEventKind {
|
||||
P_WindowEventKind_None,
|
||||
|
||||
P_WindowEventKind_ButtonDown,
|
||||
P_WindowEventKind_ButtonUp,
|
||||
P_WindowEventKind_CursorMove,
|
||||
P_WindowEventKind_MouseMove,
|
||||
P_WindowEventKind_Text,
|
||||
P_WindowEventKind_Quit,
|
||||
|
||||
P_WindowEventKind_Count
|
||||
} P_WindowEventKind;
|
||||
|
||||
typedef struct P_WindowEvent P_WindowEvent;
|
||||
struct P_WindowEvent {
|
||||
P_WindowEventKind kind;
|
||||
|
||||
/* P_WindowEventKind_BUTTON_DOWN */
|
||||
/* P_WindowEventKind_BUTTON_UP */
|
||||
P_Btn button;
|
||||
b32 is_repeat;
|
||||
|
||||
/* P_WindowEventKind_TEXT */
|
||||
u32 text_codepoint;
|
||||
|
||||
/* P_WindowEventKind_CURSOR_MOVE */
|
||||
V2 cursor_position;
|
||||
|
||||
/* P_WindowEventKind_MOUSE_MOVE */
|
||||
V2 mouse_delta;
|
||||
};
|
||||
|
||||
typedef struct P_WindowEventArray P_WindowEventArray;
|
||||
struct P_WindowEventArray {
|
||||
u64 count;
|
||||
P_WindowEvent *events;
|
||||
};
|
||||
|
||||
/* 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 {
|
||||
P_WindowSettingsFlag_None = 0x00,
|
||||
P_WindowSettingsFlag_Fullscreen = 0x01,
|
||||
|
||||
/* NOTE: Both maximized and minimized can be true at the same time. This
|
||||
* means that the window was minimized from a maximized state, and will
|
||||
* restore to being maximized once it's un-minimized. */
|
||||
P_WindowSettingsFlag_Maximized = 0x02,
|
||||
P_WindowSettingsFlag_Minimized = 0x04
|
||||
} P_WindowSettingsFlag;
|
||||
|
||||
typedef enum P_WindowFlag {
|
||||
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 {
|
||||
char title[256];
|
||||
u32 flags;
|
||||
|
||||
/* NOTE: Below fields are NOT representative of actual window dimensions.
|
||||
* These values represent the window dimensions when the window is not
|
||||
* maximized, minimized, or fullscreen. AKA 'floating'. Use
|
||||
* `P_GetWindowSize` for rendering instead. */
|
||||
i32 floating_x;
|
||||
i32 floating_y;
|
||||
i32 floating_width;
|
||||
i32 floating_height;
|
||||
};
|
||||
|
||||
P_Window *P_AllocWindow(void);
|
||||
|
||||
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 {
|
||||
P_AddressFamily_Ipv4,
|
||||
P_AddressFamily_Ipv6
|
||||
} P_AddressFamily;
|
||||
|
||||
typedef struct P_Address P_Address;
|
||||
struct P_Address {
|
||||
b32 valid;
|
||||
P_AddressFamily family;
|
||||
/* NOTE: ipnb & portnb are stored in network byte order */
|
||||
u8 ipnb[16];
|
||||
u16 portnb;
|
||||
};
|
||||
|
||||
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
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_SockReadResult 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;
|
||||
|
||||
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 {
|
||||
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
|
||||
* ========================== */
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
/* Signals the program to shut down gracefully and run exit callbacks */
|
||||
void P_Exit(void);
|
||||
|
||||
/* Forcefully exits the program and displays `msg` to the user */
|
||||
void P_Panic(String msg);
|
||||
|
||||
/* ========================== *
|
||||
* App entry point
|
||||
* ========================== */
|
||||
|
||||
/* Must be defined by app */
|
||||
void P_AppStartup(String args_str);
|
||||
@ -11,17 +11,17 @@ struct log_event_callback {
|
||||
struct shared_log_ctx {
|
||||
Atomic32 initialized;
|
||||
|
||||
struct snc_mutex callbacks_mutex;
|
||||
P_Mutex callbacks_mutex;
|
||||
Arena *callbacks_arena;
|
||||
struct log_event_callback *first_callback;
|
||||
struct log_event_callback *last_callback;
|
||||
|
||||
struct sys_file file;
|
||||
P_File file;
|
||||
b32 file_valid;
|
||||
};
|
||||
|
||||
GLOBAL struct shared_log_ctx g_shared_log_ctx = ZI;
|
||||
GLOBAL READONLY struct log_level_settings g_log_settings[LOG_LEVEL_COUNT] = {
|
||||
GLOBAL READONLY P_LogLevelSettings g_log_settings[LOG_LEVEL_COUNT] = {
|
||||
[LOG_LEVEL_CRITICAL] = {
|
||||
LIT_NOCAST("CRITICAL"),
|
||||
COLOR_PURPLE
|
||||
@ -64,10 +64,10 @@ void log_startup(String logfile_path)
|
||||
ctx->callbacks_arena = arena_alloc(MEBI(8));
|
||||
if (logfile_path.len > 0) {
|
||||
/* Create / wipe log file */
|
||||
sys_file_close(sys_file_open_write(logfile_path));
|
||||
P_CloseFIle(P_OpenFileWrite(logfile_path));
|
||||
/* Keep log file open for appending */
|
||||
if (sys_is_file(logfile_path)) {
|
||||
ctx->file = sys_file_open_append(logfile_path);
|
||||
if (P_IsFile(logfile_path)) {
|
||||
ctx->file = P_OpenFileAppend(logfile_path);
|
||||
ctx->file_valid = 1;
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ void log_register_callback(log_event_callback_func *func, i32 level)
|
||||
{
|
||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
struct snc_lock lock = snc_lock_e(&ctx->callbacks_mutex);
|
||||
P_Lock lock = snc_lock_e(&ctx->callbacks_mutex);
|
||||
{
|
||||
struct log_event_callback *callback = arena_push(ctx->callbacks_arena, struct log_event_callback);
|
||||
callback->func = func;
|
||||
@ -110,7 +110,7 @@ INTERNAL void append_to_logfile(String msg)
|
||||
if (ctx->file_valid) {
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
String msg_line = string_cat(scratch.arena, msg, LIT("\n"));
|
||||
sys_file_write(ctx->file, msg_line);
|
||||
P_WriteFile(ctx->file, msg_line);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
@ -123,9 +123,9 @@ void _log_panic(String msg)
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
|
||||
if (ctx->file_valid) {
|
||||
sys_file_write(ctx->file, LIT("******** PANICKING ********\n"));
|
||||
sys_file_write(ctx->file, msg);
|
||||
sys_file_write(ctx->file, LIT("\n***************************\n"));
|
||||
P_WriteFile(ctx->file, LIT("******** PANICKING ********\n"));
|
||||
P_WriteFile(ctx->file, msg);
|
||||
P_WriteFile(ctx->file, LIT("\n***************************\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,17 +140,17 @@ void _log(i32 level, String msg)
|
||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||
|
||||
if (level < 0 || level >= LOG_LEVEL_COUNT) {
|
||||
sys_panic(LIT("Invalid log level"));
|
||||
P_Panic(LIT("Invalid log level"));
|
||||
}
|
||||
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
|
||||
struct sys_datetime datetime = sys_local_time();
|
||||
i64 time_ns = sys_time_ns();
|
||||
P_DateTime datetime = P_LocalTime();
|
||||
i64 time_ns = P_TimeNs();
|
||||
|
||||
u32 tid = sys_current_thread_id();
|
||||
u32 tid = P_GetThreadId();
|
||||
|
||||
struct log_level_settings settings = g_log_settings[level];
|
||||
P_LogLevelSettings settings = g_log_settings[level];
|
||||
String shorthand = settings.shorthand;
|
||||
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
@ -204,7 +204,7 @@ void _log(i32 level, String msg)
|
||||
|
||||
|
||||
/* Run callbacks */
|
||||
struct log_event event = ZI;
|
||||
P_LogEvent event = ZI;
|
||||
event.level = level;
|
||||
event.msg = msg;
|
||||
event.datetime = datetime;
|
||||
@ -214,7 +214,7 @@ void _log(i32 level, String msg)
|
||||
event.line = line;
|
||||
#endif
|
||||
{
|
||||
struct snc_lock lock = snc_lock_s(&ctx->callbacks_mutex);
|
||||
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) {
|
||||
__profn("Run log callback");
|
||||
@ -27,17 +27,19 @@
|
||||
* Callback interface
|
||||
* ========================== */
|
||||
|
||||
struct log_level_settings {
|
||||
typedef struct P_LogLevelSettings P_LogLevelSettings;
|
||||
struct P_LogLevelSettings {
|
||||
String shorthand;
|
||||
u32 color;
|
||||
};
|
||||
|
||||
struct log_event {
|
||||
typedef struct P_LogEvent P_LogEvent;
|
||||
struct P_LogEvent {
|
||||
/* Msg lifetime is only as long as callback duration */
|
||||
String msg;
|
||||
i32 level;
|
||||
|
||||
struct sys_datetime datetime;
|
||||
P_DateTime datetime;
|
||||
i64 time_ns;
|
||||
|
||||
/* These will be zeroed if LOG_INCLUDE_SOURCE_LOCATION is disabled */
|
||||
@ -45,7 +47,7 @@ struct log_event {
|
||||
i32 line;
|
||||
};
|
||||
|
||||
#define LOG_EVENT_CALLBACK_FUNC_DEF(name, log_event_arg) void name(struct log_event log_event_arg)
|
||||
#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);
|
||||
|
||||
void log_register_callback(log_event_callback_func *func, i32 level);
|
||||
@ -2,18 +2,18 @@ void sys_sleep_precise(i64 sleep_time_ns)
|
||||
{
|
||||
__prof;
|
||||
|
||||
i64 big_sleep = sys_current_scheduler_period_ns();
|
||||
i64 big_sleep = P_GetCurrentSchedulerPeriodNs();
|
||||
i64 tolerance = (f64)big_sleep * 0.5;
|
||||
//i64 tolerance = 1000000000;
|
||||
|
||||
i64 now_ns = sys_time_ns();
|
||||
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");
|
||||
sys_wait(0, 0, 0, big_sleep);
|
||||
now_ns = sys_time_ns();
|
||||
P_Wait(0, 0, 0, big_sleep);
|
||||
now_ns = P_TimeNs();
|
||||
}
|
||||
|
||||
/* Spin */
|
||||
@ -21,7 +21,7 @@ void sys_sleep_precise(i64 sleep_time_ns)
|
||||
__profn("Sleep spin");
|
||||
while (now_ns < target_ns) {
|
||||
ix_pause();
|
||||
now_ns = sys_time_ns();
|
||||
now_ns = P_TimeNs();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ void sys_sleep_precise(i64 sleep_time_ns)
|
||||
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 = sys_time_ns();
|
||||
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) {
|
||||
@ -4,7 +4,7 @@
|
||||
* Mutex
|
||||
* ========================== */
|
||||
|
||||
struct snc_lock snc_lock_spin_e(struct snc_mutex *m, i32 spin)
|
||||
P_Lock snc_lock_spin_e(P_Mutex *m, i32 spin)
|
||||
{
|
||||
b32 locked = 0;
|
||||
i32 spin_cnt = 0;
|
||||
@ -39,7 +39,7 @@ struct snc_lock snc_lock_spin_e(struct snc_mutex *m, i32 spin)
|
||||
if (spin_cnt < spin) {
|
||||
ix_pause();
|
||||
} else {
|
||||
sys_wait(&m->v, &v, 4, I64_MAX);
|
||||
P_Wait(&m->v, &v, 4, I64_MAX);
|
||||
spin_cnt = 0;
|
||||
}
|
||||
}
|
||||
@ -49,13 +49,13 @@ struct snc_lock snc_lock_spin_e(struct snc_mutex *m, i32 spin)
|
||||
atomic32_fetch_set(&m->exclusive_fiber_id, FiberId());
|
||||
#endif
|
||||
|
||||
struct snc_lock lock = ZI;
|
||||
P_Lock lock = ZI;
|
||||
lock.exclusive = 1;
|
||||
lock.mutex = m;
|
||||
return lock;
|
||||
}
|
||||
|
||||
struct snc_lock snc_lock_spin_s(struct snc_mutex *m, i32 spin)
|
||||
P_Lock snc_lock_spin_s(P_Mutex *m, i32 spin)
|
||||
{
|
||||
b32 locked = 0;
|
||||
i32 spin_cnt = 0;
|
||||
@ -76,29 +76,29 @@ struct snc_lock snc_lock_spin_s(struct snc_mutex *m, i32 spin)
|
||||
if (spin_cnt < spin) {
|
||||
ix_pause();
|
||||
} else {
|
||||
sys_wait(&m->v, &v, 4, I64_MAX);
|
||||
P_Wait(&m->v, &v, 4, I64_MAX);
|
||||
spin_cnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct snc_lock lock = ZI;
|
||||
P_Lock lock = ZI;
|
||||
lock.mutex = m;
|
||||
return lock;
|
||||
}
|
||||
|
||||
struct snc_lock snc_lock_e(struct snc_mutex *m)
|
||||
P_Lock snc_lock_e(P_Mutex *m)
|
||||
{
|
||||
return snc_lock_spin_e(m, DEFAULT_MUTEX_SPIN);
|
||||
}
|
||||
|
||||
struct snc_lock snc_lock_s(struct snc_mutex *m)
|
||||
P_Lock snc_lock_s(P_Mutex *m)
|
||||
{
|
||||
return snc_lock_spin_s(m, DEFAULT_MUTEX_SPIN);
|
||||
}
|
||||
|
||||
void snc_unlock(struct snc_lock *l)
|
||||
void snc_unlock(P_Lock *l)
|
||||
{
|
||||
struct snc_mutex *m = l->mutex;
|
||||
P_Mutex *m = l->mutex;
|
||||
if (l->exclusive) {
|
||||
#if RTC
|
||||
atomic32_fetch_set(&m->exclusive_fiber_id, 0);
|
||||
@ -107,7 +107,7 @@ void snc_unlock(struct snc_lock *l)
|
||||
} else {
|
||||
atomic32_fetch_add(&m->v, -1);
|
||||
}
|
||||
sys_wake(&m->v, I32_MAX);
|
||||
P_Wake(&m->v, I32_MAX);
|
||||
MEMZERO_STRUCT(l);
|
||||
}
|
||||
|
||||
@ -115,20 +115,20 @@ void snc_unlock(struct snc_lock *l)
|
||||
* Condition variable
|
||||
* ========================== */
|
||||
|
||||
void snc_cv_wait(struct snc_cv *cv, struct snc_lock *l)
|
||||
void snc_cv_wait(P_Cv *cv, P_Lock *l)
|
||||
{
|
||||
snc_cv_wait_time(cv, l, I64_MAX);
|
||||
}
|
||||
|
||||
void snc_cv_wait_time(struct snc_cv *cv, struct snc_lock *l, i64 timeout_ns)
|
||||
void snc_cv_wait_time(P_Cv *cv, P_Lock *l, i64 timeout_ns)
|
||||
{
|
||||
u64 old_wake_gen = atomic64_fetch(&cv->wake_gen);
|
||||
struct snc_mutex *mutex = l->mutex;
|
||||
P_Mutex *mutex = l->mutex;
|
||||
b32 exclusive = l->exclusive;
|
||||
{
|
||||
snc_unlock(l);
|
||||
{
|
||||
sys_wait(&cv->wake_gen, &old_wake_gen, sizeof(old_wake_gen), timeout_ns);
|
||||
P_Wait(&cv->wake_gen, &old_wake_gen, sizeof(old_wake_gen), timeout_ns);
|
||||
}
|
||||
if (exclusive) {
|
||||
*l = snc_lock_e(mutex);
|
||||
@ -138,30 +138,30 @@ void snc_cv_wait_time(struct snc_cv *cv, struct snc_lock *l, i64 timeout_ns)
|
||||
}
|
||||
}
|
||||
|
||||
void snc_cv_signal(struct snc_cv *cv, i32 count)
|
||||
void snc_cv_signal(P_Cv *cv, i32 count)
|
||||
{
|
||||
atomic64_fetch_add(&cv->wake_gen, 1);
|
||||
sys_wake(&cv->wake_gen, count);
|
||||
P_Wake(&cv->wake_gen, count);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Counter
|
||||
* ========================== */
|
||||
|
||||
void snc_counter_add(struct snc_counter *counter, i64 x)
|
||||
void snc_counter_add(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) {
|
||||
sys_wake(&counter->v, I32_MAX);
|
||||
P_Wake(&counter->v, I32_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void snc_counter_wait(struct snc_counter *counter)
|
||||
void snc_counter_wait(P_Counter *counter)
|
||||
{
|
||||
i64 v = atomic64_fetch(&counter->v);
|
||||
while (v > 0) {
|
||||
sys_wait(&counter->v, &v, sizeof(v), I64_MAX);
|
||||
P_Wait(&counter->v, &v, sizeof(v), I64_MAX);
|
||||
v = atomic64_fetch(&counter->v);
|
||||
}
|
||||
}
|
||||
72
src/platform/platform_snc.h
Normal file
72
src/platform/platform_snc.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* ========================== *
|
||||
* Mutex
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_Mutex P_Mutex;
|
||||
struct alignas(64) P_Mutex {
|
||||
/* Bit 31 = Exclusive lock is held
|
||||
* Bit 30 = Exclusive lock is pending
|
||||
* Bit 0-30 = Shared locks count
|
||||
*/
|
||||
Atomic32 v;
|
||||
|
||||
#if RTC
|
||||
Atomic32 exclusive_fiber_id;
|
||||
u8 _pad[56];
|
||||
#else
|
||||
u8 _pad[60];
|
||||
#endif
|
||||
};
|
||||
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 {
|
||||
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);
|
||||
|
||||
#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 {
|
||||
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
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_Counter P_Counter;
|
||||
struct alignas(64) P_Counter {
|
||||
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);
|
||||
File diff suppressed because it is too large
Load Diff
469
src/platform/platform_win32.h
Normal file
469
src/platform/platform_win32.h
Normal file
@ -0,0 +1,469 @@
|
||||
#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)
|
||||
|
||||
#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 {
|
||||
Atomic64Padded ticket;
|
||||
Atomic64Padded serving;
|
||||
};
|
||||
|
||||
void P_W32_LockTicketMutex(P_W32_TicketMutex *tm);
|
||||
|
||||
void P_W32_UnlockTicketMutex(P_W32_TicketMutex *tm);
|
||||
|
||||
/* ========================== *
|
||||
* Thread
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_Thread P_W32_Thread;
|
||||
struct P_W32_Thread {
|
||||
P_W32_ThreadFunc *entry_point;
|
||||
void *thread_data;
|
||||
char thread_name_cstr[256];
|
||||
wchar_t thread_name_wstr[256];
|
||||
i32 profiler_group;
|
||||
|
||||
P_W32_Thread *next;
|
||||
P_W32_Thread *prev;
|
||||
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
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
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_JobPool P_W32_JobPool;
|
||||
|
||||
typedef struct P_W32_WaitList P_W32_WaitList;
|
||||
struct alignas(64) P_W32_WaitList {
|
||||
u64 value;
|
||||
i16 first_waiter;
|
||||
i16 last_waiter;
|
||||
i32 num_waiters;
|
||||
P_W32_WaitList *next_in_bin;
|
||||
P_W32_WaitList *prev_in_bin;
|
||||
};
|
||||
STATIC_ASSERT(alignof(P_W32_WaitList) == 64); /* Avoid false sharing */
|
||||
|
||||
typedef struct P_W32_WaitBin P_W32_WaitBin;
|
||||
struct alignas(64) P_W32_WaitBin {
|
||||
P_W32_WaitList *first_wait_list;
|
||||
P_W32_WaitList *last_wait_list;
|
||||
P_W32_WaitList *first_free_wait_list;
|
||||
P_W32_TicketMutex lock;
|
||||
};
|
||||
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);
|
||||
|
||||
void P_W32_WakeByAddress(void *addr, i32 count);
|
||||
|
||||
void P_W32_WakeByTime(u64 time);
|
||||
|
||||
/* ========================== *
|
||||
* Fiber
|
||||
* ========================== */
|
||||
|
||||
typedef enum P_W32_YieldKind {
|
||||
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 {
|
||||
P_W32_YieldKind kind;
|
||||
union {
|
||||
struct {
|
||||
volatile void *addr;
|
||||
void *cmp;
|
||||
u32 size;
|
||||
i64 timeout_ns;
|
||||
} wait;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct P_W32_Fiber P_W32_Fiber;
|
||||
struct alignas(64) P_W32_Fiber {
|
||||
/* ---------------------------------------------------- */
|
||||
void *addr; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
char *name_cstr; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
Atomic32 wake_lock; /* 04 bytes (4 byte alignment) */
|
||||
i16 id; /* 02 bytes */
|
||||
i16 parent_id; /* 02 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
u64 wait_addr; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
u64 wait_time; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
i16 next_addr_waiter; /* 02 bytes */
|
||||
i16 prev_addr_waiter; /* 02 bytes */
|
||||
i16 next_time_waiter; /* 02 bytes */
|
||||
i16 prev_time_waiter; /* 02 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
u8 _pad1[8]; /* 08 bytes (padding) */
|
||||
/* ---------------------------------------------------- */
|
||||
u8 _pad2[8]; /* 08 bytes (padding) */
|
||||
/* ---------------------------------------------------- */
|
||||
/* -------------------- Cache line -------------------- */
|
||||
/* ---------------------------------------------------- */
|
||||
P_JobFunc *job_func; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
void *job_sig; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
i32 job_id; /* 04 bytes */
|
||||
i16 job_pool; /* 02 bytes */
|
||||
i16 job_priority; /* 02 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
P_Counter *job_counter; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
P_W32_YieldParam *yield_param; /* 08 bytes */
|
||||
/* ---------------------------------------------------- */
|
||||
u8 _pad3[24]; /* 24 bytes (padding) */
|
||||
|
||||
};
|
||||
STATIC_ASSERT(sizeof(P_W32_Fiber) == 128); /* Padding validation (increase if necessary) */
|
||||
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);
|
||||
|
||||
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 {
|
||||
P_Pool pool_kind;
|
||||
i32 id;
|
||||
};
|
||||
|
||||
typedef struct P_W32_JobInfo P_W32_JobInfo;
|
||||
struct P_W32_JobInfo {
|
||||
i32 num_dispatched;
|
||||
|
||||
i32 count;
|
||||
P_JobFunc *func;
|
||||
void *sig;
|
||||
P_Counter *counter;
|
||||
|
||||
i16 fiber_id; /* If the job is being resumed from a yield */
|
||||
|
||||
P_W32_JobInfo *next;
|
||||
};
|
||||
|
||||
typedef struct P_W32_JobQueue P_W32_JobQueue;
|
||||
struct alignas(64) P_W32_JobQueue {
|
||||
P_W32_TicketMutex lock;
|
||||
Arena *arena;
|
||||
|
||||
P_W32_JobInfo *first;
|
||||
P_W32_JobInfo *last;
|
||||
|
||||
P_W32_JobInfo *first_free;
|
||||
};
|
||||
|
||||
typedef struct P_W32_JobPool P_W32_JobPool;
|
||||
struct alignas(64) P_W32_JobPool {
|
||||
/* Jobs */
|
||||
P_W32_JobQueue job_queues[P_Priority_Count];
|
||||
|
||||
P_W32_TicketMutex free_fibers_lock;
|
||||
i16 first_free_fiber_id;
|
||||
|
||||
/* Workers */
|
||||
Atomic32Padded workers_shutdown;
|
||||
Atomic64Padded num_jobs_in_queue;
|
||||
P_W32_TicketMutex workers_wake_lock;
|
||||
|
||||
i32 num_worker_threads;
|
||||
i32 thread_priority;
|
||||
u64 thread_affinity_mask;
|
||||
b32 thread_is_audio;
|
||||
Arena *worker_threads_arena;
|
||||
P_W32_Thread **worker_threads;
|
||||
P_W32_WorkerCtx *worker_contexts;
|
||||
};
|
||||
|
||||
P_W32_ThreadDef(P_W32_JobWorkerEntryFunc, worker_ctx_arg);
|
||||
|
||||
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 {
|
||||
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 {
|
||||
u32 flags;
|
||||
|
||||
HWND hwnd;
|
||||
P_Counter ready_fence;
|
||||
|
||||
u16 utf16_high_surrogate_last_input;
|
||||
|
||||
P_Mutex settings_mutex;
|
||||
P_WindowSettings settings;
|
||||
|
||||
i32 monitor_width;
|
||||
i32 monitor_height;
|
||||
/* NOTE: width & height are unaffected by window minimization (they retain
|
||||
* their pre-minimized values) */
|
||||
i32 x, y, width, height;
|
||||
|
||||
/* FIXME: Use a cmd buffer for updating cursor (and maybe also settings).
|
||||
* Current setup means cursor_set calls can be applied out of order */
|
||||
u32 cursor_set_flags;
|
||||
V2 cursor_set_position;
|
||||
Rect cursor_clip_bounds;
|
||||
|
||||
Atomic32 topmost_toggles;
|
||||
b32 is_topmost;
|
||||
|
||||
P_Mutex event_arena_swp_mutex;
|
||||
i32 current_event_arena_index;
|
||||
Arena *event_arenas[2];
|
||||
|
||||
P_W32_Thread *window_thread;
|
||||
|
||||
Atomic32 shutdown;
|
||||
P_W32_Window *next_free;
|
||||
};
|
||||
|
||||
void P_W32_ProcessWindowEvent(P_W32_Window *window, P_WindowEvent event);
|
||||
|
||||
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 {
|
||||
HANDLE dir_handle;
|
||||
HANDLE wake_handle;
|
||||
P_W32_Watch *next_free;
|
||||
u8 results_buff[KIBI(64)];
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Address
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_Address P_W32_Address;
|
||||
struct P_W32_Address {
|
||||
i32 size;
|
||||
i32 family;
|
||||
union {
|
||||
struct sockaddr_storage sas;
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
};
|
||||
};
|
||||
|
||||
P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr);
|
||||
|
||||
/* 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 {
|
||||
SOCKET sock;
|
||||
P_W32_Sock *next_free;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Entry
|
||||
* ========================== */
|
||||
|
||||
|
||||
void P_W32_InitBtnTable(void);
|
||||
|
||||
P_JobDef(P_W32_AppStartupJob, _);
|
||||
|
||||
P_JobDef(P_W32_AppShutdownJob, _);
|
||||
|
||||
/* ========================== *
|
||||
* Global state
|
||||
* ========================== */
|
||||
|
||||
typedef struct P_W32_Ctx P_W32_Ctx;
|
||||
struct P_W32_Ctx {
|
||||
SYSTEM_INFO info;
|
||||
i64 timer_start_qpc;
|
||||
i64 ns_per_qpc;
|
||||
u32 main_thread_id;
|
||||
Atomic32 shutdown;
|
||||
|
||||
wchar_t cmdline_args_wstr[8192];
|
||||
|
||||
/* Application control flow */
|
||||
Atomic32 panicking;
|
||||
wchar_t panic_wstr[4096];
|
||||
HANDLE panic_event;
|
||||
HANDLE startup_end_event;
|
||||
HANDLE exit_begin_event;
|
||||
HANDLE exit_end_event;
|
||||
|
||||
/* Key lookup table */
|
||||
P_Btn vk_btn_table[256];
|
||||
|
||||
/* Threads 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 */
|
||||
P_Mutex watches_mutex;
|
||||
Arena *watches_arena;
|
||||
P_W32_Watch *watches_first_free;
|
||||
|
||||
/* Windows pool */
|
||||
WNDCLASSEXW window_class;
|
||||
P_Mutex windows_mutex;
|
||||
Arena *windows_arena;
|
||||
P_W32_Window *first_free_window;
|
||||
|
||||
/* Sockets pool */
|
||||
WSADATA wsa_data;
|
||||
Arena *socks_arena;
|
||||
P_Mutex socks_mutex;
|
||||
P_W32_Sock *first_free_sock;
|
||||
|
||||
/* Exit funcs */
|
||||
Atomic32 num_exit_funcs;
|
||||
P_ExitFunc *exit_funcs[P_W32_MaxOnExitFuncs];
|
||||
|
||||
/* Scheduler */
|
||||
Atomic64Padded current_scheduler_cycle;
|
||||
Atomic64Padded current_scheduler_cycle_period_ns;
|
||||
|
||||
/* Fibers */
|
||||
P_W32_TicketMutex fibers_lock;
|
||||
i16 num_fibers;
|
||||
Arena *fiber_names_arena;
|
||||
P_W32_Fiber fibers[MAX_FIBERS];
|
||||
|
||||
/* Wait lists */
|
||||
Atomic64Padded waiter_wake_gen;
|
||||
P_W32_TicketMutex wait_lists_arena_lock;
|
||||
Arena *wait_lists_arena;
|
||||
|
||||
/* Wait tables */
|
||||
P_W32_WaitBin wait_addr_bins[P_W32_NumWaitAddrBins];
|
||||
P_W32_WaitBin wait_time_bins[P_W32_NumWaitTimeBins];
|
||||
|
||||
/* Job pools */
|
||||
P_W32_JobPool job_pools[P_Pool_Count];
|
||||
};
|
||||
|
||||
extern P_W32_Ctx P_W32_g_shared_ctx;
|
||||
@ -2,7 +2,7 @@
|
||||
#define PLAYBACK_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../mixer/mixer.h"
|
||||
|
||||
#include "playback_core.h"
|
||||
|
||||
@ -8,10 +8,6 @@
|
||||
#define COBJMACROS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define UNICODE
|
||||
#define WINVER 0x0A00
|
||||
#define _WIN32_WINNT 0x0A00
|
||||
#define NTDDI_WIN11_DT 0x0C0A0000
|
||||
#define NTDDI_VERSION 0x0A000000
|
||||
#include <Windows.h>
|
||||
#include <initguid.h>
|
||||
#include <objbase.h>
|
||||
@ -39,7 +35,7 @@ GLOBAL struct {
|
||||
IAudioRenderClient *playback;
|
||||
WAVEFORMATEX *buffer_format;
|
||||
u32 buffer_frames;
|
||||
struct snc_counter playback_job_counter;
|
||||
P_Counter playback_job_counter;
|
||||
} G = ZI, DEBUG_ALIAS(G, G_playback_wasapi);
|
||||
|
||||
/* ========================== *
|
||||
@ -47,8 +43,8 @@ GLOBAL struct {
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void wasapi_initialize(void);
|
||||
INTERNAL SYS_EXIT_FUNC(playback_shutdown);
|
||||
INTERNAL SYS_JOB_DEF(playback_job, _);
|
||||
INTERNAL P_ExitFuncDef(playback_shutdown);
|
||||
INTERNAL P_JobDef(playback_job, _);
|
||||
|
||||
PB_StartupReceipt playback_startup(M_StartupReceipt *mixer_sr)
|
||||
{
|
||||
@ -56,13 +52,13 @@ PB_StartupReceipt playback_startup(M_StartupReceipt *mixer_sr)
|
||||
(UNUSED)mixer_sr;
|
||||
wasapi_initialize();
|
||||
/* Start playback job */
|
||||
sys_run(1, playback_job, 0, SYS_POOL_AUDIO, SYS_PRIORITY_HIGH, &G.playback_job_counter);
|
||||
sys_on_exit(&playback_shutdown);
|
||||
P_Run(1, playback_job, 0, P_Pool_Audio, P_Priority_High, &G.playback_job_counter);
|
||||
P_OnExit(&playback_shutdown);
|
||||
|
||||
return (PB_StartupReceipt) { 0 };
|
||||
}
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(playback_shutdown)
|
||||
INTERNAL P_ExitFuncDef(playback_shutdown)
|
||||
{
|
||||
__prof;
|
||||
atomic32_fetch_set(&G.shutdown, 1);
|
||||
@ -219,7 +215,7 @@ INTERNAL void wasapi_update_end(struct wasapi_buffer *wspbuf, M_PcmF32 src)
|
||||
* Playback thread entry
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(playback_job, _)
|
||||
INTERNAL P_JobDef(playback_job, _)
|
||||
{
|
||||
__prof;
|
||||
(UNUSED)_;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define RESOURCE_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../tar/tar.h"
|
||||
|
||||
#if RESOURCES_EMBEDDED
|
||||
|
||||
@ -24,13 +24,13 @@ R_StartupReceipt resource_startup(void)
|
||||
#if RESOURCES_EMBEDDED
|
||||
String embedded_data = inc_res_tar();
|
||||
if (embedded_data.len <= 0) {
|
||||
sys_panic(LIT("No embedded resources found"));
|
||||
P_Panic(LIT("No embedded resources found"));
|
||||
}
|
||||
G.archive = tar_parse(G.arena, embedded_data, LIT(""));
|
||||
#else
|
||||
/* Ensure we have the right working directory */
|
||||
if (!sys_is_dir(LIT("res"))) {
|
||||
sys_panic(LIT("Resource directory \"res\" not found. Make sure the executable is being launched from the correct working directory."));
|
||||
if (!P_IsDir(LIT("res"))) {
|
||||
P_Panic(LIT("Resource directory \"res\" not found. Make sure the executable is being launched from the correct working directory."));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -67,18 +67,18 @@ R_Resource resource_open(String name)
|
||||
path = STRING(path_text_len, path_text);
|
||||
}
|
||||
|
||||
struct sys_file file = sys_file_open_read_wait(path);
|
||||
struct sys_file_map file_map = ZI;
|
||||
P_File file = P_OpenFileReadWait(path);
|
||||
P_FileMap file_map = ZI;
|
||||
String data = ZI;
|
||||
if (file.valid) {
|
||||
file_map = sys_file_map_open_read(file);
|
||||
file_map = P_OpenFileMap(file);
|
||||
if (file_map.valid) {
|
||||
data = sys_file_map_data(file_map);
|
||||
data = P_GetFileMapData(file_map);
|
||||
} else {
|
||||
sys_file_map_close(file_map);
|
||||
P_CloseFileMap(file_map);
|
||||
}
|
||||
} else {
|
||||
sys_file_close(file);
|
||||
P_CloseFIle(file);
|
||||
}
|
||||
|
||||
res._exists = file.valid && file_map.valid;
|
||||
@ -97,7 +97,7 @@ R_Resource resource_open(String name)
|
||||
#if !RESOURCES_EMBEDDED
|
||||
void resource_close(R_Resource *res_ptr)
|
||||
{
|
||||
sys_file_map_close(res_ptr->_file_map);
|
||||
sys_file_close(res_ptr->_file);
|
||||
P_CloseFileMap(res_ptr->_file_map);
|
||||
P_CloseFIle(res_ptr->_file);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -10,8 +10,8 @@ struct R_Resource {
|
||||
#if RESOURCES_EMBEDDED
|
||||
String _name;
|
||||
#else
|
||||
struct sys_file _file;
|
||||
struct sys_file_map _file_map;
|
||||
P_File _file;
|
||||
P_FileMap _file_map;
|
||||
u8 _name_text[RESOURCE_NAME_LEN_MAX];
|
||||
u8 _name_len;
|
||||
#endif
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define SETTINGS_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../json/json.h"
|
||||
|
||||
#include "settings_core.h"
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
String settings_serialize(Arena *arena, const struct sys_window_settings *settings)
|
||||
String settings_serialize(Arena *arena, const P_WindowSettings *settings)
|
||||
{
|
||||
__prof;
|
||||
|
||||
String minimized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MINIMIZED ? LIT("true") : LIT("false");
|
||||
String maximized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED ? LIT("true") : LIT("false");
|
||||
String fullscreen = settings->flags & SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN ? LIT("true") : LIT("false");
|
||||
String minimized = settings->flags & P_WindowSettingsFlag_Minimized ? LIT("true") : LIT("false");
|
||||
String maximized = settings->flags & P_WindowSettingsFlag_Maximized ? LIT("true") : LIT("false");
|
||||
String fullscreen = settings->flags & P_WindowSettingsFlag_Fullscreen ? LIT("true") : LIT("false");
|
||||
i32 x = settings->floating_x;
|
||||
i32 y = settings->floating_y;
|
||||
i32 width = settings->floating_width;
|
||||
@ -37,7 +37,7 @@ String settings_serialize(Arena *arena, const struct sys_window_settings *settin
|
||||
return formatted;
|
||||
}
|
||||
|
||||
struct sys_window_settings *settings_deserialize(Arena *arena, String src, String *error_out)
|
||||
P_WindowSettings *settings_deserialize(Arena *arena, String src, String *error_out)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin(arena);
|
||||
@ -45,7 +45,7 @@ struct sys_window_settings *settings_deserialize(Arena *arena, String src, Strin
|
||||
String error = ZI;
|
||||
JSON_Error json_error = ZI;
|
||||
|
||||
struct sys_window_settings *settings = arena_push(arena, struct sys_window_settings);
|
||||
P_WindowSettings *settings = arena_push(arena, P_WindowSettings);
|
||||
JSON_Result parse_res = json_from_string(scratch.arena, src);
|
||||
|
||||
if (parse_res.errors.count > 0) {
|
||||
@ -80,7 +80,7 @@ struct sys_window_settings *settings_deserialize(Arena *arena, String src, Strin
|
||||
goto abort;
|
||||
}
|
||||
if (child->value.boolean) {
|
||||
settings->flags |= SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED;
|
||||
settings->flags |= P_WindowSettingsFlag_Maximized;
|
||||
}
|
||||
found_maximized = 1;
|
||||
} else if (string_eq(key, LIT("fullscreen"))) {
|
||||
@ -89,7 +89,7 @@ struct sys_window_settings *settings_deserialize(Arena *arena, String src, Strin
|
||||
goto abort;
|
||||
}
|
||||
if (child->value.boolean) {
|
||||
settings->flags |= SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN;
|
||||
settings->flags |= P_WindowSettingsFlag_Fullscreen;
|
||||
}
|
||||
found_fullscreen = 1;
|
||||
} else if (string_eq(key, LIT("x"))) {
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
String settings_serialize(Arena *arena, const struct sys_window_settings *settings);
|
||||
String settings_serialize(Arena *arena, const P_WindowSettings *settings);
|
||||
|
||||
struct sys_window_settings *settings_deserialize(Arena *arena, String src, String *error_out);
|
||||
P_WindowSettings *settings_deserialize(Arena *arena, String src, String *error_out);
|
||||
|
||||
@ -34,40 +34,40 @@
|
||||
|
||||
GLOBAL struct {
|
||||
Arena *nil_arena;
|
||||
struct sim_client_store *nil_client_store;
|
||||
struct sim_client *nil_client;
|
||||
struct sim_snapshot *nil_snapshot;
|
||||
ClientStore *nil_client_store;
|
||||
Client *nil_client;
|
||||
Snapshot *nil_snapshot;
|
||||
struct sim_ent *nil_ent;
|
||||
} G = ZI, DEBUG_ALIAS(G, G_sim);
|
||||
|
||||
/* Accessed via `sim_client_store_nil()` */
|
||||
READONLY struct sim_client_store **_g_sim_client_store_nil = &G.nil_client_store;
|
||||
READONLY ClientStore **_g_sim_client_store_nil = &G.nil_client_store;
|
||||
|
||||
/* Accessed via `sim_client_nil()` */
|
||||
READONLY struct sim_client **_g_sim_client_nil = &G.nil_client;
|
||||
READONLY Client **_g_sim_client_nil = &G.nil_client;
|
||||
|
||||
/* Accessed via `sim_snapshot_nil()` */
|
||||
READONLY struct sim_snapshot **_g_sim_snapshot_nil = &G.nil_snapshot;
|
||||
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;
|
||||
|
||||
struct sim_startup_receipt sim_startup(void)
|
||||
SimStartupReceipt sim_startup(void)
|
||||
{
|
||||
__prof;
|
||||
G.nil_arena = arena_alloc(GIBI(1));
|
||||
|
||||
/* Nil client store */
|
||||
G.nil_client_store = arena_push(G.nil_arena, struct sim_client_store);
|
||||
G.nil_client_store = arena_push(G.nil_arena, ClientStore);
|
||||
G.nil_client_store->valid = 0;
|
||||
|
||||
/* Nil client */
|
||||
G.nil_client = arena_push(G.nil_arena, struct sim_client);
|
||||
G.nil_client = arena_push(G.nil_arena, Client);
|
||||
G.nil_client->valid = 0;
|
||||
G.nil_client->store = sim_client_store_nil();
|
||||
|
||||
/* Nil snapshot */
|
||||
G.nil_snapshot = arena_push(G.nil_arena, struct sim_snapshot);
|
||||
G.nil_snapshot = arena_push(G.nil_arena, Snapshot);
|
||||
G.nil_snapshot->valid = 0;
|
||||
G.nil_snapshot->client = sim_client_nil();
|
||||
|
||||
@ -87,35 +87,35 @@ struct sim_startup_receipt sim_startup(void)
|
||||
|
||||
/* Lock nil arena */
|
||||
arena_set_readonly(G.nil_arena);
|
||||
return (struct sim_startup_receipt) { 0 };
|
||||
return (SimStartupReceipt) { 0 };
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Client store alloc
|
||||
* ========================== */
|
||||
|
||||
struct sim_client_store *sim_client_store_alloc(void)
|
||||
ClientStore *sim_client_store_alloc(void)
|
||||
{
|
||||
__prof;
|
||||
struct sim_client_store *store;
|
||||
ClientStore *store;
|
||||
{
|
||||
Arena *arena = arena_alloc(GIBI(64));
|
||||
store = arena_push(arena, struct sim_client_store);
|
||||
store = arena_push(arena, ClientStore);
|
||||
store->arena = arena;
|
||||
}
|
||||
store->valid = 1;
|
||||
store->num_client_lookup_bins = CLIENT_LOOKUP_BINS;
|
||||
store->client_lookup_bins = arena_push_array(store->arena, struct sim_client_lookup_bin, store->num_client_lookup_bins);
|
||||
store->client_lookup_bins = arena_push_array(store->arena, ClientLookupBin, store->num_client_lookup_bins);
|
||||
store->clients_arena = arena_alloc(GIBI(64));
|
||||
store->clients = arena_push_dry(store->clients_arena, struct sim_client);
|
||||
store->clients = arena_push_dry(store->clients_arena, Client);
|
||||
return store;
|
||||
}
|
||||
|
||||
void sim_client_store_release(struct sim_client_store *store)
|
||||
void sim_client_store_release(ClientStore *store)
|
||||
{
|
||||
__prof;
|
||||
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
|
||||
struct sim_client *client = &store->clients[i];
|
||||
Client *client = &store->clients[i];
|
||||
if (client->valid) {
|
||||
sim_client_release(client);
|
||||
}
|
||||
@ -128,17 +128,17 @@ void sim_client_store_release(struct sim_client_store *store)
|
||||
* Client alloc
|
||||
* ========================== */
|
||||
|
||||
struct sim_client *sim_client_alloc(struct sim_client_store *store)
|
||||
Client *sim_client_alloc(ClientStore *store)
|
||||
{
|
||||
struct sim_client_handle handle = ZI;
|
||||
struct sim_client *client = sim_client_from_handle(store, store->first_free_client);
|
||||
ClientHandle handle = ZI;
|
||||
Client *client = sim_client_from_handle(store, store->first_free_client);
|
||||
|
||||
if (client->valid) {
|
||||
store->first_free_client = client->next_free;
|
||||
handle = client->handle;
|
||||
++handle.gen;
|
||||
} else {
|
||||
client = arena_push_no_zero(store->clients_arena, struct sim_client);
|
||||
client = arena_push_no_zero(store->clients_arena, Client);
|
||||
handle.gen = 1;
|
||||
handle.idx = store->num_clients_reserved;
|
||||
++store->num_clients_reserved;
|
||||
@ -151,19 +151,19 @@ struct sim_client *sim_client_alloc(struct sim_client_store *store)
|
||||
|
||||
client->snapshots_arena = arena_alloc(GIBI(8));
|
||||
client->num_snapshot_lookup_bins = TICK_LOOKUP_BINS;
|
||||
client->snapshot_lookup_bins = arena_push_array(client->snapshots_arena, struct sim_snapshot_lookup_bin, client->num_snapshot_lookup_bins);
|
||||
client->snapshot_lookup_bins = arena_push_array(client->snapshots_arena, SnapshotLookupBin, client->num_snapshot_lookup_bins);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void sim_client_release(struct sim_client *client)
|
||||
void sim_client_release(Client *client)
|
||||
{
|
||||
/* Release internal snapshot memory */
|
||||
for (u64 i = 0; i < client->num_snapshot_lookup_bins; ++i) {
|
||||
struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[i];
|
||||
struct sim_snapshot *ss = bin->first;
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[i];
|
||||
Snapshot *ss = bin->first;
|
||||
while (ss) {
|
||||
struct sim_snapshot *next = ss->next_in_bin;
|
||||
Snapshot *next = ss->next_in_bin;
|
||||
arena_release(ss->ents_arena);
|
||||
arena_release(ss->arena);
|
||||
ss = next;
|
||||
@ -174,7 +174,7 @@ void sim_client_release(struct sim_client *client)
|
||||
sim_client_set_channel_id(client, HOST_CHANNEL_ID_NIL);
|
||||
|
||||
/* Release client */
|
||||
struct sim_client_store *store = client->store;
|
||||
ClientStore *store = client->store;
|
||||
client->valid = 0;
|
||||
client->next_free = store->first_free_client;
|
||||
store->first_free_client = client->handle;
|
||||
@ -192,17 +192,17 @@ INTERNAL u64 hash_from_channel_id(N_ChannelId channel_id)
|
||||
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&channel_id));
|
||||
}
|
||||
|
||||
void sim_client_set_channel_id(struct sim_client *client, N_ChannelId channel_id)
|
||||
void sim_client_set_channel_id(Client *client, N_ChannelId channel_id)
|
||||
{
|
||||
struct sim_client_store *store = client->store;
|
||||
ClientStore *store = client->store;
|
||||
N_ChannelId old_channel_id = client->channel_id;
|
||||
|
||||
/* Remove old channel id from channel lookup */
|
||||
if (!host_channel_id_is_nil(old_channel_id)) {
|
||||
u64 bin_index = client->channel_hash % store->num_client_lookup_bins;
|
||||
struct sim_client_lookup_bin *bin = &store->client_lookup_bins[bin_index];
|
||||
struct sim_client *prev = sim_client_from_handle(store, client->prev_in_bin);
|
||||
struct sim_client *next = sim_client_from_handle(store, client->next_in_bin);
|
||||
ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
Client *prev = sim_client_from_handle(store, client->prev_in_bin);
|
||||
Client *next = sim_client_from_handle(store, client->next_in_bin);
|
||||
if (prev->valid) {
|
||||
prev->next_in_bin = next->handle;
|
||||
} else {
|
||||
@ -222,9 +222,9 @@ void sim_client_set_channel_id(struct sim_client *client, N_ChannelId channel_id
|
||||
client->channel_hash = channel_hash;
|
||||
if (!host_channel_id_is_nil(channel_id)) {
|
||||
u64 bin_index = channel_hash % store->num_client_lookup_bins;
|
||||
struct sim_client_lookup_bin *bin = &store->client_lookup_bins[bin_index];
|
||||
ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
{
|
||||
struct sim_client *prev_in_bin = sim_client_from_handle(store, bin->last);
|
||||
Client *prev_in_bin = sim_client_from_handle(store, bin->last);
|
||||
if (prev_in_bin->valid) {
|
||||
prev_in_bin->next_in_bin = client->handle;
|
||||
client->prev_in_bin = prev_in_bin->handle;
|
||||
@ -236,13 +236,13 @@ void sim_client_set_channel_id(struct sim_client *client, N_ChannelId channel_id
|
||||
}
|
||||
}
|
||||
|
||||
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, N_ChannelId channel_id)
|
||||
Client *sim_client_from_channel_id(ClientStore *store, N_ChannelId channel_id)
|
||||
{
|
||||
struct sim_client *res = sim_client_nil();
|
||||
Client *res = sim_client_nil();
|
||||
u64 channel_hash = hash_from_channel_id(channel_id);
|
||||
u64 bin_index = channel_hash % store->num_client_lookup_bins;
|
||||
struct sim_client_lookup_bin *bin = &store->client_lookup_bins[bin_index];
|
||||
for (struct sim_client *client = sim_client_from_handle(store, bin->first); client->valid; client = sim_client_from_handle(store, client->next_in_bin)) {
|
||||
ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
for (Client *client = sim_client_from_handle(store, bin->first); client->valid; client = sim_client_from_handle(store, client->next_in_bin)) {
|
||||
if (client->channel_hash == channel_hash) {
|
||||
res = client;
|
||||
break;
|
||||
@ -251,10 +251,10 @@ struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, N_
|
||||
return res;
|
||||
}
|
||||
|
||||
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct sim_client_handle handle)
|
||||
Client *sim_client_from_handle(ClientStore *store, ClientHandle handle)
|
||||
{
|
||||
if (handle.gen != 0 && handle.idx < store->num_clients_reserved) {
|
||||
struct sim_client *client = &store->clients[handle.idx];
|
||||
Client *client = &store->clients[handle.idx];
|
||||
if (client->handle.gen == handle.gen) {
|
||||
return client;
|
||||
}
|
||||
@ -267,13 +267,13 @@ struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct
|
||||
* ========================== */
|
||||
|
||||
/* Produces a new snapshot at `tick` with data copied from `src` snapshot. */
|
||||
struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_snapshot *src, u64 tick)
|
||||
Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick)
|
||||
{
|
||||
if (tick == 0) {
|
||||
return sim_snapshot_nil();
|
||||
}
|
||||
|
||||
struct sim_snapshot *ss;
|
||||
Snapshot *ss;
|
||||
{
|
||||
Arena *arena = ZI;
|
||||
Arena *ents_arena = 0;
|
||||
@ -291,7 +291,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
||||
}
|
||||
}
|
||||
arena_reset(arena);
|
||||
ss = arena_push(arena, struct sim_snapshot);
|
||||
ss = arena_push(arena, Snapshot);
|
||||
ss->arena = arena;
|
||||
|
||||
ss->ents_arena = ents_arena;
|
||||
@ -360,7 +360,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
||||
|
||||
/* Release duplicate tick if it exists */
|
||||
{
|
||||
struct sim_snapshot *existing = sim_snapshot_from_tick(client, tick);
|
||||
Snapshot *existing = sim_snapshot_from_tick(client, tick);
|
||||
if (existing->valid) {
|
||||
sim_snapshot_release(existing);
|
||||
}
|
||||
@ -368,7 +368,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
||||
|
||||
/* Linear search to insert snapshot in tick order */
|
||||
{
|
||||
struct sim_snapshot *prev = sim_snapshot_from_tick(client, client->last_tick);
|
||||
Snapshot *prev = sim_snapshot_from_tick(client, client->last_tick);
|
||||
while (prev->valid) {
|
||||
if (prev->tick < tick) {
|
||||
break;
|
||||
@ -376,7 +376,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
||||
prev = sim_snapshot_from_tick(client, prev->prev_tick);
|
||||
}
|
||||
if (prev->valid) {
|
||||
struct sim_snapshot *next = sim_snapshot_from_tick(client, prev->next_tick);
|
||||
Snapshot *next = sim_snapshot_from_tick(client, prev->next_tick);
|
||||
if (next->valid) {
|
||||
next->prev_tick = tick;
|
||||
} else {
|
||||
@ -386,7 +386,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
||||
ss->prev_tick = prev->tick;
|
||||
prev->next_tick = ss->tick;
|
||||
} else {
|
||||
struct sim_snapshot *first = sim_snapshot_from_tick(client, client->first_tick);
|
||||
Snapshot *first = sim_snapshot_from_tick(client, client->first_tick);
|
||||
if (first->valid) {
|
||||
ss->next_tick = first->tick;
|
||||
first->prev_tick = tick;
|
||||
@ -401,7 +401,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
||||
/* Insert into lookup */
|
||||
{
|
||||
u64 bin_index = tick % client->num_snapshot_lookup_bins;
|
||||
struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
if (bin->last) {
|
||||
bin->last->next_in_bin = ss;
|
||||
ss->prev_in_bin = bin->last;
|
||||
@ -414,16 +414,16 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
||||
return ss;
|
||||
}
|
||||
|
||||
void sim_snapshot_release(struct sim_snapshot *ss)
|
||||
void sim_snapshot_release(Snapshot *ss)
|
||||
{
|
||||
struct sim_client *client = ss->client;
|
||||
Client *client = ss->client;
|
||||
|
||||
/* Remove from lookup */
|
||||
{
|
||||
u64 bin_index = ss->tick % client->num_snapshot_lookup_bins;
|
||||
struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
struct sim_snapshot *prev = ss->prev_in_bin;
|
||||
struct sim_snapshot *next = ss->next_in_bin;
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
Snapshot *prev = ss->prev_in_bin;
|
||||
Snapshot *next = ss->next_in_bin;
|
||||
if (prev) {
|
||||
prev->next_in_bin = next;
|
||||
} else {
|
||||
@ -438,8 +438,8 @@ void sim_snapshot_release(struct sim_snapshot *ss)
|
||||
|
||||
/* Remove from snapshot list */
|
||||
{
|
||||
struct sim_snapshot *prev = sim_snapshot_from_tick(client, ss->prev_tick);
|
||||
struct sim_snapshot *next = sim_snapshot_from_tick(client, ss->next_tick);
|
||||
Snapshot *prev = sim_snapshot_from_tick(client, ss->prev_tick);
|
||||
Snapshot *next = sim_snapshot_from_tick(client, ss->next_tick);
|
||||
if (prev->valid) {
|
||||
prev->next_tick = next->tick;
|
||||
} else {
|
||||
@ -459,7 +459,7 @@ void sim_snapshot_release(struct sim_snapshot *ss)
|
||||
}
|
||||
|
||||
/* Release all snapshots for client with tick in range [start, end] */
|
||||
void sim_snapshot_release_ticks_in_range(struct sim_client *client, u64 start, u64 end)
|
||||
void sim_snapshot_release_ticks_in_range(Client *client, u64 start, u64 end)
|
||||
{
|
||||
if (start > end) {
|
||||
u64 swp = start;
|
||||
@ -467,7 +467,7 @@ void sim_snapshot_release_ticks_in_range(struct sim_client *client, u64 start, u
|
||||
end = swp;
|
||||
}
|
||||
|
||||
struct sim_snapshot *ss = sim_snapshot_from_tick(client, client->first_tick);
|
||||
Snapshot *ss = sim_snapshot_from_tick(client, client->first_tick);
|
||||
while (ss->valid) {
|
||||
u64 tick = ss->tick;
|
||||
u64 next_tick = ss->next_tick;
|
||||
@ -486,13 +486,13 @@ void sim_snapshot_release_ticks_in_range(struct sim_client *client, u64 start, u
|
||||
* Snapshot lookup
|
||||
* ========================== */
|
||||
|
||||
struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick)
|
||||
Snapshot *sim_snapshot_from_tick(Client *client, u64 tick)
|
||||
{
|
||||
struct sim_snapshot *ss = sim_snapshot_nil();
|
||||
Snapshot *ss = sim_snapshot_nil();
|
||||
if (tick > 0) {
|
||||
u64 bin_index = tick % client->num_snapshot_lookup_bins;
|
||||
struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
for (struct sim_snapshot *search = bin->first; search; search = search->next_in_bin) {
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
for (Snapshot *search = bin->first; search; search = search->next_in_bin) {
|
||||
if (search->tick == tick) {
|
||||
ss = search;
|
||||
break;
|
||||
@ -503,9 +503,9 @@ struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick)
|
||||
}
|
||||
|
||||
/* Returns the snapshot at nearest valid tick <= supplied tick */
|
||||
struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *client, u64 tick)
|
||||
Snapshot *sim_snapshot_from_closest_tick_lte(Client *client, u64 tick)
|
||||
{
|
||||
struct sim_snapshot *ss = sim_snapshot_from_tick(client, tick);
|
||||
Snapshot *ss = sim_snapshot_from_tick(client, tick);
|
||||
if (!ss->valid) {
|
||||
/* Degenerate to linear search */
|
||||
ss = sim_snapshot_from_tick(client, client->last_tick);
|
||||
@ -520,9 +520,9 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *clien
|
||||
}
|
||||
|
||||
/* Returns the snapshot at nearest valid tick >= supplied tick */
|
||||
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick)
|
||||
Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick)
|
||||
{
|
||||
struct sim_snapshot *ss = sim_snapshot_from_tick(client, tick);
|
||||
Snapshot *ss = sim_snapshot_from_tick(client, tick);
|
||||
if (!ss->valid) {
|
||||
/* Degenerate to linear search */
|
||||
ss = sim_snapshot_from_tick(client, client->first_tick);
|
||||
@ -589,11 +589,11 @@ V2i32 sim_tile_chunk_index_from_world_tile_index(V2i32 world_tile_index)
|
||||
return res;
|
||||
}
|
||||
|
||||
void sim_snapshot_set_tile(struct sim_snapshot *ss, V2i32 world_tile_index, enum sim_tile_kind tile_kind)
|
||||
void sim_snapshot_set_tile(Snapshot *ss, V2i32 world_tile_index, TileKind tile_kind)
|
||||
{
|
||||
V2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
||||
|
||||
struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(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);
|
||||
if (!chunk_ent->valid) {
|
||||
struct sim_ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
@ -610,14 +610,14 @@ void sim_snapshot_set_tile(struct sim_snapshot *ss, V2i32 world_tile_index, enum
|
||||
* Snapshot lerp
|
||||
* ========================== */
|
||||
|
||||
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend)
|
||||
Snapshot *sim_snapshot_alloc_from_lerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend)
|
||||
{
|
||||
__prof;
|
||||
|
||||
/* New snapshot will be allocated with same tick as ss0 or ss1, so the result should go into a different client */
|
||||
ASSERT(ss0->client != client && ss1->client != client);
|
||||
|
||||
struct sim_snapshot *ss;
|
||||
Snapshot *ss;
|
||||
b32 should_blend = 1;
|
||||
if (ss0->continuity_gen == ss1->continuity_gen && 0 < blend && blend < 1) {
|
||||
ss = sim_snapshot_alloc(client, ss0, ss0->tick);
|
||||
@ -661,7 +661,7 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str
|
||||
* ========================== */
|
||||
|
||||
/* Syncs entity data between snapshots */
|
||||
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_id remote_player, u32 sync_flags)
|
||||
void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntId remote_player, u32 sync_flags)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -720,7 +720,7 @@ void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *
|
||||
* Snapshot encode
|
||||
* ========================== */
|
||||
|
||||
void sim_snapshot_encode(BitbuffWriter *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
|
||||
void sim_snapshot_encode(BitbuffWriter *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -789,7 +789,7 @@ void sim_snapshot_encode(BitbuffWriter *bw, struct sim_client *receiver, struct
|
||||
* Snapshot decode
|
||||
* ========================== */
|
||||
|
||||
void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||
void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -801,7 +801,7 @@ void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||
ss->continuity_gen = br_read_uv(br);
|
||||
ss->phys_iteration = br_read_uv(br);
|
||||
|
||||
ss->local_player = (struct sim_ent_id) { .uid = br_read_uid(br) };
|
||||
ss->local_player = (EntId) { .uid = br_read_uid(br) };
|
||||
|
||||
/* Id bins */
|
||||
/* TODO: Don't decode these, determine them implicitly from decoded ents */
|
||||
@ -869,7 +869,7 @@ void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||
* Snapshot encode
|
||||
* ========================== */
|
||||
|
||||
void sim_snapshot_encode(BitbuffWriter *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
|
||||
void sim_snapshot_encode(BitbuffWriter *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -936,7 +936,7 @@ struct sim_ent_decode_queue {
|
||||
struct sim_ent_decode_node *last;
|
||||
};
|
||||
|
||||
void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||
void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -947,7 +947,7 @@ void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||
ss->continuity_gen = br_read_uv(br);
|
||||
ss->phys_iteration = br_read_uv(br);
|
||||
|
||||
ss->local_player = (struct sim_ent_id) { .uid = br_read_uid(br) };
|
||||
ss->local_player = (EntId) { .uid = br_read_uid(br) };
|
||||
|
||||
#if 1
|
||||
|
||||
@ -978,7 +978,7 @@ void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||
b32 released = 0;
|
||||
|
||||
u32 alloc_parent_index = ZI;
|
||||
struct sim_ent_id alloc_ent_id = ZI;
|
||||
EntId alloc_ent_id = ZI;
|
||||
if (allocation_changed) {
|
||||
released = br_read_bit(br);
|
||||
if (released) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#define SIM_CLIENT_NIL_HANDLE ((struct sim_client_handle) { .gen = 0, .idx = 0 })
|
||||
#define SIM_CLIENT_NIL_HANDLE ((ClientHandle) { .gen = 0, .idx = 0 })
|
||||
|
||||
/* Absolute layers */
|
||||
#define SIM_LAYER_FLOOR_DECALS (-300)
|
||||
@ -11,11 +11,13 @@
|
||||
#define SIM_LAYER_RELATIVE_DEFAULT (0)
|
||||
#define SIM_LAYER_RELATIVE_WEAPON (1)
|
||||
|
||||
struct sim_ent_id {
|
||||
typedef struct EntId EntId;
|
||||
struct EntId {
|
||||
UID uid;
|
||||
};
|
||||
|
||||
struct sim_client_handle {
|
||||
typedef struct ClientHandle ClientHandle;
|
||||
struct ClientHandle {
|
||||
u32 idx;
|
||||
u32 gen;
|
||||
};
|
||||
@ -24,58 +26,63 @@ struct sim_client_handle {
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
struct sim_startup_receipt { i32 _; };
|
||||
struct sim_startup_receipt sim_startup(void);
|
||||
typedef struct SimStartupReceipt SimStartupReceipt;
|
||||
struct SimStartupReceipt { i32 _; };
|
||||
SimStartupReceipt sim_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
* Client store
|
||||
* ========================== */
|
||||
|
||||
struct sim_client_lookup_bin {
|
||||
struct sim_client_handle first;
|
||||
struct sim_client_handle last;
|
||||
typedef struct ClientLookupBin ClientLookupBin;
|
||||
struct ClientLookupBin {
|
||||
ClientHandle first;
|
||||
ClientHandle last;
|
||||
};
|
||||
|
||||
struct sim_client_store {
|
||||
typedef struct Client Client;
|
||||
typedef struct ClientStore ClientStore;
|
||||
struct ClientStore {
|
||||
b32 valid;
|
||||
Arena *arena;
|
||||
|
||||
/* Client lookup */
|
||||
struct sim_client_lookup_bin *client_lookup_bins;
|
||||
ClientLookupBin *client_lookup_bins;
|
||||
u64 num_client_lookup_bins;
|
||||
|
||||
/* Clients */
|
||||
Arena *clients_arena;
|
||||
struct sim_client *clients;
|
||||
struct sim_client_handle first_free_client;
|
||||
Client *clients;
|
||||
ClientHandle first_free_client;
|
||||
u64 num_clients_allocated;
|
||||
u64 num_clients_reserved;
|
||||
};
|
||||
|
||||
INLINE struct sim_client_store *sim_client_store_nil(void)
|
||||
INLINE ClientStore *sim_client_store_nil(void)
|
||||
{
|
||||
extern READONLY struct sim_client_store **_g_sim_client_store_nil;
|
||||
extern READONLY ClientStore **_g_sim_client_store_nil;
|
||||
return *_g_sim_client_store_nil;
|
||||
}
|
||||
|
||||
struct sim_client_store *sim_client_store_alloc(void);
|
||||
void sim_client_store_release(struct sim_client_store *store);
|
||||
ClientStore *sim_client_store_alloc(void);
|
||||
void sim_client_store_release(ClientStore *store);
|
||||
|
||||
/* ========================== *
|
||||
* Client
|
||||
* ========================== */
|
||||
|
||||
struct sim_snapshot;
|
||||
|
||||
struct sim_snapshot_lookup_bin {
|
||||
struct sim_snapshot *first;
|
||||
struct sim_snapshot *last;
|
||||
typedef struct Snapshot Snapshot;
|
||||
typedef struct SnapshotLookupBin SnapshotLookupBin;
|
||||
struct SnapshotLookupBin {
|
||||
Snapshot *first;
|
||||
Snapshot *last;
|
||||
};
|
||||
|
||||
struct sim_client {
|
||||
typedef struct Client Client;
|
||||
struct Client {
|
||||
b32 valid;
|
||||
struct sim_client_handle handle;
|
||||
struct sim_client_store *store;
|
||||
ClientHandle handle;
|
||||
ClientStore *store;
|
||||
|
||||
Arena *snapshots_arena;
|
||||
|
||||
@ -85,12 +92,12 @@ struct sim_client {
|
||||
N_ChannelId channel_id;
|
||||
u64 channel_hash;
|
||||
|
||||
struct sim_client_handle next_free;
|
||||
struct sim_client_handle next_in_bin;
|
||||
struct sim_client_handle prev_in_bin;
|
||||
ClientHandle next_free;
|
||||
ClientHandle next_in_bin;
|
||||
ClientHandle prev_in_bin;
|
||||
|
||||
/* The client's player entity id in the master sim (if relevant) */
|
||||
struct sim_ent_id player_id;
|
||||
EntId player_id;
|
||||
|
||||
/* This is the highest confirmed tick of ours that we know this client has received */
|
||||
u64 ack;
|
||||
@ -107,40 +114,40 @@ struct sim_client {
|
||||
u64 first_tick;
|
||||
u64 last_tick;
|
||||
u64 num_ticks;
|
||||
struct sim_snapshot *first_free_snapshot;
|
||||
Snapshot *first_free_snapshot;
|
||||
|
||||
/* Tick -> snapshot lookup */
|
||||
u64 num_snapshot_lookup_bins;
|
||||
struct sim_snapshot_lookup_bin *snapshot_lookup_bins;
|
||||
SnapshotLookupBin *snapshot_lookup_bins;
|
||||
};
|
||||
|
||||
INLINE struct sim_client *sim_client_nil(void)
|
||||
INLINE Client *sim_client_nil(void)
|
||||
{
|
||||
extern READONLY struct sim_client **_g_sim_client_nil;
|
||||
extern READONLY Client **_g_sim_client_nil;
|
||||
return *_g_sim_client_nil;
|
||||
}
|
||||
|
||||
INLINE b32 sim_client_handle_eq(struct sim_client_handle a, struct sim_client_handle b)
|
||||
INLINE b32 sim_client_handle_eq(ClientHandle a, ClientHandle b)
|
||||
{
|
||||
return a.gen == b.gen && a.idx == b.idx;
|
||||
}
|
||||
|
||||
struct sim_client *sim_client_alloc(struct sim_client_store *store);
|
||||
void sim_client_release(struct sim_client *client);
|
||||
Client *sim_client_alloc(ClientStore *store);
|
||||
void sim_client_release(Client *client);
|
||||
|
||||
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, N_ChannelId channel_id);
|
||||
void sim_client_set_channel_id(struct sim_client *client, N_ChannelId channel_id);
|
||||
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct sim_client_handle handle);
|
||||
Client *sim_client_from_channel_id(ClientStore *store, N_ChannelId channel_id);
|
||||
void sim_client_set_channel_id(Client *client, N_ChannelId channel_id);
|
||||
Client *sim_client_from_handle(ClientStore *store, ClientHandle handle);
|
||||
|
||||
/* ========================== *
|
||||
* Snapshot
|
||||
* ========================== */
|
||||
|
||||
enum sim_sync_flag {
|
||||
typedef enum SyncFlag {
|
||||
SIM_SYNC_FLAG_NOSYNC_PREDICTABLES = 1 << 0
|
||||
};
|
||||
} SyncFlag;
|
||||
|
||||
enum sim_control_flag {
|
||||
typedef enum ControlFlag {
|
||||
SIM_CONTROL_FLAG_FIRE = 1 << 0,
|
||||
SIM_CONTROL_FLAG_FIRE_ALT = 1 << 1,
|
||||
|
||||
@ -156,39 +163,42 @@ enum sim_control_flag {
|
||||
SIM_CONTROL_FLAG_TILE_TEST = 1 << 10,
|
||||
SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 11,
|
||||
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 12,
|
||||
};
|
||||
} ControlFlag;
|
||||
|
||||
struct sim_control {
|
||||
typedef struct ControlData 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;
|
||||
};
|
||||
|
||||
enum sim_cmd_kind {
|
||||
typedef enum CmdKind {
|
||||
SIM_CMD_KIND_INVALID,
|
||||
|
||||
SIM_CMD_KIND_CONTROL,
|
||||
SIM_CMD_KIND_CHAT
|
||||
};
|
||||
} CmdKind;
|
||||
|
||||
enum sim_tile_kind {
|
||||
|
||||
typedef enum TileKind {
|
||||
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;
|
||||
|
||||
struct sim_snapshot {
|
||||
typedef struct Snapshot Snapshot;
|
||||
struct Snapshot {
|
||||
b32 valid;
|
||||
u64 tick;
|
||||
struct sim_client *client;
|
||||
struct sim_snapshot *next_free;
|
||||
struct sim_snapshot *next_in_bin;
|
||||
struct sim_snapshot *prev_in_bin;
|
||||
Client *client;
|
||||
Snapshot *next_free;
|
||||
Snapshot *next_in_bin;
|
||||
Snapshot *prev_in_bin;
|
||||
u64 prev_tick;
|
||||
u64 next_tick;
|
||||
|
||||
@ -205,7 +215,7 @@ struct sim_snapshot {
|
||||
u64 phys_iteration;
|
||||
|
||||
/* The id of the receiver's player in the snapshot */
|
||||
struct sim_ent_id local_player;
|
||||
EntId local_player;
|
||||
|
||||
/* Id lookup */
|
||||
struct sim_ent_bin *id_bins;
|
||||
@ -219,21 +229,21 @@ struct sim_snapshot {
|
||||
u32 num_ents_reserved;
|
||||
};
|
||||
|
||||
INLINE struct sim_snapshot *sim_snapshot_nil(void)
|
||||
INLINE Snapshot *sim_snapshot_nil(void)
|
||||
{
|
||||
extern READONLY struct sim_snapshot **_g_sim_snapshot_nil;
|
||||
extern READONLY Snapshot **_g_sim_snapshot_nil;
|
||||
return *_g_sim_snapshot_nil;
|
||||
}
|
||||
|
||||
/* Alloc */
|
||||
struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_snapshot *src, u64 tick);
|
||||
void sim_snapshot_release(struct sim_snapshot *sim_snapshot);
|
||||
void sim_snapshot_release_ticks_in_range(struct sim_client *client, u64 start, u64 end);
|
||||
Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick);
|
||||
void sim_snapshot_release(Snapshot *sim_snapshot);
|
||||
void sim_snapshot_release_ticks_in_range(Client *client, u64 start, u64 end);
|
||||
|
||||
/* Lookup */
|
||||
struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick);
|
||||
struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *client, u64 tick);
|
||||
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick);
|
||||
Snapshot *sim_snapshot_from_tick(Client *client, u64 tick);
|
||||
Snapshot *sim_snapshot_from_closest_tick_lte(Client *client, u64 tick);
|
||||
Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick);
|
||||
|
||||
/* Tile */
|
||||
V2i32 sim_world_tile_index_from_pos(V2 pos);
|
||||
@ -241,14 +251,14 @@ V2 sim_pos_from_world_tile_index(V2i32 world_tile_index);
|
||||
V2i32 sim_local_tile_index_from_world_tile_index(V2i32 world_tile_index);
|
||||
V2i32 sim_world_tile_index_from_local_tile_index(V2i32 tile_chunk_index, V2i32 local_tile_index);
|
||||
V2i32 sim_tile_chunk_index_from_world_tile_index(V2i32 world_tile_index);
|
||||
void sim_snapshot_set_tile(struct sim_snapshot *ss, V2i32 world_tile_index, enum sim_tile_kind tile_kind);
|
||||
void sim_snapshot_set_tile(Snapshot *ss, V2i32 world_tile_index, TileKind tile_kind);
|
||||
|
||||
/* Lerp */
|
||||
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
|
||||
Snapshot *sim_snapshot_alloc_from_lerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend);
|
||||
|
||||
/* Sync */
|
||||
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_id remote_player, u32 sync_flags);
|
||||
void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntId remote_player, u32 sync_flags);
|
||||
|
||||
/* Encode / decode */
|
||||
void sim_snapshot_encode(BitbuffWriter *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);
|
||||
void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss);
|
||||
void sim_snapshot_encode(BitbuffWriter *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1);
|
||||
void sim_snapshot_decode(BitbuffReader *br, Snapshot *ss);
|
||||
|
||||
@ -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(struct sim_snapshot *ss, struct sim_ent *ent)
|
||||
INTERNAL u32 index_from_ent(Snapshot *ss, struct sim_ent *ent)
|
||||
{
|
||||
return ent - ss->ents;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *ent_from_index(struct sim_snapshot *ss, u32 index)
|
||||
INTERNAL struct sim_ent *ent_from_index(Snapshot *ss, u32 index)
|
||||
{
|
||||
if (index > 0 && index < ss->num_ents_reserved) {
|
||||
return &ss->ents[index];
|
||||
@ -21,7 +21,7 @@ INTERNAL struct sim_ent *ent_from_index(struct sim_snapshot *ss, u32 index)
|
||||
* Ent allocation
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss, struct sim_ent *parent, struct sim_ent_id id)
|
||||
struct sim_ent *sim_ent_alloc_raw(Snapshot *ss, struct sim_ent *parent, EntId id)
|
||||
{
|
||||
ASSERT(parent->valid);
|
||||
ASSERT(ss->valid);
|
||||
@ -52,15 +52,15 @@ struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss, struct sim_ent *paren
|
||||
/* Allocates a new entity that will not sync */
|
||||
struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent)
|
||||
{
|
||||
struct sim_snapshot *ss = parent->ss;
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_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, struct sim_ent_id id)
|
||||
struct sim_ent *sim_ent_alloc_local_with_id(struct sim_ent *parent, EntId id)
|
||||
{
|
||||
struct sim_snapshot *ss = parent->ss;
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
@ -69,16 +69,16 @@ struct sim_ent *sim_ent_alloc_local_with_id(struct sim_ent *parent, struct sim_e
|
||||
/* Allocates a new entity to be synced to clients */
|
||||
struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent)
|
||||
{
|
||||
struct sim_snapshot *ss = parent->ss;
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_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, struct sim_ent_id id)
|
||||
struct sim_ent *sim_ent_alloc_sync_src_with_id(struct sim_ent *parent, EntId id)
|
||||
{
|
||||
struct sim_snapshot *ss = parent->ss;
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_SRC);
|
||||
e->owner = ss->local_player;
|
||||
@ -86,9 +86,9 @@ struct sim_ent *sim_ent_alloc_sync_src_with_id(struct sim_ent *parent, struct si
|
||||
}
|
||||
|
||||
/* 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, struct sim_ent_id ent_id, struct sim_ent_id owner_id)
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, EntId ent_id, EntId owner_id)
|
||||
{
|
||||
struct sim_snapshot *ss = parent->ss;
|
||||
Snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss, parent, ent_id);
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_DST);
|
||||
e->owner = owner_id;
|
||||
@ -97,7 +97,7 @@ struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_ent_id
|
||||
|
||||
void sim_ent_release_raw(struct sim_ent *ent)
|
||||
{
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
Snapshot *ss = ent->ss;
|
||||
/* Release children */
|
||||
struct sim_ent *child = sim_ent_from_id(ss, ent->first);
|
||||
while (child->valid) {
|
||||
@ -118,7 +118,7 @@ void sim_ent_release_raw(struct sim_ent *ent)
|
||||
|
||||
void sim_ent_release(struct sim_ent *ent)
|
||||
{
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
Snapshot *ss = ent->ss;
|
||||
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
if (parent->valid) {
|
||||
sim_ent_unlink_from_parent(ent);
|
||||
@ -126,7 +126,7 @@ void sim_ent_release(struct sim_ent *ent)
|
||||
sim_ent_release_raw(ent);
|
||||
}
|
||||
|
||||
void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop prop)
|
||||
void sim_ent_release_all_with_prop(Snapshot *ss, enum sim_ent_prop prop)
|
||||
{
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
|
||||
@ -168,16 +168,16 @@ void sim_ent_activate(struct sim_ent *ent, u64 current_tick)
|
||||
* Ent id
|
||||
* ========================== */
|
||||
|
||||
INTERNAL struct sim_ent_bin *bin_from_id(struct sim_snapshot *ss, struct sim_ent_id id)
|
||||
INTERNAL struct sim_ent_bin *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, struct sim_ent_id id)
|
||||
void sim_ent_set_id(struct sim_ent *ent, EntId id)
|
||||
{
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
struct sim_ent_id old_id = ent->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)) {
|
||||
@ -244,7 +244,7 @@ void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id)
|
||||
|
||||
}
|
||||
|
||||
struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id)
|
||||
struct sim_ent *sim_ent_from_id(Snapshot *ss, EntId id)
|
||||
{
|
||||
struct sim_ent *res = sim_ent_nil();
|
||||
if (!sim_ent_id_is_nil(id) && ss->valid) {
|
||||
@ -259,17 +259,17 @@ struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id)
|
||||
return res;
|
||||
}
|
||||
|
||||
struct sim_ent_id sim_ent_random_id(void)
|
||||
EntId sim_ent_random_id(void)
|
||||
{
|
||||
struct sim_ent_id res = ZI;
|
||||
EntId res = ZI;
|
||||
res.uid = uid_true_rand();
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the contact constraint ent id that should be produced from e0 & e1 colliding */
|
||||
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1)
|
||||
EntId sim_ent_contact_constraint_id_from_contacting_ids(EntId player_id, EntId id0, EntId id1)
|
||||
{
|
||||
struct sim_ent_id res = ZI;
|
||||
EntId res = ZI;
|
||||
res.uid = SIM_ENT_CONTACT_BASIS_UID;
|
||||
res.uid = uid_combine(res.uid, player_id.uid);
|
||||
res.uid = uid_combine(res.uid, id0.uid);
|
||||
@ -278,9 +278,9 @@ struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_e
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the debug contact constraint ent id that should be produced from e0 & e1 colliding */
|
||||
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1)
|
||||
EntId sim_ent_collision_debug_id_from_ids(EntId player_id, EntId id0, EntId id1)
|
||||
{
|
||||
struct sim_ent_id res = ZI;
|
||||
EntId res = ZI;
|
||||
res.uid = SIM_ENT_COLLISION_DEBUG_BASIS_UID;
|
||||
res.uid = uid_combine(res.uid, player_id.uid);
|
||||
res.uid = uid_combine(res.uid, id0.uid);
|
||||
@ -289,9 +289,9 @@ struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_i
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
|
||||
struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_index)
|
||||
EntId sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_index)
|
||||
{
|
||||
struct sim_ent_id res = ZI;
|
||||
EntId res = ZI;
|
||||
res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID;
|
||||
res.uid = uid_combine(res.uid, MakeUID(rand_u64_from_seed(chunk_index.x), rand_u64_from_seed(chunk_index.y)));
|
||||
return res;
|
||||
@ -301,7 +301,7 @@ struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_index)
|
||||
* Ent query
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop)
|
||||
struct sim_ent *sim_ent_find_first_match_one(Snapshot *ss, enum sim_ent_prop prop)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
struct sim_ent *entities = ss->ents;
|
||||
@ -314,7 +314,7 @@ struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_e
|
||||
return sim_ent_nil();
|
||||
}
|
||||
|
||||
struct sim_ent *sim_ent_find_first_match_all(struct sim_snapshot *ss, struct sim_ent_prop_array props)
|
||||
struct sim_ent *sim_ent_find_first_match_all(Snapshot *ss, struct sim_ent_prop_array props)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
struct sim_ent *entities = ss->ents;
|
||||
@ -342,7 +342,7 @@ struct sim_ent *sim_ent_find_first_match_all(struct sim_snapshot *ss, struct sim
|
||||
|
||||
void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent)
|
||||
{
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
Snapshot *ss = ent->ss;
|
||||
|
||||
struct sim_ent *old_parent = sim_ent_from_id(ss, ent->parent);
|
||||
if (old_parent->valid) {
|
||||
@ -350,8 +350,8 @@ void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent)
|
||||
sim_ent_unlink_from_parent(ent);
|
||||
}
|
||||
|
||||
struct sim_ent_id ent_id = ent->id;
|
||||
struct sim_ent_id last_child_id = parent->last;
|
||||
EntId ent_id = ent->id;
|
||||
EntId last_child_id = parent->last;
|
||||
struct sim_ent *last_child = sim_ent_from_id(ss, last_child_id);
|
||||
if (last_child->valid) {
|
||||
ent->prev = last_child_id;
|
||||
@ -374,9 +374,9 @@ 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)
|
||||
{
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
Snapshot *ss = ent->ss;
|
||||
|
||||
struct sim_ent_id parent_id = ent->parent;
|
||||
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);
|
||||
@ -400,7 +400,7 @@ void sim_ent_unlink_from_parent(struct sim_ent *ent)
|
||||
* Ent xform
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void sim_ent_mark_child_xforms_dirty(struct sim_snapshot *ss, struct sim_ent *ent)
|
||||
INTERNAL void sim_ent_mark_child_xforms_dirty(Snapshot *ss, struct sim_ent *ent)
|
||||
{
|
||||
for (struct sim_ent *child = sim_ent_from_id(ss, ent->first); child->valid; child = sim_ent_from_id(ss, child->next)) {
|
||||
if (child->_is_xform_dirty) {
|
||||
@ -412,7 +412,7 @@ INTERNAL void sim_ent_mark_child_xforms_dirty(struct sim_snapshot *ss, struct si
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL Xform sim_ent_get_xform_internal(struct sim_snapshot *ss, struct sim_ent *ent)
|
||||
INTERNAL Xform sim_ent_get_xform_internal(Snapshot *ss, struct sim_ent *ent)
|
||||
{
|
||||
Xform xf;
|
||||
if (ent->_is_xform_dirty) {
|
||||
@ -440,7 +440,7 @@ Xform sim_ent_get_xform(struct sim_ent *ent)
|
||||
if (ent->is_top) {
|
||||
xf = ent->_local_xform;
|
||||
} else {
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
Snapshot *ss = ent->ss;
|
||||
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
xf = sim_ent_get_xform_internal(ss, parent);
|
||||
xf = xform_mul(xf, ent->_local_xform);
|
||||
@ -463,7 +463,7 @@ Xform sim_ent_get_local_xform(struct sim_ent *ent)
|
||||
void sim_ent_set_xform(struct sim_ent *ent, Xform xf)
|
||||
{
|
||||
if (!xform_eq(xf, ent->_xform)) {
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
Snapshot *ss = ent->ss;
|
||||
/* Update local xform */
|
||||
if (ent->is_top) {
|
||||
ent->_local_xform = xf;
|
||||
@ -559,23 +559,23 @@ void sim_ent_apply_torque(struct sim_ent *ent, f32 torque)
|
||||
* Tile
|
||||
* ========================== */
|
||||
|
||||
struct sim_ent *sim_tile_chunk_from_chunk_index(struct sim_snapshot *ss, V2i32 chunk_index)
|
||||
struct sim_ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2i32 chunk_index)
|
||||
{
|
||||
struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(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);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, V2i32 world_tile_index)
|
||||
struct sim_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);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index)
|
||||
TileKind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index)
|
||||
{
|
||||
enum sim_tile_kind res = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
TileKind res = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -624,14 +624,14 @@ 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, struct sim_ent_id remote_player)
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote, EntId remote_player)
|
||||
{
|
||||
__prof;
|
||||
if (sim_ent_has_prop(remote, SEPROP_SYNC_SRC)) {
|
||||
struct sim_snapshot *local_ss = local_parent->ss;
|
||||
struct sim_snapshot *remote_ss = remote->ss;
|
||||
Snapshot *local_ss = local_parent->ss;
|
||||
Snapshot *remote_ss = remote->ss;
|
||||
|
||||
struct sim_ent_id id = remote->id;
|
||||
EntId id = remote->id;
|
||||
struct sim_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);
|
||||
@ -689,7 +689,7 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
|
||||
|
||||
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||
{
|
||||
struct sim_snapshot *ss = e1->ss;
|
||||
Snapshot *ss = e1->ss;
|
||||
/* FIXME: Things like xforms need to be retreived manually rather than memcopied. */
|
||||
|
||||
/* TODO: Granular delta encoding */
|
||||
@ -716,7 +716,7 @@ void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||
|
||||
void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||
{
|
||||
struct sim_snapshot *old_ss = e->ss;
|
||||
Snapshot *old_ss = e->ss;
|
||||
{
|
||||
u64 pos = 0;
|
||||
while (pos < sizeof(*e)) {
|
||||
@ -741,7 +741,7 @@ void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||
|
||||
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||
{
|
||||
struct sim_snapshot *ss = e1->ss;
|
||||
Snapshot *ss = e1->ss;
|
||||
|
||||
|
||||
/* FIXME: Things like xforms need to be retreived manually rather than memcopied.
|
||||
@ -789,8 +789,8 @@ void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||
}
|
||||
decoded.ss = e->ss;
|
||||
|
||||
struct sim_ent_id old_id = e->id;
|
||||
struct sim_ent_id new_id = decoded.id;
|
||||
EntId old_id = e->id;
|
||||
EntId new_id = decoded.id;
|
||||
MEMCPY_STRUCT(e, &decoded);
|
||||
e->id = old_id;
|
||||
if (!sim_ent_id_eq(old_id, new_id)) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#define SIM_ENT_NIL_ID ((struct sim_ent_id) { MakeUID(0, 0) })
|
||||
#define SIM_ENT_ROOT_ID ((struct sim_ent_id) { MakeUID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||
#define SIM_ENT_NIL_ID ((EntId) { MakeUID(0, 0) })
|
||||
#define SIM_ENT_ROOT_ID ((EntId) { MakeUID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||
|
||||
enum sim_ent_prop {
|
||||
SEPROP_ACTIVE,
|
||||
@ -61,13 +61,13 @@ enum sim_ent_prop {
|
||||
};
|
||||
|
||||
struct sim_ent {
|
||||
struct sim_snapshot *ss;
|
||||
Snapshot *ss;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Metadata */
|
||||
|
||||
b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */
|
||||
struct sim_ent_id id;
|
||||
EntId id;
|
||||
u64 props[(SEPROP_COUNT + 63) / 64];
|
||||
u64 continuity_gen;
|
||||
|
||||
@ -78,14 +78,14 @@ struct sim_ent {
|
||||
b32 is_top;
|
||||
|
||||
/* The id of the top level parent of the ent tree (if ent is top then this point to itself) */
|
||||
struct sim_ent_id top;
|
||||
EntId top;
|
||||
|
||||
/* Tree */
|
||||
struct sim_ent_id parent;
|
||||
struct sim_ent_id next;
|
||||
struct sim_ent_id prev;
|
||||
struct sim_ent_id first;
|
||||
struct sim_ent_id last;
|
||||
EntId parent;
|
||||
EntId next;
|
||||
EntId prev;
|
||||
EntId first;
|
||||
EntId last;
|
||||
|
||||
/* Lists keyed by index in snapshot ent array */
|
||||
u32 next_in_id_bin;
|
||||
@ -99,10 +99,10 @@ struct sim_ent {
|
||||
/* SEPROP_SYNC_DST */
|
||||
|
||||
/* Id of the player that owns simulation for this entity */
|
||||
struct sim_ent_id owner;
|
||||
EntId owner;
|
||||
|
||||
/* Id of the player that should predict simulation of this this entity locally */
|
||||
struct sim_ent_id predictor;
|
||||
EntId predictor;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Position */
|
||||
@ -129,14 +129,14 @@ struct sim_ent {
|
||||
|
||||
/* SEPROP_CMD */
|
||||
|
||||
enum sim_cmd_kind cmd_kind;
|
||||
struct sim_ent_id cmd_player;
|
||||
CmdKind cmd_kind;
|
||||
EntId cmd_player;
|
||||
|
||||
/* FIXME: Lerp */
|
||||
|
||||
/* Control cmd */
|
||||
struct sim_control cmd_control;
|
||||
struct sim_ent_id cmd_control_hovered_ent;
|
||||
ControlData cmd_control;
|
||||
EntId cmd_control_hovered_ent;
|
||||
|
||||
/* Chat cmd */
|
||||
//String cmd_chat_msg;
|
||||
@ -146,7 +146,7 @@ struct sim_ent {
|
||||
|
||||
/* SEPROP_CHAT */
|
||||
|
||||
struct sim_ent_id chat_player;
|
||||
EntId chat_player;
|
||||
//String chat_msg;
|
||||
|
||||
|
||||
@ -166,16 +166,16 @@ struct sim_ent {
|
||||
|
||||
/* FIXME: Lerp */
|
||||
|
||||
struct sim_client_handle player_client_handle; /* The client handle on the master sim's machine */
|
||||
ClientHandle player_client_handle; /* The client handle on the master sim's machine */
|
||||
|
||||
struct sim_control player_control;
|
||||
ControlData player_control;
|
||||
V2 player_cursor_pos;
|
||||
|
||||
struct sim_ent_id player_hovered_ent;
|
||||
struct sim_ent_id player_control_ent;
|
||||
struct sim_ent_id player_camera_ent;
|
||||
EntId player_hovered_ent;
|
||||
EntId player_control_ent;
|
||||
EntId player_camera_ent;
|
||||
|
||||
struct sim_ent_id player_dbg_drag_joint_ent;
|
||||
EntId player_dbg_drag_joint_ent;
|
||||
b32 player_dbg_drag_start;
|
||||
b32 player_dbg_drag_stop;
|
||||
|
||||
@ -190,42 +190,42 @@ struct sim_ent {
|
||||
CLD_Shape local_collider;
|
||||
|
||||
#if COLLIDER_DEBUG
|
||||
struct phys_collision_debug collision_debug_data;
|
||||
CollisionDebugData collision_debug_data;
|
||||
#endif
|
||||
|
||||
struct space_entry_handle space_handle;
|
||||
SpaceEntryHandle space_handle;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Constraints / joints */
|
||||
|
||||
/* SEPROP_CONSTRAINT_CONTACT */
|
||||
struct phys_contact_constraint contact_constraint_data;
|
||||
ContactConstraint contact_constraint_data;
|
||||
|
||||
/* SEPROP_MOTOR_JOINT */
|
||||
struct phys_motor_joint motor_joint_data;
|
||||
MotorJoint motor_joint_data;
|
||||
|
||||
/* SEPROP_MOUSE_JOINT */
|
||||
struct phys_mouse_joint mouse_joint_data;
|
||||
MouseJoint mouse_joint_data;
|
||||
|
||||
/* SEPROP_WELD_JOINT */
|
||||
struct phys_weld_joint weld_joint_data;
|
||||
WeldJoint weld_joint_data;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Control */
|
||||
|
||||
/* SEPROP_CONTROLLED */
|
||||
|
||||
struct sim_ent_id controlling_player;
|
||||
EntId controlling_player;
|
||||
|
||||
f32 control_force; /* How much force is applied to achieve desired control movement */
|
||||
f32 control_force_max_speed; /* Maximum linear velocity achieved by force (m/s) */
|
||||
|
||||
f32 control_torque; /* How much torque is applied when turning towards desired focus */
|
||||
|
||||
struct sim_control control;
|
||||
ControlData control;
|
||||
|
||||
struct sim_ent_id move_joint;
|
||||
struct sim_ent_id aim_joint;
|
||||
EntId move_joint;
|
||||
EntId aim_joint;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Physics */
|
||||
@ -239,7 +239,7 @@ struct sim_ent {
|
||||
f32 mass_unscaled; /* Mass of ent in kg before any transformations */
|
||||
f32 inertia_unscaled; /* Inertia of ent in kg*m^2 before any transformations */
|
||||
|
||||
struct sim_ent_id ground_friction_joint;
|
||||
EntId ground_friction_joint;
|
||||
f32 linear_ground_friction;
|
||||
f32 angular_ground_friction;
|
||||
|
||||
@ -256,7 +256,7 @@ struct sim_ent {
|
||||
/* ====================================================================== */
|
||||
/* Sprite */
|
||||
|
||||
struct sprite_tag sprite;
|
||||
S_Tag sprite;
|
||||
String sprite_span_name;
|
||||
u32 sprite_tint;
|
||||
V3 sprite_emittance;
|
||||
@ -282,22 +282,22 @@ struct sim_ent {
|
||||
/* ====================================================================== */
|
||||
/* Equip */
|
||||
|
||||
struct sim_ent_id equipped;
|
||||
EntId equipped;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Chucker */
|
||||
|
||||
/* SEPROP_WEAPON_CHUCKER */
|
||||
|
||||
struct sim_ent_id chucker_zone;
|
||||
struct sim_ent_id chucker_joint;
|
||||
EntId chucker_zone;
|
||||
EntId chucker_joint;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Chucker zone */
|
||||
|
||||
/* SEPROP_CHUCKER_ZONE */
|
||||
|
||||
struct sim_ent_id chucker_zone_ent;
|
||||
EntId chucker_zone_ent;
|
||||
u64 chucker_zone_ent_tick;
|
||||
|
||||
/* ====================================================================== */
|
||||
@ -319,14 +319,14 @@ struct sim_ent {
|
||||
i64 triggered_count;
|
||||
|
||||
/* Other triggers to activate when this entity has been triggered */
|
||||
//struct sim_ent_id trigger_out_left;
|
||||
//struct sim_ent_id trigger_out_right;
|
||||
//EntId trigger_out_left;
|
||||
//EntId trigger_out_right;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Bullet */
|
||||
|
||||
struct sim_ent_id bullet_src;
|
||||
struct sim_ent_id bullet_tracer;
|
||||
EntId bullet_src;
|
||||
EntId bullet_tracer;
|
||||
V2 bullet_src_pos;
|
||||
V2 bullet_src_dir;
|
||||
f32 bullet_launch_velocity;
|
||||
@ -380,7 +380,7 @@ struct sim_ent {
|
||||
/* Camera */
|
||||
|
||||
/* SEPROP_CAMERA */
|
||||
struct sim_ent_id camera_follow;
|
||||
EntId camera_follow;
|
||||
Xform camera_quad_xform;
|
||||
f32 camera_lerp; /* Rate at which camera xform approaches target xform */
|
||||
|
||||
@ -420,12 +420,12 @@ INLINE struct sim_ent *sim_ent_nil(void)
|
||||
* Id helpers
|
||||
* ========================== */
|
||||
|
||||
INLINE b32 sim_ent_id_eq(struct sim_ent_id a, struct sim_ent_id b)
|
||||
INLINE b32 sim_ent_id_eq(EntId a, EntId b)
|
||||
{
|
||||
return uid_eq(a.uid, b.uid);
|
||||
}
|
||||
|
||||
INLINE b32 sim_ent_id_is_nil(struct sim_ent_id id)
|
||||
INLINE b32 sim_ent_id_is_nil(EntId id)
|
||||
{
|
||||
return uid_eq(id.uid, SIM_ENT_NIL_ID.uid);
|
||||
}
|
||||
@ -476,7 +476,7 @@ INLINE b32 sim_ent_should_simulate(struct sim_ent *ent)
|
||||
if (sim_ent_is_valid_and_active(ent)) {
|
||||
res = 1;
|
||||
if (sim_ent_has_prop(ent, SEPROP_SYNC_DST)) {
|
||||
struct sim_ent_id local_player = ent->ss->local_player;
|
||||
EntId local_player = ent->ss->local_player;
|
||||
res = sim_ent_id_eq(local_player, ent->owner) || sim_ent_id_eq(local_player, ent->predictor);
|
||||
}
|
||||
}
|
||||
@ -488,31 +488,31 @@ INLINE b32 sim_ent_should_simulate(struct sim_ent *ent)
|
||||
* ========================== */
|
||||
|
||||
/* Alloc */
|
||||
struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss, struct sim_ent *parent, struct sim_ent_id id);
|
||||
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, struct sim_ent_id id);
|
||||
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, struct sim_ent_id id);
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_ent_id ent_id, struct sim_ent_id owner_id);
|
||||
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);
|
||||
|
||||
void sim_ent_release_raw(struct sim_ent *ent);
|
||||
void sim_ent_release(struct sim_ent *ent);
|
||||
void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop prop);
|
||||
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);
|
||||
|
||||
/* Id */
|
||||
void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id);
|
||||
struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id);
|
||||
struct sim_ent_id sim_ent_random_id(void);
|
||||
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
||||
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
||||
struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_start);
|
||||
void sim_ent_set_id(struct sim_ent *ent, EntId id);
|
||||
struct sim_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(struct sim_snapshot *ss, enum sim_ent_prop prop);
|
||||
struct sim_ent *sim_ent_find_first_match_all(struct sim_snapshot *ss, struct sim_ent_prop_array props);
|
||||
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);
|
||||
|
||||
/* Tree */
|
||||
void sim_ent_link_parent(struct sim_ent *parent, struct sim_ent *child);
|
||||
@ -534,15 +534,15 @@ void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse);
|
||||
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
|
||||
|
||||
/* Tile */
|
||||
struct sim_ent *sim_tile_chunk_from_chunk_index(struct sim_snapshot *ss, V2i32 chunk_index);
|
||||
struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, V2i32 world_tile_index);
|
||||
enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index);
|
||||
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);
|
||||
|
||||
/* Lerp */
|
||||
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);
|
||||
|
||||
/* Sync */
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote, struct sim_ent_id remote_player);
|
||||
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);
|
||||
|
||||
/* Encode / decode */
|
||||
|
||||
@ -14,13 +14,13 @@ INTERNAL b32 can_contact(struct sim_ent *e0, struct sim_ent *e1)
|
||||
return res;
|
||||
}
|
||||
|
||||
void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration)
|
||||
void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration)
|
||||
{
|
||||
__prof;
|
||||
struct sim_step_ctx *sim_step_ctx = ctx->sim_step_ctx;
|
||||
struct sim_snapshot *ss = sim_step_ctx->world;
|
||||
struct space *space = sim_step_ctx->accel->space;
|
||||
struct sim_ent_id local_player = ss->local_player;
|
||||
SimStepCtx *sim_step_ctx = ctx->sim_step_ctx;
|
||||
Snapshot *ss = sim_step_ctx->world;
|
||||
Space *space = sim_step_ctx->accel->space;
|
||||
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);
|
||||
@ -36,8 +36,8 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
CLD_Shape check0_collider = check0->local_collider;
|
||||
Aabb aabb = collider_aabb_from_collider(&check0_collider, check0_xf);
|
||||
|
||||
struct space_iter iter = space_iter_begin_aabb(space, aabb);
|
||||
struct space_entry *space_entry;
|
||||
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);
|
||||
if (!sim_ent_is_valid_and_active(check1)) continue;
|
||||
@ -68,7 +68,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
e1_collider = check0_collider;
|
||||
}
|
||||
|
||||
struct sim_ent_id constraint_id = sim_ent_contact_constraint_id_from_contacting_ids(local_player, e0->id, e1->id);
|
||||
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);
|
||||
|
||||
if (constraint_ent->valid) {
|
||||
@ -87,7 +87,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
STATIC_ASSERT(countof(constraint_ent->contact_constraint_data.points) == 2);
|
||||
STATIC_ASSERT(countof(collider_res.points) == 2);
|
||||
|
||||
struct phys_contact_constraint *constraint = 0;
|
||||
ContactConstraint *constraint = 0;
|
||||
if (collider_res.num_points > 0) {
|
||||
b32 is_start = 0;
|
||||
if (!constraint_ent->valid) {
|
||||
@ -111,7 +111,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
|
||||
/* Delete old contacts that are no longer present */
|
||||
for (u32 i = 0; i < constraint->num_points; ++i) {
|
||||
struct phys_contact_point *old = &constraint->points[i];
|
||||
ContactPoint *old = &constraint->points[i];
|
||||
u32 id = old->id;
|
||||
b32 found = 0;
|
||||
for (u32 j = 0; j < collider_res.num_points; ++j) {
|
||||
@ -133,10 +133,10 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
V2 point = res_point->point;
|
||||
f32 sep = res_point->separation;
|
||||
u32 id = res_point->id;
|
||||
struct phys_contact_point *contact = 0;
|
||||
ContactPoint *contact = 0;
|
||||
/* Match */
|
||||
for (u32 j = 0; j < constraint->num_points; ++j) {
|
||||
struct phys_contact_point *t = &constraint->points[j];
|
||||
ContactPoint *t = &constraint->points[j];
|
||||
if (t->id == id) {
|
||||
contact = t;
|
||||
break;
|
||||
@ -178,7 +178,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
|
||||
/* Run collision callback */
|
||||
if (collision_callback) {
|
||||
struct phys_collision_data data = ZI;
|
||||
CollisionData data = ZI;
|
||||
data.e0 = e0->id;
|
||||
data.e1 = e1->id;
|
||||
data.normal = collider_res.normal;
|
||||
@ -208,7 +208,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
data.vrel = vrel;
|
||||
|
||||
/* Collision data from e1's perspective */
|
||||
struct phys_collision_data data_inverted = data;
|
||||
CollisionData data_inverted = data;
|
||||
data_inverted.e0 = data.e1;
|
||||
data_inverted.e1 = data.e0;
|
||||
data_inverted.normal = v2_neg(data.normal);
|
||||
@ -228,7 +228,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
/* TODO: Remove this (debugging) */
|
||||
#if COLLIDER_DEBUG && COLLIDER_DEBUG_DETAILED
|
||||
{
|
||||
struct sim_ent_id dbg_ent_id = sim_ent_collision_debug_id_from_ids(local_player, e0->id, e1->id);
|
||||
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);
|
||||
if (!dbg_ent->valid) {
|
||||
/* FIXME: Entity never released */
|
||||
@ -236,7 +236,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
sim_ent_enable_prop(dbg_ent, SEPROP_COLLISION_DEBUG);
|
||||
}
|
||||
|
||||
struct phys_collision_debug *dbg = &dbg_ent->collision_debug_data;
|
||||
CollisionDebugData *dbg = &dbg_ent->collision_debug_data;
|
||||
|
||||
dbg->e0 = e0->id;
|
||||
dbg->e1 = e1->id;
|
||||
@ -265,17 +265,17 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
||||
}
|
||||
}
|
||||
|
||||
void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
||||
void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
u32 num_points = constraint->num_points;
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
@ -318,7 +318,7 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
||||
|
||||
/* Update / insert returned contacts */
|
||||
for (u32 i = 0; i < num_points; ++i) {
|
||||
struct phys_contact_point *contact = &constraint->points[i];
|
||||
ContactPoint *contact = &constraint->points[i];
|
||||
V2 vcp0 = contact->vcp0;
|
||||
V2 vcp1 = contact->vcp1;
|
||||
|
||||
@ -359,7 +359,7 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
||||
if (!sim_ent_should_simulate(dbg_ent)) continue;
|
||||
if (!sim_ent_has_prop(dbg_ent, SEPROP_COLLISION_DEBUG)) continue;
|
||||
|
||||
struct phys_collision_debug *dbg = &dbg_ent->collision_debug_data;
|
||||
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);
|
||||
|
||||
@ -375,16 +375,16 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
||||
#endif
|
||||
}
|
||||
|
||||
void phys_warm_start_contacts(struct phys_step_ctx *ctx)
|
||||
void phys_warm_start_contacts(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
u32 num_points = constraint->num_points;
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
@ -406,7 +406,7 @@ void phys_warm_start_contacts(struct phys_step_ctx *ctx)
|
||||
V2 tangent = v2_perp(normal);
|
||||
f32 inv_num_points = 1.f / num_points;
|
||||
for (u32 i = 0; i < num_points; ++i) {
|
||||
struct phys_contact_point *point = &constraint->points[i];
|
||||
ContactPoint *point = &constraint->points[i];
|
||||
V2 vcp0 = point->vcp0;
|
||||
V2 vcp1 = point->vcp1;
|
||||
|
||||
@ -427,16 +427,16 @@ void phys_warm_start_contacts(struct phys_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
||||
void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
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);
|
||||
@ -459,7 +459,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
||||
/* Normal impulse */
|
||||
V2 normal = constraint->normal;
|
||||
for (u32 point_index = 0; point_index < num_points; ++point_index) {
|
||||
struct phys_contact_point *point = &constraint->points[point_index];
|
||||
ContactPoint *point = &constraint->points[point_index];
|
||||
V2 vcp0 = point->vcp0;
|
||||
V2 vcp1 = point->vcp1;
|
||||
V2 p0 = v2_add(e0_xf.og, vcp0);
|
||||
@ -509,7 +509,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
||||
/* Tangent impulse */
|
||||
V2 tangent = v2_perp(normal);
|
||||
for (u32 point_index = 0; point_index < num_points; ++point_index) {
|
||||
struct phys_contact_point *point = &constraint->points[point_index];
|
||||
ContactPoint *point = &constraint->points[point_index];
|
||||
V2 vcp0 = point->vcp0;
|
||||
V2 vcp1 = point->vcp1;
|
||||
|
||||
@ -548,15 +548,15 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
||||
* Motor joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_motor_joint_def phys_motor_joint_def_init(void)
|
||||
MotorJointDesc phys_motor_joint_def_init(void)
|
||||
{
|
||||
struct phys_motor_joint_def def = ZI;
|
||||
MotorJointDesc def = ZI;
|
||||
return def;
|
||||
}
|
||||
|
||||
struct phys_motor_joint phys_motor_joint_from_def(struct phys_motor_joint_def def)
|
||||
MotorJoint phys_motor_joint_from_def(MotorJointDesc def)
|
||||
{
|
||||
struct phys_motor_joint res = ZI;
|
||||
MotorJoint res = ZI;
|
||||
res.e0 = def.e0;
|
||||
res.e1 = def.e1;
|
||||
res.correction_rate = clamp_f32(def.correction_rate, 0, 1);
|
||||
@ -565,16 +565,16 @@ struct phys_motor_joint phys_motor_joint_from_def(struct phys_motor_joint_def de
|
||||
return res;
|
||||
}
|
||||
|
||||
void phys_prepare_motor_joints(struct phys_step_ctx *ctx)
|
||||
void phys_prepare_motor_joints(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
struct phys_motor_joint *joint = &joint_ent->motor_joint_data;
|
||||
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);
|
||||
@ -629,16 +629,16 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_warm_start_motor_joints(struct phys_step_ctx *ctx)
|
||||
void phys_warm_start_motor_joints(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
struct phys_motor_joint *joint = &joint_ent->motor_joint_data;
|
||||
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);
|
||||
@ -661,16 +661,16 @@ void phys_warm_start_motor_joints(struct phys_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt)
|
||||
void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
struct phys_motor_joint *joint = &joint_ent->motor_joint_data;
|
||||
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);
|
||||
@ -742,9 +742,9 @@ void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt)
|
||||
* Mouse joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_mouse_joint_def phys_mouse_joint_def_init(void)
|
||||
MouseJointDesc phys_mouse_joint_def_init(void)
|
||||
{
|
||||
struct phys_mouse_joint_def def = ZI;
|
||||
MouseJointDesc def = ZI;
|
||||
def.linear_spring_hz = 5.0f;
|
||||
def.linear_spring_damp = 0.7f;
|
||||
def.angular_spring_hz = 5.0f;
|
||||
@ -753,9 +753,9 @@ struct phys_mouse_joint_def phys_mouse_joint_def_init(void)
|
||||
return def;
|
||||
}
|
||||
|
||||
struct phys_mouse_joint phys_mouse_joint_from_def(struct phys_mouse_joint_def def)
|
||||
MouseJoint phys_mouse_joint_from_def(MouseJointDesc def)
|
||||
{
|
||||
struct phys_mouse_joint res = ZI;
|
||||
MouseJoint res = ZI;
|
||||
res.target = def.target;
|
||||
res.point_local_start = def.point_local_start;
|
||||
res.point_end = def.point_end;
|
||||
@ -767,16 +767,16 @@ struct phys_mouse_joint phys_mouse_joint_from_def(struct phys_mouse_joint_def de
|
||||
return res;
|
||||
}
|
||||
|
||||
void phys_prepare_mouse_joints(struct phys_step_ctx *ctx)
|
||||
void phys_prepare_mouse_joints(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -814,16 +814,16 @@ void phys_prepare_mouse_joints(struct phys_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_warm_start_mouse_joints(struct phys_step_ctx *ctx)
|
||||
void phys_warm_start_mouse_joints(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
f32 inv_m = joint->inv_m;
|
||||
@ -836,16 +836,16 @@ void phys_warm_start_mouse_joints(struct phys_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt)
|
||||
void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
V2 v = ent->linear_velocity;
|
||||
@ -909,9 +909,9 @@ void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt)
|
||||
* Weld joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_weld_joint_def phys_weld_joint_def_init(void)
|
||||
WeldJointDesc phys_weld_joint_def_init(void)
|
||||
{
|
||||
struct phys_weld_joint_def def = ZI;
|
||||
WeldJointDesc def = ZI;
|
||||
def.linear_spring_hz = 50;
|
||||
def.linear_spring_damp = 0;
|
||||
def.angular_spring_hz = 50;
|
||||
@ -919,9 +919,9 @@ struct phys_weld_joint_def phys_weld_joint_def_init(void)
|
||||
return def;
|
||||
}
|
||||
|
||||
struct phys_weld_joint phys_weld_joint_from_def(struct phys_weld_joint_def def)
|
||||
WeldJoint phys_weld_joint_from_def(WeldJointDesc def)
|
||||
{
|
||||
struct phys_weld_joint res = ZI;
|
||||
WeldJoint res = ZI;
|
||||
res.e0 = def.e0;
|
||||
res.e1 = def.e1;
|
||||
res.linear_spring_hz = def.linear_spring_hz;
|
||||
@ -932,10 +932,10 @@ struct phys_weld_joint phys_weld_joint_from_def(struct phys_weld_joint_def def)
|
||||
return res;
|
||||
}
|
||||
|
||||
void phys_prepare_weld_joints(struct phys_step_ctx *ctx)
|
||||
void phys_prepare_weld_joints(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
@ -943,7 +943,7 @@ void phys_prepare_weld_joints(struct phys_step_ctx *ctx)
|
||||
|
||||
/* TODO: Lookup and disable collision for any contacts between e0 & e1? */
|
||||
|
||||
struct phys_weld_joint *joint = &joint_ent->weld_joint_data;
|
||||
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);
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
@ -981,16 +981,16 @@ void phys_prepare_weld_joints(struct phys_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_warm_start_weld_joints(struct phys_step_ctx *ctx)
|
||||
void phys_warm_start_weld_joints(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
struct phys_weld_joint *joint = &joint_ent->weld_joint_data;
|
||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||
|
||||
#if 0
|
||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
@ -1018,16 +1018,16 @@ void phys_warm_start_weld_joints(struct phys_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_solve_weld_joints(struct phys_step_ctx *ctx, f32 dt)
|
||||
void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
struct phys_weld_joint *joint = &joint_ent->weld_joint_data;
|
||||
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);
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
@ -1098,10 +1098,10 @@ INTERNAL Xform get_derived_xform(struct sim_ent *ent, f32 dt)
|
||||
return xf;
|
||||
}
|
||||
|
||||
void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt)
|
||||
void phys_integrate_forces(PhysStepCtx *ctx, f32 dt)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
@ -1140,10 +1140,10 @@ void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt)
|
||||
}
|
||||
}
|
||||
|
||||
void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt)
|
||||
void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
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];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
@ -1158,11 +1158,11 @@ void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt)
|
||||
* Earliest time of impact
|
||||
* ========================== */
|
||||
|
||||
f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations)
|
||||
f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
struct space *space = ctx->sim_step_ctx->accel->space;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
Space *space = ctx->sim_step_ctx->accel->space;
|
||||
f32 smallest_t = 1;
|
||||
|
||||
for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) {
|
||||
@ -1181,8 +1181,8 @@ f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tole
|
||||
Aabb aabb_t1 = collider_aabb_from_collider(&e0_collider, e0_xf_t1);
|
||||
Aabb combined_aabb = collider_aabb_from_combined_aabb(aabb_t0, aabb_t1);
|
||||
|
||||
struct space_iter iter = space_iter_begin_aabb(space, combined_aabb);
|
||||
struct space_entry *entry;
|
||||
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);
|
||||
if (!sim_ent_should_simulate(e1)) continue;
|
||||
@ -1209,17 +1209,17 @@ f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tole
|
||||
* Space
|
||||
* ========================== */
|
||||
|
||||
void phys_update_aabbs(struct phys_step_ctx *ctx)
|
||||
void phys_update_aabbs(PhysStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
struct space *space = ctx->sim_step_ctx->accel->space;
|
||||
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];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
if (ent->local_collider.count > 0) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
struct space_entry *space_entry = space_entry_from_handle(space, ent->space_handle);
|
||||
SpaceEntry *space_entry = space_entry_from_handle(space, ent->space_handle);
|
||||
if (!space_entry->valid) {
|
||||
space_entry = space_entry_alloc(space, ent->id);
|
||||
ent->space_handle = space_entry->handle;
|
||||
@ -1235,11 +1235,11 @@ void phys_update_aabbs(struct phys_step_ctx *ctx)
|
||||
* ========================== */
|
||||
|
||||
/* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */
|
||||
void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
||||
void phys_step(PhysStepCtx *ctx, f32 timestep)
|
||||
{
|
||||
__prof;
|
||||
phys_integrate_forces(ctx, timestep);
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
u64 phys_iteration = ss->phys_iteration;
|
||||
|
||||
phys_update_aabbs(ctx);
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
struct space;
|
||||
struct sim_ent_lookup;
|
||||
struct sim_step_ctx;
|
||||
|
||||
struct phys_contact_constraint;
|
||||
struct phys_collision_data {
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
typedef struct CollisionData CollisionData;
|
||||
struct CollisionData {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
V2 point;
|
||||
V2 normal; /* Normal of the collision from e0 to e1 */
|
||||
V2 vrel; /* Relative velocity at point of collision */
|
||||
@ -14,12 +10,14 @@ struct phys_collision_data {
|
||||
};
|
||||
|
||||
/* Callback can return 1 to prevent the physics system from resolving */
|
||||
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_sim_step_ctx) b32 name(struct phys_collision_data *arg_collision_data, struct sim_step_ctx *arg_sim_step_ctx)
|
||||
typedef struct SimStepCtx SimStepCtx;
|
||||
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_sim_step_ctx) b32 name(CollisionData *arg_collision_data, SimStepCtx *arg_sim_step_ctx)
|
||||
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision_data, ctx);
|
||||
|
||||
/* Structure containing data used for a single physics step */
|
||||
struct phys_step_ctx {
|
||||
struct sim_step_ctx *sim_step_ctx;
|
||||
typedef struct PhysStepCtx PhysStepCtx;
|
||||
struct PhysStepCtx {
|
||||
SimStepCtx *sim_step_ctx;
|
||||
phys_collision_callback_func *collision_callback;
|
||||
};
|
||||
|
||||
@ -27,7 +25,8 @@ struct phys_step_ctx {
|
||||
* Contact
|
||||
* ========================== */
|
||||
|
||||
struct phys_contact_point {
|
||||
typedef struct ContactPoint ContactPoint;
|
||||
struct ContactPoint {
|
||||
/* Contact point relative to the center of each entity.
|
||||
*
|
||||
* NOTE: We use fixed (non-rotated) points relative to the entities
|
||||
@ -52,12 +51,13 @@ struct phys_contact_point {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct phys_contact_constraint {
|
||||
typedef struct ContactConstraint ContactConstraint;
|
||||
struct ContactConstraint {
|
||||
u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */
|
||||
b32 skip_solve;
|
||||
b32 wrong_dir;
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
f32 inv_m0;
|
||||
f32 inv_m1;
|
||||
f32 inv_i0;
|
||||
@ -65,7 +65,7 @@ struct phys_contact_constraint {
|
||||
|
||||
V2 normal; /* Normal vector of collision from e0 -> e1 */
|
||||
u64 last_iteration;
|
||||
struct phys_contact_point points[2];
|
||||
ContactPoint points[2];
|
||||
u32 num_points;
|
||||
|
||||
f32 friction;
|
||||
@ -73,12 +73,13 @@ struct phys_contact_constraint {
|
||||
f32 pushout_velocity;
|
||||
};
|
||||
|
||||
struct phys_collision_debug {
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
typedef struct CollisionDebugData CollisionDebugData;
|
||||
struct CollisionDebugData {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
CLD_CollisionResult res;
|
||||
|
||||
struct phys_contact_point points[2];
|
||||
ContactPoint points[2];
|
||||
u32 num_points;
|
||||
|
||||
V2 closest0;
|
||||
@ -88,26 +89,28 @@ struct phys_collision_debug {
|
||||
Xform xf1;
|
||||
};
|
||||
|
||||
void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration);
|
||||
void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration);
|
||||
void phys_warm_start_contacts(struct phys_step_ctx *ctx);
|
||||
void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias);
|
||||
void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration);
|
||||
void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration);
|
||||
void phys_warm_start_contacts(PhysStepCtx *ctx);
|
||||
void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias);
|
||||
|
||||
/* ========================== *
|
||||
* Motor joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_motor_joint_def {
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
typedef struct MotorJointDesc MotorJointDesc;
|
||||
struct MotorJointDesc {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
};
|
||||
|
||||
struct phys_motor_joint {
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
typedef struct MotorJoint MotorJoint;
|
||||
struct MotorJoint {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
@ -127,18 +130,19 @@ struct phys_motor_joint {
|
||||
f32 angular_mass;
|
||||
};
|
||||
|
||||
struct phys_motor_joint_def phys_motor_joint_def_init(void);
|
||||
struct phys_motor_joint phys_motor_joint_from_def(struct phys_motor_joint_def def);
|
||||
void phys_prepare_motor_joints(struct phys_step_ctx *ctx);
|
||||
void phys_warm_start_motor_joints(struct phys_step_ctx *ctx);
|
||||
void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt);
|
||||
MotorJointDesc phys_motor_joint_def_init(void);
|
||||
MotorJoint phys_motor_joint_from_def(MotorJointDesc def);
|
||||
void phys_prepare_motor_joints(PhysStepCtx *ctx);
|
||||
void phys_warm_start_motor_joints(PhysStepCtx *ctx);
|
||||
void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
/* ========================== *
|
||||
* Mouse joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_mouse_joint_def {
|
||||
struct sim_ent_id target;
|
||||
typedef struct MouseJointDesc MouseJointDesc;
|
||||
struct MouseJointDesc {
|
||||
EntId target;
|
||||
V2 point_local_start;
|
||||
V2 point_end;
|
||||
f32 linear_spring_hz;
|
||||
@ -148,8 +152,9 @@ struct phys_mouse_joint_def {
|
||||
f32 max_force;
|
||||
};
|
||||
|
||||
struct phys_mouse_joint {
|
||||
struct sim_ent_id target;
|
||||
typedef struct MouseJoint MouseJoint;
|
||||
struct MouseJoint {
|
||||
EntId target;
|
||||
V2 point_local_start;
|
||||
V2 point_end;
|
||||
f32 linear_spring_hz;
|
||||
@ -167,19 +172,20 @@ struct phys_mouse_joint {
|
||||
Xform linear_mass_xf;
|
||||
};
|
||||
|
||||
struct phys_mouse_joint_def phys_mouse_joint_def_init(void);
|
||||
struct phys_mouse_joint phys_mouse_joint_from_def(struct phys_mouse_joint_def def);
|
||||
void phys_prepare_mouse_joints(struct phys_step_ctx *ctx);
|
||||
void phys_warm_start_mouse_joints(struct phys_step_ctx *ctx);
|
||||
void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt);
|
||||
MouseJointDesc phys_mouse_joint_def_init(void);
|
||||
MouseJoint phys_mouse_joint_from_def(MouseJointDesc def);
|
||||
void phys_prepare_mouse_joints(PhysStepCtx *ctx);
|
||||
void phys_warm_start_mouse_joints(PhysStepCtx *ctx);
|
||||
void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
/* ========================== *
|
||||
* Weld joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_weld_joint_def {
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
typedef struct WeldJointDesc WeldJointDesc;
|
||||
struct WeldJointDesc {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
|
||||
/* The xform that transforms a point in e0's space into the desired e1 space
|
||||
* (IE `xf` * V2FromXY(0, 0) should evaluate to the local point that e1's origin will lie) */
|
||||
@ -191,9 +197,10 @@ struct phys_weld_joint_def {
|
||||
f32 angular_spring_damp;
|
||||
};
|
||||
|
||||
struct phys_weld_joint {
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
typedef struct WeldJoint WeldJoint;
|
||||
struct WeldJoint {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
Xform xf0_to_xf1;
|
||||
|
||||
f32 linear_spring_hz;
|
||||
@ -212,33 +219,33 @@ struct phys_weld_joint {
|
||||
f32 angular_impulse1;
|
||||
};
|
||||
|
||||
struct phys_weld_joint_def phys_weld_joint_def_init(void);
|
||||
struct phys_weld_joint phys_weld_joint_from_def(struct phys_weld_joint_def def);
|
||||
void phys_prepare_weld_joints(struct phys_step_ctx *ctx);
|
||||
void phys_warm_start_weld_joints(struct phys_step_ctx *ctx);
|
||||
void phys_solve_weld_joints(struct phys_step_ctx *ctx, f32 dt);
|
||||
WeldJointDesc phys_weld_joint_def_init(void);
|
||||
WeldJoint phys_weld_joint_from_def(WeldJointDesc def);
|
||||
void phys_prepare_weld_joints(PhysStepCtx *ctx);
|
||||
void phys_warm_start_weld_joints(PhysStepCtx *ctx);
|
||||
void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
/* ========================== *
|
||||
* Integration
|
||||
* ========================== */
|
||||
|
||||
void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt);
|
||||
void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt);
|
||||
void phys_integrate_forces(PhysStepCtx *ctx, f32 dt);
|
||||
void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
/* ========================== *
|
||||
* Earliest time of impact
|
||||
* ========================== */
|
||||
|
||||
f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations);
|
||||
f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations);
|
||||
|
||||
/* ========================== *
|
||||
* Space
|
||||
* ========================== */
|
||||
|
||||
void phys_update_aabbs(struct phys_step_ctx *ctx);
|
||||
void phys_update_aabbs(PhysStepCtx *ctx);
|
||||
|
||||
/* ========================== *
|
||||
* Step
|
||||
* ========================== */
|
||||
|
||||
void phys_step(struct phys_step_ctx *ctx, f32 timestep);
|
||||
void phys_step(PhysStepCtx *ctx, f32 timestep);
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
/* FIXME: Default space entry & cell pointers to nil */
|
||||
|
||||
/* Offset in bytes from start of space struct to start of entry array (assume adjacently allocated) */
|
||||
#define SPACE_ENTRIES_OFFSET (sizeof(struct space) + (sizeof(struct space) % alignof(struct space_entry)))
|
||||
#define SPACE_ENTRIES_OFFSET (sizeof(Space) + (sizeof(Space) % alignof(SpaceEntry)))
|
||||
|
||||
/* Accessed via sim_ent_nil() */
|
||||
READONLY struct space_entry _g_space_entry_nil = { .valid = 0 };
|
||||
READONLY struct space_cell _g_space_cell_nil = { .valid = 0 };
|
||||
READONLY struct space _g_space_nil = { .valid = 0 };
|
||||
READONLY SpaceEntry _g_space_entry_nil = { .valid = 0 };
|
||||
READONLY SpaceCell _g_space_cell_nil = { .valid = 0 };
|
||||
READONLY Space _g_space_nil = { .valid = 0 };
|
||||
|
||||
/* ========================== *
|
||||
* Space alloc
|
||||
@ -15,50 +15,50 @@ READONLY struct space _g_space_nil = { .valid = 0 };
|
||||
/* NOTE:
|
||||
* The number of bins determines how often tiles will collide in the spatial hash.
|
||||
* For example, at `num_bins_sqrt` = 256 (65536 bins), tiles <1, 1>, <1, 257>, and <257, 257> will collide. */
|
||||
struct space *space_alloc(f32 cell_size, u32 num_bins_sqrt)
|
||||
Space *space_alloc(f32 cell_size, u32 num_bins_sqrt)
|
||||
{
|
||||
struct space *space;
|
||||
Space *space;
|
||||
{
|
||||
Arena *arena = arena_alloc(GIBI(64));
|
||||
space = arena_push(arena, struct space);
|
||||
space = arena_push(arena, Space);
|
||||
space->entry_arena = arena;
|
||||
}
|
||||
|
||||
space->valid = 1;
|
||||
space->entries = arena_push_dry(space->entry_arena, struct space_entry);
|
||||
space->entries = arena_push_dry(space->entry_arena, SpaceEntry);
|
||||
|
||||
space->cell_arena = arena_alloc(GIBI(64));
|
||||
space->cell_size = cell_size;
|
||||
space->num_bins = num_bins_sqrt * num_bins_sqrt;
|
||||
space->num_bins_sqrt = num_bins_sqrt;
|
||||
space->bins = arena_push_array(space->cell_arena, struct space_cell_bin, space->num_bins);
|
||||
space->bins = arena_push_array(space->cell_arena, SpaceCellBin, space->num_bins);
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
void space_release(struct space *space)
|
||||
void space_release(Space *space)
|
||||
{
|
||||
arena_release(space->cell_arena);
|
||||
arena_release(space->entry_arena);
|
||||
}
|
||||
|
||||
void space_reset(struct space *space)
|
||||
void space_reset(Space *space)
|
||||
{
|
||||
arena_pop_to(space->entry_arena, (u64)space->entries - (u64)arena_base(space->entry_arena));
|
||||
arena_reset(space->cell_arena);
|
||||
space->bins = arena_push_array(space->cell_arena, struct space_cell_bin, space->num_bins);
|
||||
space->bins = arena_push_array(space->cell_arena, SpaceCellBin, space->num_bins);
|
||||
space->num_entries_reserved = 0;
|
||||
space->first_free_cell = 0;
|
||||
space->first_free_cell_node = 0;
|
||||
space->first_free_entry = 0;
|
||||
}
|
||||
|
||||
struct space *space_from_entry(struct space_entry *entry)
|
||||
Space *space_from_entry(SpaceEntry *entry)
|
||||
{
|
||||
if (entry->valid) {
|
||||
u64 first_entry_addr = (u64)(entry - entry->handle.idx);
|
||||
struct space *space = (struct space *)(first_entry_addr - SPACE_ENTRIES_OFFSET);
|
||||
ASSERT(space->entries == (struct space_entry *)first_entry_addr);
|
||||
Space *space = (Space *)(first_entry_addr - SPACE_ENTRIES_OFFSET);
|
||||
ASSERT(space->entries == (SpaceEntry *)first_entry_addr);
|
||||
return space;
|
||||
} else {
|
||||
return space_nil();
|
||||
@ -78,7 +78,7 @@ INTERNAL V2i32 world_to_cell_coords(f32 cell_size, V2 world_pos)
|
||||
return V2i32FromXY((i32)x, (i32)y);
|
||||
}
|
||||
|
||||
INTERNAL i32 cell_coords_to_bin_index(struct space *space, V2i32 cell_pos)
|
||||
INTERNAL i32 cell_coords_to_bin_index(Space *space, V2i32 cell_pos)
|
||||
{
|
||||
i32 num_bins_sqrt = space->num_bins_sqrt;
|
||||
|
||||
@ -100,12 +100,12 @@ INTERNAL i32 cell_coords_to_bin_index(struct space *space, V2i32 cell_pos)
|
||||
return bin_index;
|
||||
}
|
||||
|
||||
struct space_cell *space_get_cell(struct space *space, V2i32 cell_pos)
|
||||
SpaceCell *space_get_cell(Space *space, V2i32 cell_pos)
|
||||
{
|
||||
i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
|
||||
struct space_cell_bin *bin = &space->bins[bin_index];
|
||||
struct space_cell *res = space_cell_nil();
|
||||
for (struct space_cell *n = bin->first_cell; n; n = n->next_in_bin) {
|
||||
SpaceCellBin *bin = &space->bins[bin_index];
|
||||
SpaceCell *res = space_cell_nil();
|
||||
for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin) {
|
||||
if (v2i32_eq(n->pos, cell_pos)) {
|
||||
res = n;
|
||||
break;
|
||||
@ -114,15 +114,15 @@ struct space_cell *space_get_cell(struct space *space, V2i32 cell_pos)
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERNAL void space_cell_node_alloc(V2i32 cell_pos, struct space_entry *entry)
|
||||
INTERNAL void space_cell_node_alloc(V2i32 cell_pos, SpaceEntry *entry)
|
||||
{
|
||||
struct space *space = space_from_entry(entry);
|
||||
Space *space = space_from_entry(entry);
|
||||
i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
|
||||
struct space_cell_bin *bin = &space->bins[bin_index];
|
||||
SpaceCellBin *bin = &space->bins[bin_index];
|
||||
|
||||
/* Find existing cell */
|
||||
struct space_cell *cell = 0;
|
||||
for (struct space_cell *n = bin->first_cell; n; n = n->next_in_bin) {
|
||||
SpaceCell *cell = 0;
|
||||
for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin) {
|
||||
if (v2i32_eq(n->pos, cell_pos)) {
|
||||
cell = n;
|
||||
break;
|
||||
@ -135,7 +135,7 @@ INTERNAL void space_cell_node_alloc(V2i32 cell_pos, struct space_entry *entry)
|
||||
cell = space->first_free_cell;
|
||||
space->first_free_cell = cell->next_free;
|
||||
} else {
|
||||
cell = arena_push_no_zero(space->cell_arena, struct space_cell);
|
||||
cell = arena_push_no_zero(space->cell_arena, SpaceCell);
|
||||
}
|
||||
MEMZERO_STRUCT(cell);
|
||||
if (bin->last_cell) {
|
||||
@ -151,13 +151,13 @@ INTERNAL void space_cell_node_alloc(V2i32 cell_pos, struct space_entry *entry)
|
||||
}
|
||||
|
||||
/* Allocate node */
|
||||
struct space_cell_node *node;
|
||||
SpaceCellNode *node;
|
||||
{
|
||||
if (space->first_free_cell_node) {
|
||||
node = space->first_free_cell_node;
|
||||
space->first_free_cell_node = node->next_free;
|
||||
} else {
|
||||
node = arena_push_no_zero(space->cell_arena, struct space_cell_node);
|
||||
node = arena_push_no_zero(space->cell_arena, SpaceCellNode);
|
||||
}
|
||||
MEMZERO_STRUCT(node);
|
||||
}
|
||||
@ -183,17 +183,17 @@ INTERNAL void space_cell_node_alloc(V2i32 cell_pos, struct space_entry *entry)
|
||||
entry->last_node = node;
|
||||
}
|
||||
|
||||
INTERNAL void space_cell_node_release(struct space_cell_node *n)
|
||||
INTERNAL void space_cell_node_release(SpaceCellNode *n)
|
||||
{
|
||||
struct space_cell *cell = n->cell;
|
||||
struct space_entry *entry = n->entry;
|
||||
struct space *space = space_from_entry(entry);
|
||||
struct space_cell_bin *bin = cell->bin;
|
||||
SpaceCell *cell = n->cell;
|
||||
SpaceEntry *entry = n->entry;
|
||||
Space *space = space_from_entry(entry);
|
||||
SpaceCellBin *bin = cell->bin;
|
||||
|
||||
/* Remove from entry list */
|
||||
{
|
||||
struct space_cell_node *prev = n->prev_in_entry;
|
||||
struct space_cell_node *next = n->next_in_entry;
|
||||
SpaceCellNode *prev = n->prev_in_entry;
|
||||
SpaceCellNode *next = n->next_in_entry;
|
||||
if (prev) {
|
||||
prev->next_in_entry = next;
|
||||
} else {
|
||||
@ -208,8 +208,8 @@ INTERNAL void space_cell_node_release(struct space_cell_node *n)
|
||||
|
||||
/* Remove from cell list */
|
||||
{
|
||||
struct space_cell_node *prev = n->prev_in_cell;
|
||||
struct space_cell_node *next = n->next_in_cell;
|
||||
SpaceCellNode *prev = n->prev_in_cell;
|
||||
SpaceCellNode *next = n->next_in_cell;
|
||||
if (prev) {
|
||||
prev->next_in_cell = next;
|
||||
} else {
|
||||
@ -225,8 +225,8 @@ INTERNAL void space_cell_node_release(struct space_cell_node *n)
|
||||
/* If cell is now empty, release it */
|
||||
if (!cell->first_node && !cell->last_node) {
|
||||
/* Remove from bin */
|
||||
struct space_cell *prev = cell->prev_in_bin;
|
||||
struct space_cell *next = cell->next_in_bin;
|
||||
SpaceCell *prev = cell->prev_in_bin;
|
||||
SpaceCell *next = cell->next_in_bin;
|
||||
if (prev) {
|
||||
prev->next_in_bin = next;
|
||||
} else {
|
||||
@ -253,12 +253,12 @@ INTERNAL void space_cell_node_release(struct space_cell_node *n)
|
||||
* Entry
|
||||
* ========================== */
|
||||
|
||||
struct space_entry *space_entry_from_handle(struct space *space, struct space_entry_handle handle)
|
||||
SpaceEntry *space_entry_from_handle(Space *space, SpaceEntryHandle handle)
|
||||
{
|
||||
struct space_entry *entry = space_entry_nil();
|
||||
SpaceEntry *entry = space_entry_nil();
|
||||
|
||||
if (handle.gen > 0 && handle.idx < space->num_entries_reserved) {
|
||||
struct space_entry *tmp = &space->entries[handle.idx];
|
||||
SpaceEntry *tmp = &space->entries[handle.idx];
|
||||
if (tmp->handle.gen == handle.gen) {
|
||||
entry = tmp;
|
||||
}
|
||||
@ -267,16 +267,16 @@ struct space_entry *space_entry_from_handle(struct space *space, struct space_en
|
||||
return entry;
|
||||
}
|
||||
|
||||
struct space_entry *space_entry_alloc(struct space *space, struct sim_ent_id ent)
|
||||
SpaceEntry *space_entry_alloc(Space *space, EntId ent)
|
||||
{
|
||||
struct space_entry *entry = 0;
|
||||
struct space_entry_handle handle = ZI;
|
||||
SpaceEntry *entry = 0;
|
||||
SpaceEntryHandle handle = ZI;
|
||||
if (space->first_free_entry) {
|
||||
entry = space->first_free_entry;
|
||||
space->first_free_entry = entry->next_free;
|
||||
handle = entry->handle;
|
||||
} else {
|
||||
entry = arena_push_no_zero(space->entry_arena, struct space_entry);
|
||||
entry = arena_push_no_zero(space->entry_arena, SpaceEntry);
|
||||
handle.idx = space->num_entries_reserved;
|
||||
handle.gen = 1;
|
||||
++space->num_entries_reserved;
|
||||
@ -288,27 +288,27 @@ struct space_entry *space_entry_alloc(struct space *space, struct sim_ent_id ent
|
||||
return entry;
|
||||
}
|
||||
|
||||
void space_entry_release(struct space_entry *entry)
|
||||
void space_entry_release(SpaceEntry *entry)
|
||||
{
|
||||
/* Release nodes */
|
||||
struct space_cell_node *n = entry->first_node;
|
||||
SpaceCellNode *n = entry->first_node;
|
||||
while (n) {
|
||||
struct space_cell_node *next = n->next_in_entry;
|
||||
SpaceCellNode *next = n->next_in_entry;
|
||||
/* TODO: More efficient batch release that doesn't care about maintaining entry list */
|
||||
space_cell_node_release(n);
|
||||
n = next;
|
||||
}
|
||||
|
||||
struct space *space = space_from_entry(entry);
|
||||
Space *space = space_from_entry(entry);
|
||||
entry->next_free = space->first_free_entry;
|
||||
entry->valid = 0;
|
||||
++entry->handle.gen;
|
||||
space->first_free_entry = entry;
|
||||
}
|
||||
|
||||
void space_entry_update_aabb(struct space_entry *entry, Aabb new_aabb)
|
||||
void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb)
|
||||
{
|
||||
struct space *space = space_from_entry(entry);
|
||||
Space *space = space_from_entry(entry);
|
||||
f32 cell_size = space->cell_size;
|
||||
|
||||
V2i32 old_cell_p0 = V2i32FromXY(0, 0);
|
||||
@ -323,13 +323,13 @@ void space_entry_update_aabb(struct space_entry *entry, Aabb new_aabb)
|
||||
V2i32 new_cell_p1 = world_to_cell_coords(cell_size, new_aabb.p1);
|
||||
|
||||
/* Release outdated nodes */
|
||||
struct space_cell_node *n = entry->first_node;
|
||||
SpaceCellNode *n = entry->first_node;
|
||||
while (n) {
|
||||
struct space_cell *cell = n->cell;
|
||||
SpaceCell *cell = n->cell;
|
||||
V2i32 cell_pos = cell->pos;
|
||||
if (cell_pos.x < new_cell_p0.x || cell_pos.x > new_cell_p1.x || cell_pos.y < new_cell_p0.y || cell_pos.y > new_cell_p1.y) {
|
||||
/* Cell is outside of new AABB */
|
||||
struct space_cell_node *next = n->next_in_entry;
|
||||
SpaceCellNode *next = n->next_in_entry;
|
||||
space_cell_node_release(n);
|
||||
n = next;
|
||||
} else {
|
||||
@ -354,9 +354,9 @@ void space_entry_update_aabb(struct space_entry *entry, Aabb new_aabb)
|
||||
* Iter
|
||||
* ========================== */
|
||||
|
||||
struct space_iter space_iter_begin_aabb(struct space *space, Aabb aabb)
|
||||
SpaceIter space_iter_begin_aabb(Space *space, Aabb aabb)
|
||||
{
|
||||
struct space_iter iter = ZI;
|
||||
SpaceIter iter = ZI;
|
||||
f32 cell_size = space->cell_size;
|
||||
|
||||
iter.space = space;
|
||||
@ -377,16 +377,16 @@ struct space_iter space_iter_begin_aabb(struct space *space, Aabb aabb)
|
||||
return iter;
|
||||
}
|
||||
|
||||
struct space_entry *space_iter_next(struct space_iter *iter)
|
||||
SpaceEntry *space_iter_next(SpaceIter *iter)
|
||||
{
|
||||
struct space *space = iter->space;
|
||||
Space *space = iter->space;
|
||||
Aabb iter_aabb = iter->aabb;
|
||||
V2i32 cell_start = iter->cell_start;
|
||||
V2i32 cell_end = iter->cell_end;
|
||||
V2i32 cell_cur = iter->cell_cur;
|
||||
i32 span = cell_end.x - cell_start.x;
|
||||
|
||||
struct space_cell_node *next_node = 0;
|
||||
SpaceCellNode *next_node = 0;
|
||||
if (cell_cur.x >= cell_start.x && cell_cur.x <= cell_end.x && cell_cur.y >= cell_start.y && cell_cur.y <= cell_end.y) {
|
||||
/* Started */
|
||||
ASSERT(iter->prev != 0);
|
||||
@ -398,7 +398,7 @@ struct space_entry *space_iter_next(struct space_iter *iter)
|
||||
|
||||
for (;;) {
|
||||
if (next_node) {
|
||||
struct space_entry *entry = next_node->entry;
|
||||
SpaceEntry *entry = next_node->entry;
|
||||
Aabb entry_aabb = entry->aabb;
|
||||
if (collider_test_aabb(entry_aabb, iter_aabb)) {
|
||||
break;
|
||||
@ -414,7 +414,7 @@ struct space_entry *space_iter_next(struct space_iter *iter)
|
||||
cell_cur.y += nexty;
|
||||
cell_cur.x += (cell_cur.x == 0);
|
||||
cell_cur.y += (cell_cur.y == 0);
|
||||
struct space_cell *cell = space_get_cell(space, cell_cur);
|
||||
SpaceCell *cell = space_get_cell(space, cell_cur);
|
||||
next_node = cell->first_node;
|
||||
} else {
|
||||
/* Reached end of iter */
|
||||
|
||||
@ -1,104 +1,112 @@
|
||||
struct space_cell_bin;
|
||||
|
||||
struct space_entry_handle {
|
||||
typedef struct SpaceEntryHandle SpaceEntryHandle;
|
||||
struct SpaceEntryHandle {
|
||||
u64 idx;
|
||||
u64 gen;
|
||||
};
|
||||
|
||||
struct space_entry {
|
||||
typedef struct SpaceCellNode SpaceCellNode;
|
||||
typedef struct SpaceEntry SpaceEntry;
|
||||
struct SpaceEntry {
|
||||
b32 valid;
|
||||
struct space_entry_handle handle;
|
||||
SpaceEntryHandle handle;
|
||||
|
||||
struct space_cell_node *first_node;
|
||||
struct space_cell_node *last_node;
|
||||
SpaceCellNode *first_node;
|
||||
SpaceCellNode *last_node;
|
||||
|
||||
Aabb aabb;
|
||||
struct sim_ent_id ent;
|
||||
EntId ent;
|
||||
|
||||
struct space_entry *next_free;
|
||||
SpaceEntry *next_free;
|
||||
};
|
||||
|
||||
/* Links a cell to a entry.
|
||||
* Acts as both a node in the list of entries contained by the cell, and a node in the list of cells containing the entry. */
|
||||
struct space_cell_node {
|
||||
struct space_entry *entry;
|
||||
struct space_cell *cell;
|
||||
typedef struct SpaceCell SpaceCell;
|
||||
typedef struct SpaceCellNode SpaceCellNode;
|
||||
struct SpaceCellNode {
|
||||
SpaceEntry *entry;
|
||||
SpaceCell *cell;
|
||||
|
||||
/* For list of all entries contained by cell */
|
||||
struct space_cell_node *prev_in_cell;
|
||||
struct space_cell_node *next_in_cell;
|
||||
SpaceCellNode *prev_in_cell;
|
||||
SpaceCellNode *next_in_cell;
|
||||
|
||||
/* For list of all cells containing entry */
|
||||
struct space_cell_node *prev_in_entry;
|
||||
struct space_cell_node *next_in_entry;
|
||||
SpaceCellNode *prev_in_entry;
|
||||
SpaceCellNode *next_in_entry;
|
||||
|
||||
struct space_cell_node *next_free;
|
||||
SpaceCellNode *next_free;
|
||||
};
|
||||
|
||||
struct space_cell {
|
||||
typedef struct SpaceCellBin SpaceCellBin;
|
||||
typedef struct SpaceCell SpaceCell;
|
||||
struct SpaceCell {
|
||||
b32 valid;
|
||||
V2i32 pos;
|
||||
|
||||
struct space_cell_node *first_node;
|
||||
struct space_cell_node *last_node;
|
||||
SpaceCellNode *first_node;
|
||||
SpaceCellNode *last_node;
|
||||
|
||||
struct space_cell_bin *bin;
|
||||
struct space_cell *prev_in_bin;
|
||||
struct space_cell *next_in_bin;
|
||||
SpaceCellBin *bin;
|
||||
SpaceCell *prev_in_bin;
|
||||
SpaceCell *next_in_bin;
|
||||
|
||||
struct space_cell *next_free;
|
||||
SpaceCell *next_free;
|
||||
};
|
||||
|
||||
struct space_cell_bin {
|
||||
struct space_cell *first_cell;
|
||||
struct space_cell *last_cell;
|
||||
typedef struct SpaceCellBin SpaceCellBin;
|
||||
struct SpaceCellBin {
|
||||
SpaceCell *first_cell;
|
||||
SpaceCell *last_cell;
|
||||
};
|
||||
|
||||
struct space {
|
||||
typedef struct Space Space;
|
||||
struct Space {
|
||||
b32 valid;
|
||||
f32 cell_size;
|
||||
|
||||
Arena *cell_arena;
|
||||
struct space_cell_bin *bins;
|
||||
SpaceCellBin *bins;
|
||||
i32 num_bins;
|
||||
i32 num_bins_sqrt;
|
||||
struct space_cell *first_free_cell;
|
||||
struct space_cell_node *first_free_cell_node;
|
||||
SpaceCell *first_free_cell;
|
||||
SpaceCellNode *first_free_cell_node;
|
||||
|
||||
Arena *entry_arena;
|
||||
u64 num_entries_reserved;
|
||||
struct space_entry *entries;
|
||||
struct space_entry *first_free_entry;
|
||||
SpaceEntry *entries;
|
||||
SpaceEntry *first_free_entry;
|
||||
};
|
||||
|
||||
struct space_iter {
|
||||
typedef struct SpaceIter SpaceIter;
|
||||
struct SpaceIter {
|
||||
Aabb aabb;
|
||||
struct space *space;
|
||||
Space *space;
|
||||
V2i32 cell_start;
|
||||
V2i32 cell_end;
|
||||
V2i32 cell_cur;
|
||||
struct space_cell_node *prev;
|
||||
SpaceCellNode *prev;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Nil
|
||||
* ========================== */
|
||||
|
||||
INLINE struct space_entry *space_entry_nil(void)
|
||||
INLINE SpaceEntry *space_entry_nil(void)
|
||||
{
|
||||
extern READONLY struct space_entry _g_space_entry_nil;
|
||||
extern READONLY SpaceEntry _g_space_entry_nil;
|
||||
return &_g_space_entry_nil;
|
||||
}
|
||||
|
||||
INLINE struct space_cell *space_cell_nil(void)
|
||||
INLINE SpaceCell *space_cell_nil(void)
|
||||
{
|
||||
extern READONLY struct space_cell _g_space_cell_nil;
|
||||
extern READONLY SpaceCell _g_space_cell_nil;
|
||||
return &_g_space_cell_nil;
|
||||
}
|
||||
|
||||
INLINE struct space *space_nil(void)
|
||||
INLINE Space *space_nil(void)
|
||||
{
|
||||
extern READONLY struct space _g_space_nil;
|
||||
extern READONLY Space _g_space_nil;
|
||||
return &_g_space_nil;
|
||||
}
|
||||
|
||||
@ -106,31 +114,31 @@ INLINE struct space *space_nil(void)
|
||||
* Space
|
||||
* ========================== */
|
||||
|
||||
struct space *space_alloc(f32 cell_size, u32 num_bins_sqrt);
|
||||
void space_release(struct space *space);
|
||||
void space_reset(struct space *space);
|
||||
Space *space_alloc(f32 cell_size, u32 num_bins_sqrt);
|
||||
void space_release(Space *space);
|
||||
void space_reset(Space *space);
|
||||
|
||||
struct space *space_from_entry(struct space_entry *entry);
|
||||
Space *space_from_entry(SpaceEntry *entry);
|
||||
|
||||
/* ========================== *
|
||||
* Cell
|
||||
* ========================== */
|
||||
|
||||
struct space_cell *space_get_cell(struct space *space, V2i32 cell_pos);
|
||||
SpaceCell *space_get_cell(Space *space, V2i32 cell_pos);
|
||||
|
||||
/* ========================== *
|
||||
* Entry
|
||||
* ========================== */
|
||||
|
||||
struct space_entry *space_entry_from_handle(struct space *space, struct space_entry_handle handle);
|
||||
struct space_entry *space_entry_alloc(struct space *space, struct sim_ent_id entity);
|
||||
void space_entry_release(struct space_entry *entry);
|
||||
void space_entry_update_aabb(struct space_entry *entry, Aabb new_aabb);
|
||||
SpaceEntry *space_entry_from_handle(Space *space, SpaceEntryHandle handle);
|
||||
SpaceEntry *space_entry_alloc(Space *space, EntId entity);
|
||||
void space_entry_release(SpaceEntry *entry);
|
||||
void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb);
|
||||
|
||||
/* ========================== *
|
||||
* Iter
|
||||
* ========================== */
|
||||
|
||||
struct space_iter space_iter_begin_aabb(struct space *space, Aabb aabb);
|
||||
struct space_entry *space_iter_next(struct space_iter *iter);
|
||||
SpaceIter space_iter_begin_aabb(Space *space, Aabb aabb);
|
||||
SpaceEntry *space_iter_next(SpaceIter *iter);
|
||||
#define space_iter_end(i)
|
||||
|
||||
@ -2,19 +2,19 @@
|
||||
* Sim accel
|
||||
* ========================== */
|
||||
|
||||
struct sim_accel sim_accel_alloc(void)
|
||||
SimAccel sim_accel_alloc(void)
|
||||
{
|
||||
struct sim_accel accel = ZI;
|
||||
SimAccel accel = ZI;
|
||||
accel.space = space_alloc(SPACE_CELL_SIZE, SPACE_CELL_BINS_SQRT);
|
||||
return accel;
|
||||
}
|
||||
|
||||
void sim_accel_release(struct sim_accel *accel)
|
||||
void sim_accel_release(SimAccel *accel)
|
||||
{
|
||||
space_release(accel->space);
|
||||
}
|
||||
|
||||
void sim_accel_reset(struct sim_snapshot *ss, struct sim_accel *accel)
|
||||
void sim_accel_reset(Snapshot *ss, SimAccel *accel)
|
||||
{
|
||||
space_reset(accel->space);
|
||||
|
||||
@ -358,7 +358,7 @@ INTERNAL void test_spawn_entities4(struct sim_ent *parent, V2 pos)
|
||||
e->sprite_tint = RGB32_F(1, 1, 1);
|
||||
}
|
||||
|
||||
INTERNAL void test_spawn_tile(struct sim_snapshot *world, V2 world_pos)
|
||||
INTERNAL void test_spawn_tile(Snapshot *world, V2 world_pos)
|
||||
{
|
||||
#if 0
|
||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||
@ -382,8 +382,8 @@ INTERNAL void test_spawn_tile(struct sim_snapshot *world, V2 world_pos)
|
||||
e->sprite_tint = COLOR_RED;
|
||||
|
||||
{
|
||||
struct sprite_scope *scope = sprite_scope_begin();
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(scope, e->sprite);
|
||||
S_Scope *scope = sprite_scope_begin();
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_await(scope, e->sprite);
|
||||
e->sprite_local_xform = XFORM_TRS(.s = v2_div(sheet->frame_size, PIXELS_PER_UNIT));
|
||||
sprite_scope_end(scope);
|
||||
}
|
||||
@ -431,7 +431,7 @@ INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort_y, arg_a, arg_b, udata)
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||
INTERNAL void test_generate_walls(Snapshot *world)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -495,12 +495,12 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||
i32 wall_dir = -1;
|
||||
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
||||
i32 desired_wall_dir = -1;
|
||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||
TileKind tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y));
|
||||
}
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
|
||||
TileKind top_tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_y == 0) {
|
||||
if (top_chunk->valid) {
|
||||
V2i32 top_tile_local_index = V2i32FromXY(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1);
|
||||
@ -584,13 +584,13 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||
i32 wall_dir = -1;
|
||||
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
||||
i32 desired_wall_dir = -1;
|
||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||
TileKind tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y));
|
||||
}
|
||||
|
||||
if (tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
enum sim_tile_kind left_tile = SIM_TILE_KIND_NONE;
|
||||
TileKind left_tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x == 0) {
|
||||
if (left_chunk->valid) {
|
||||
V2i32 left_tile_local_index = V2i32FromXY(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y);
|
||||
@ -695,9 +695,9 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||
|
||||
|
||||
|
||||
INTERNAL void test_clear_level(struct sim_step_ctx *ctx)
|
||||
INTERNAL void test_clear_level(SimStepCtx *ctx)
|
||||
{
|
||||
struct sim_snapshot *world = ctx->world;
|
||||
Snapshot *world = ctx->world;
|
||||
for (u64 j = 0; j < world->num_ents_reserved; ++j) {
|
||||
struct sim_ent *ent = &world->ents[j];
|
||||
if (ent->valid) {
|
||||
@ -712,7 +712,7 @@ INTERNAL void test_clear_level(struct sim_step_ctx *ctx)
|
||||
|
||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
{
|
||||
struct sim_snapshot *world = step_ctx->world;
|
||||
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);
|
||||
@ -836,19 +836,19 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
* Update
|
||||
* ========================== */
|
||||
|
||||
void sim_step(struct sim_step_ctx *ctx)
|
||||
void sim_step(SimStepCtx *ctx)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
|
||||
b32 is_master = ctx->is_master;
|
||||
struct sim_snapshot *world = ctx->world;
|
||||
Snapshot *world = ctx->world;
|
||||
|
||||
struct sim_client_store *client_store = world->client->store;
|
||||
struct sim_client *world_client = world->client;
|
||||
struct sim_client *user_input_client = ctx->user_input_client;
|
||||
struct sim_client *publish_client = ctx->publish_client;
|
||||
struct sim_client *master_client = ctx->master_client;
|
||||
ClientStore *client_store = world->client->store;
|
||||
Client *world_client = world->client;
|
||||
Client *user_input_client = ctx->user_input_client;
|
||||
Client *publish_client = ctx->publish_client;
|
||||
Client *master_client = ctx->master_client;
|
||||
|
||||
i64 sim_dt_ns = ctx->sim_dt_ns;
|
||||
|
||||
@ -860,7 +860,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
world->sim_time_ns += world->sim_dt_ns;
|
||||
f32 sim_dt = SECONDS_FROM_NS(world->sim_dt_ns);
|
||||
|
||||
struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
|
||||
S_Scope *sprite_frame_scope = sprite_scope_begin();
|
||||
|
||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
root->owner = world->client->player_id;
|
||||
@ -872,7 +872,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
{
|
||||
/* FIXME: Ensure only cmds are synced to master player */
|
||||
for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) {
|
||||
struct sim_client *client = &client_store->clients[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);
|
||||
|
||||
@ -904,7 +904,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
|
||||
/* Sync ents from client */
|
||||
if (player->valid) {
|
||||
struct sim_snapshot *src_ss = sim_snapshot_from_tick(client, world->tick);
|
||||
Snapshot *src_ss = sim_snapshot_from_tick(client, world->tick);
|
||||
if (src_ss->valid) {
|
||||
sim_snapshot_sync_ents(world, src_ss, player->id, 0);
|
||||
}
|
||||
@ -983,7 +983,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
continue;
|
||||
}
|
||||
|
||||
enum sim_cmd_kind kind = cmd_ent->cmd_kind;
|
||||
CmdKind kind = cmd_ent->cmd_kind;
|
||||
switch (kind) {
|
||||
case SIM_CMD_KIND_CONTROL:
|
||||
{
|
||||
@ -991,8 +991,8 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
persist_cmd = 1;
|
||||
|
||||
/* Process control cmd for player */
|
||||
struct sim_control old_control = player->player_control;
|
||||
struct sim_control *control = &player->player_control;
|
||||
ControlData old_control = player->player_control;
|
||||
ControlData *control = &player->player_control;
|
||||
*control = cmd_ent->cmd_control;
|
||||
{
|
||||
u32 flags = control->flags;
|
||||
@ -1170,11 +1170,11 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (sprite_tag_is_nil(ent->sprite)) continue;
|
||||
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
||||
|
||||
/* Update animation */
|
||||
{
|
||||
struct sprite_sheet_span span = sprite_sheet_get_span(sheet, ent->sprite_span_name);
|
||||
S_SheetSpan span = sprite_sheet_get_span(sheet, ent->sprite_span_name);
|
||||
if (ent->animation_last_frame_change_time_ns == 0) {
|
||||
ent->animation_last_frame_change_time_ns = SECONDS_FROM_NS(world->sim_time_ns);
|
||||
}
|
||||
@ -1186,7 +1186,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
}
|
||||
|
||||
if (span.end > span.start) {
|
||||
struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, frame_index);
|
||||
S_SheetFrame frame = sprite_sheet_get_frame(sheet, frame_index);
|
||||
while (time_in_frame > frame.duration) {
|
||||
time_in_frame -= frame.duration;
|
||||
++frame_index;
|
||||
@ -1205,7 +1205,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
#if 0
|
||||
/* Update sprite local xform */
|
||||
{
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("pivot"), ent->animation_frame);
|
||||
S_SheetSlice slice = sprite_sheet_get_slice(sheet, LIT("pivot"), ent->animation_frame);
|
||||
V2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT);
|
||||
|
||||
V2 dir = v2_mul_v2(sprite_size, slice.dir);
|
||||
@ -1223,7 +1223,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
if (ent->sprite_collider_slice.len > 0) {
|
||||
Xform cxf = ent->sprite_local_xform;
|
||||
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame);
|
||||
S_SheetSlice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame);
|
||||
ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect)));
|
||||
}
|
||||
|
||||
@ -1273,12 +1273,12 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
if (!sim_ent_has_prop(ent, SEPROP_ATTACHED)) continue;
|
||||
|
||||
struct sim_ent *parent = sim_ent_from_id(world, ent->parent);
|
||||
struct sprite_tag parent_sprite = parent->sprite;
|
||||
struct sprite_sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite);
|
||||
S_Tag parent_sprite = parent->sprite;
|
||||
S_Sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite);
|
||||
|
||||
Xform parent_sprite_xf = parent->sprite_local_xform;
|
||||
|
||||
struct sprite_sheet_slice attach_slice = sprite_sheet_get_slice(parent_sheet, ent->attach_slice, parent->animation_frame);
|
||||
S_SheetSlice attach_slice = sprite_sheet_get_slice(parent_sheet, ent->attach_slice, parent->animation_frame);
|
||||
V2 attach_pos = xform_mul_v2(parent_sprite_xf, attach_slice.center);
|
||||
V2 attach_dir = xform_basis_mul_v2(parent_sprite_xf, attach_slice.dir);
|
||||
|
||||
@ -1297,7 +1297,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
struct sim_control *control = &ent->control;
|
||||
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);
|
||||
@ -1350,11 +1350,11 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
/* Fire smg */
|
||||
if (sim_ent_has_prop(ent, SEPROP_WEAPON_SMG)) {
|
||||
if (primary_triggered) {
|
||||
struct sprite_tag sprite = ent->sprite;
|
||||
S_Tag sprite = ent->sprite;
|
||||
u32 animation_frame = ent->animation_frame;
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
||||
Xform sprite_local_xform = ent->sprite_local_xform;
|
||||
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
||||
S_SheetSlice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
||||
V2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
|
||||
V2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
||||
|
||||
@ -1397,11 +1397,11 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
/* Fire launcher */
|
||||
if (sim_ent_has_prop(ent, SEPROP_WEAPON_LAUNCHER)) {
|
||||
if (primary_triggered) {
|
||||
struct sprite_tag sprite = ent->sprite;
|
||||
S_Tag sprite = ent->sprite;
|
||||
u32 animation_frame = ent->animation_frame;
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
||||
Xform sprite_local_xform = ent->sprite_local_xform;
|
||||
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
||||
S_SheetSlice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
||||
V2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
|
||||
V2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
||||
|
||||
@ -1458,7 +1458,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
Xform xf0_to_xf1 = xform_mul(xform_invert(xf0), xf1);
|
||||
|
||||
sim_ent_enable_prop(joint_ent, SEPROP_WELD_JOINT);
|
||||
struct phys_weld_joint_def def = phys_weld_joint_def_init();
|
||||
WeldJointDesc def = phys_weld_joint_def_init();
|
||||
def.e0 = ent->id;
|
||||
def.e1 = target->id;
|
||||
def.xf = xf0_to_xf1;
|
||||
@ -1498,7 +1498,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
ent->move_joint = joint_ent->id;
|
||||
|
||||
sim_ent_enable_prop(joint_ent, SEPROP_MOTOR_JOINT);
|
||||
struct phys_motor_joint_def def = phys_motor_joint_def_init();
|
||||
MotorJointDesc def = phys_motor_joint_def_init();
|
||||
def.e0 = joint_ent->id; /* Re-using joint entity as e0 */
|
||||
def.e1 = ent->id;
|
||||
def.correction_rate = 0;
|
||||
@ -1539,7 +1539,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE);
|
||||
ent->aim_joint = joint_ent->id;
|
||||
|
||||
struct phys_motor_joint_def def = phys_motor_joint_def_init();
|
||||
MotorJointDesc def = phys_motor_joint_def_init();
|
||||
def.e0 = joint_ent->id; /* Re-using joint entity as e0 */
|
||||
def.e1 = ent->id;
|
||||
def.max_force = 0;
|
||||
@ -1561,8 +1561,8 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
V2 sprite_hold_pos;
|
||||
V2 sprite_hold_dir;
|
||||
{
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
||||
S_SheetSlice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
|
||||
sprite_hold_pos = slice.center;
|
||||
sprite_hold_dir = slice.dir;
|
||||
}
|
||||
@ -1624,7 +1624,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
|
||||
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->ground_friction_joint);
|
||||
|
||||
struct phys_motor_joint_def def = phys_motor_joint_def_init();
|
||||
MotorJointDesc def = phys_motor_joint_def_init();
|
||||
def.e0 = root->id;
|
||||
def.e1 = ent->id;
|
||||
def.correction_rate = 0;
|
||||
@ -1678,7 +1678,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
}
|
||||
Xform xf = sim_ent_get_xform(target_ent);
|
||||
|
||||
struct phys_mouse_joint_def def = phys_mouse_joint_def_init();
|
||||
MouseJointDesc def = phys_mouse_joint_def_init();
|
||||
def.target = target_ent->id;
|
||||
if (sim_ent_id_eq(joint_ent->mouse_joint_data.target, target_ent->id)) {
|
||||
def.point_local_start = joint_ent->mouse_joint_data.point_local_start;
|
||||
@ -1703,7 +1703,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
* ========================== */
|
||||
|
||||
{
|
||||
struct phys_step_ctx phys = ZI;
|
||||
PhysStepCtx phys = ZI;
|
||||
phys.sim_step_ctx = ctx;
|
||||
phys.collision_callback = on_collision;
|
||||
phys_step(&phys, sim_dt);
|
||||
@ -1916,8 +1916,8 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
* ========================== */
|
||||
|
||||
if (publish_client->valid && world->tick > publish_client->last_tick) {
|
||||
struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
|
||||
struct sim_snapshot *pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick);
|
||||
Snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
|
||||
Snapshot *pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick);
|
||||
|
||||
/* Sync */
|
||||
sim_snapshot_sync_ents(pub_world, world, world_client->player_id, 0);
|
||||
|
||||
@ -1,7 +1,3 @@
|
||||
struct space;
|
||||
struct sim_snapshot;
|
||||
struct sim_snapshot_list;
|
||||
|
||||
/* ========================== *
|
||||
* Sim accel
|
||||
* ========================== */
|
||||
@ -9,29 +5,31 @@ struct sim_snapshot_list;
|
||||
/* Structure used to accelerate up entity lookup (rebuilt every step) */
|
||||
/* TODO: Remove this and do something better. Just a hack to de-couple old sim ctx from step. */
|
||||
|
||||
struct sim_accel {
|
||||
struct space *space;
|
||||
typedef struct SimAccel SimAccel;
|
||||
struct SimAccel {
|
||||
Space *space;
|
||||
};
|
||||
|
||||
struct sim_accel sim_accel_alloc(void);
|
||||
void sim_accel_release(struct sim_accel *accel);
|
||||
void sim_accel_reset(struct sim_snapshot *ss, struct sim_accel *accel);
|
||||
SimAccel sim_accel_alloc(void);
|
||||
void sim_accel_release(SimAccel *accel);
|
||||
void sim_accel_reset(Snapshot *ss, SimAccel *accel);
|
||||
|
||||
/* ========================== *
|
||||
* Sim step
|
||||
* ========================== */
|
||||
|
||||
struct sim_step_ctx {
|
||||
typedef struct SimStepCtx SimStepCtx;
|
||||
struct SimStepCtx {
|
||||
b32 is_master;
|
||||
struct sim_accel *accel;
|
||||
SimAccel *accel;
|
||||
RandState rand; /* TODO: Replace with per-sim rand for deterministic rng */
|
||||
|
||||
struct sim_snapshot *world; /* The world to simulate */
|
||||
Snapshot *world; /* The world to simulate */
|
||||
i64 sim_dt_ns; /* How much sim time should progress */
|
||||
|
||||
struct sim_client *user_input_client; /* The client that contains input from the user thread */
|
||||
struct sim_client *master_client; /* The master client to read snapshots from (nil if world is master) */
|
||||
struct sim_client *publish_client; /* The publish client to write syncable state to (nil if skipping publish) */
|
||||
Client *user_input_client; /* The client that contains input from the user thread */
|
||||
Client *master_client; /* The master client to read snapshots from (nil if world is master) */
|
||||
Client *publish_client; /* The publish client to write syncable state to (nil if skipping publish) */
|
||||
};
|
||||
|
||||
void sim_step(struct sim_step_ctx *ctx);
|
||||
void sim_step(SimStepCtx *ctx);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define SOUND_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../mp3/mp3.h"
|
||||
#include "../resource/resource.h"
|
||||
#include "../asset_cache/asset_cache.h"
|
||||
|
||||
@ -12,7 +12,7 @@ struct sound_task_params {
|
||||
struct sound_task_params_store {
|
||||
struct sound_task_params *head_free;
|
||||
Arena *arena;
|
||||
struct snc_mutex mutex;
|
||||
P_Mutex mutex;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
@ -27,12 +27,12 @@ GLOBAL struct {
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
struct sound_startup_receipt sound_startup(AC_StartupReceipt *asset_cache_sr)
|
||||
SND_StartupReceipt sound_startup(AC_StartupReceipt *asset_cache_sr)
|
||||
{
|
||||
__prof;
|
||||
(UNUSED)asset_cache_sr;
|
||||
G.params.arena = arena_alloc(GIBI(64));
|
||||
return (struct sound_startup_receipt) { 0 };
|
||||
return (SND_StartupReceipt) { 0 };
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -43,7 +43,7 @@ INTERNAL struct sound_task_params *sound_task_params_alloc(void)
|
||||
{
|
||||
struct sound_task_params *p = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
if (G.params.head_free) {
|
||||
p = G.params.head_free;
|
||||
G.params.head_free = p->next_free;
|
||||
@ -57,7 +57,7 @@ INTERNAL struct sound_task_params *sound_task_params_alloc(void)
|
||||
|
||||
INTERNAL void sound_task_params_release(struct sound_task_params *p)
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.params.mutex);
|
||||
P_Lock lock = snc_lock_e(&G.params.mutex);
|
||||
p->next_free = G.params.head_free;
|
||||
G.params.head_free = p;
|
||||
snc_unlock(&lock);
|
||||
@ -67,7 +67,7 @@ INTERNAL void sound_task_params_release(struct sound_task_params *p)
|
||||
* Load
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(sound_load_asset_job, job)
|
||||
INTERNAL P_JobDef(sound_load_asset_job, job)
|
||||
{
|
||||
__prof;
|
||||
struct sound_task_params *params = job.sig;
|
||||
@ -77,7 +77,7 @@ INTERNAL SYS_JOB_DEF(sound_load_asset_job, job)
|
||||
u32 flags = params->flags;
|
||||
|
||||
logf_info("Loading sound \"%F\"", FMT_STR(path));
|
||||
i64 start_ns = sys_time_ns();
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
String error_msg = LIT("Unknown error");
|
||||
|
||||
@ -104,11 +104,11 @@ INTERNAL SYS_JOB_DEF(sound_load_asset_job, job)
|
||||
|
||||
if (decoded.success) {
|
||||
/* Store */
|
||||
struct sound *sound = 0;
|
||||
SND_Sound *sound = 0;
|
||||
i16 *samples = 0;
|
||||
{
|
||||
AC_Store store = asset_cache_store_open();
|
||||
sound = arena_push_no_zero(store.arena, struct sound);
|
||||
sound = arena_push_no_zero(store.arena, SND_Sound);
|
||||
samples = arena_push_array_no_zero(store.arena, i16, decoded.pcm.count);
|
||||
asset_cache_store_close(&store);
|
||||
}
|
||||
@ -120,19 +120,19 @@ INTERNAL SYS_JOB_DEF(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(sys_time_ns() - start_ns)));
|
||||
logf_success("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));
|
||||
|
||||
/* Store */
|
||||
struct sound *sound = 0;
|
||||
SND_Sound *sound = 0;
|
||||
{
|
||||
AC_Store store = asset_cache_store_open();
|
||||
sound = arena_push_no_zero(store.arena, struct sound);
|
||||
sound = arena_push_no_zero(store.arena, SND_Sound);
|
||||
asset_cache_store_close(&store);
|
||||
}
|
||||
*sound = (struct sound) { 0 };
|
||||
*sound = (SND_Sound) { 0 };
|
||||
asset_cache_mark_ready(asset, sound);
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ AC_Asset *sound_load_asset(String path, u32 flags, b32 wait)
|
||||
/* Assemble task params */
|
||||
struct sound_task_params *params = sound_task_params_alloc();
|
||||
if (path.len > (sizeof(params->path_cstr) - 1)) {
|
||||
sys_panic(string_format(scratch.arena,
|
||||
P_Panic(string_format(scratch.arena,
|
||||
LIT("Sound path \"%F\" too long!"),
|
||||
FMT_STR(path)));
|
||||
}
|
||||
@ -170,7 +170,7 @@ AC_Asset *sound_load_asset(String path, u32 flags, b32 wait)
|
||||
|
||||
/* Push task */
|
||||
asset_cache_mark_loading(asset);
|
||||
sys_run(1, sound_load_asset_job, params, SYS_POOL_BACKGROUND, SYS_PRIORITY_LOW, &asset->counter);
|
||||
P_Run(1, sound_load_asset_job, params, P_Pool_Background, P_Priority_Low, &asset->counter);
|
||||
if (wait) {
|
||||
asset_cache_wait(asset);
|
||||
}
|
||||
@ -180,20 +180,20 @@ AC_Asset *sound_load_asset(String path, u32 flags, b32 wait)
|
||||
return asset;
|
||||
}
|
||||
|
||||
struct sound *sound_load_async(String path, u32 flags)
|
||||
SND_Sound *sound_load_async(String path, u32 flags)
|
||||
{
|
||||
__prof;
|
||||
AC_Asset *asset = sound_load_asset(path, flags, 0);
|
||||
struct sound *sound = (struct sound *)asset_cache_get_store_data(asset);
|
||||
SND_Sound *sound = (SND_Sound *)asset_cache_get_store_data(asset);
|
||||
return sound;
|
||||
}
|
||||
|
||||
|
||||
struct sound *sound_load(String path, u32 flags)
|
||||
SND_Sound *sound_load(String path, u32 flags)
|
||||
{
|
||||
__prof;
|
||||
AC_Asset *asset = sound_load_asset(path, flags, 1);
|
||||
asset_cache_wait(asset);
|
||||
struct sound *sound = (struct sound *)asset_cache_get_store_data(asset);
|
||||
SND_Sound *sound = (SND_Sound *)asset_cache_get_store_data(asset);
|
||||
return sound;
|
||||
}
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
#define SOUND_FLAG_NONE 0x0
|
||||
#define SOUND_FLAG_STEREO 0x1
|
||||
|
||||
struct sound {
|
||||
typedef struct SND_Sound SND_Sound;
|
||||
struct SND_Sound {
|
||||
u32 flags;
|
||||
PcmData pcm;
|
||||
};
|
||||
|
||||
struct sound_startup_receipt { i32 _; };
|
||||
struct sound_startup_receipt sound_startup(AC_StartupReceipt *asset_cache_sr);
|
||||
typedef struct SND_StartupReceipt SND_StartupReceipt;
|
||||
struct SND_StartupReceipt { i32 _; };
|
||||
SND_StartupReceipt sound_startup(AC_StartupReceipt *asset_cache_sr);
|
||||
|
||||
AC_Asset *sound_load_asset(String path, u32 flags, b32 wait);
|
||||
struct sound *sound_load_async(String path, u32 flags);
|
||||
struct sound *sound_load(String path, u32 flags);
|
||||
SND_Sound *sound_load_async(String path, u32 flags);
|
||||
SND_Sound *sound_load(String path, u32 flags);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define SPRITE_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../gp/gp.h"
|
||||
#include "../ase/ase.h"
|
||||
#include "../resource/resource.h"
|
||||
|
||||
@ -60,8 +60,8 @@ struct cache_entry {
|
||||
i64 load_time_ns;
|
||||
u64 memory_usage;
|
||||
Arena *arena;
|
||||
struct sprite_texture *texture;
|
||||
struct sprite_sheet *sheet;
|
||||
S_Texture *texture;
|
||||
S_Sheet *sheet;
|
||||
|
||||
/* Hash list */
|
||||
struct cache_entry *next_in_bin;
|
||||
@ -76,7 +76,7 @@ struct cache_entry {
|
||||
};
|
||||
|
||||
struct cache_bin {
|
||||
struct snc_mutex mutex;
|
||||
P_Mutex mutex;
|
||||
struct cache_entry *first;
|
||||
struct cache_entry *last;
|
||||
};
|
||||
@ -85,7 +85,7 @@ struct cache {
|
||||
Atomic64Padded memory_usage;
|
||||
Arena *arena;
|
||||
struct cache_bin *bins;
|
||||
struct snc_mutex entry_pool_mutex;
|
||||
P_Mutex entry_pool_mutex;
|
||||
struct cache_entry *entry_pool_first_free;
|
||||
};
|
||||
|
||||
@ -106,9 +106,9 @@ struct sprite_scope_cache_ref {
|
||||
|
||||
struct load_cmd {
|
||||
struct load_cmd *next_free;
|
||||
struct sprite_scope *scope;
|
||||
S_Scope *scope;
|
||||
struct cache_ref ref;
|
||||
struct sprite_tag tag;
|
||||
S_Tag tag;
|
||||
u8 tag_path_buff[512];
|
||||
};
|
||||
|
||||
@ -118,30 +118,30 @@ struct load_cmd {
|
||||
|
||||
GLOBAL struct {
|
||||
Arena *perm_arena;
|
||||
struct sprite_texture *nil_texture;
|
||||
struct sprite_texture *loading_texture;
|
||||
struct sprite_sheet *nil_sheet;
|
||||
struct sprite_sheet *loading_sheet;
|
||||
S_Texture *nil_texture;
|
||||
S_Texture *loading_texture;
|
||||
S_Sheet *nil_sheet;
|
||||
S_Sheet *loading_sheet;
|
||||
|
||||
/* Cache */
|
||||
struct cache cache;
|
||||
|
||||
/* Load cmds */
|
||||
struct snc_mutex load_cmds_mutex;
|
||||
P_Mutex load_cmds_mutex;
|
||||
Arena *load_cmds_arena;
|
||||
struct load_cmd *first_free_load_cmd;
|
||||
|
||||
/* Scopes */
|
||||
struct snc_mutex scopes_mutex;
|
||||
P_Mutex scopes_mutex;
|
||||
Arena *scopes_arena;
|
||||
struct sprite_scope *first_free_scope;
|
||||
S_Scope *first_free_scope;
|
||||
|
||||
/* Evictor */
|
||||
Atomic32Padded evictor_cycle;
|
||||
struct snc_counter shutdown_counter;
|
||||
P_Counter shutdown_counter;
|
||||
b32 evictor_scheduler_shutdown;
|
||||
struct snc_mutex evictor_scheduler_mutex;
|
||||
struct snc_cv evictor_scheduler_shutdown_cv;
|
||||
P_Mutex evictor_scheduler_mutex;
|
||||
P_Cv evictor_scheduler_shutdown_cv;
|
||||
} G = ZI, DEBUG_ALIAS(G, G_sprite);
|
||||
|
||||
/* ========================== *
|
||||
@ -186,24 +186,24 @@ INTERNAL ImageDataRgba generate_purple_black_image(Arena *arena, u32 width, u32
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(sprite_shutdown);
|
||||
INTERNAL SYS_JOB_DEF(sprite_load_job, arg);
|
||||
INTERNAL SYS_JOB_DEF(sprite_evictor_job, _);
|
||||
INTERNAL P_ExitFuncDef(sprite_shutdown);
|
||||
INTERNAL P_JobDef(sprite_load_job, arg);
|
||||
INTERNAL P_JobDef(sprite_evictor_job, _);
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
INTERNAL WATCH_CALLBACK_FUNC_DEF(sprite_watch_callback, info);
|
||||
#endif
|
||||
|
||||
struct sprite_startup_receipt sprite_startup(void)
|
||||
S_StartupReceipt sprite_startup(void)
|
||||
{
|
||||
__prof;
|
||||
G.perm_arena = arena_alloc(MEBI(1));
|
||||
{
|
||||
/* Init loading texture */
|
||||
G.loading_texture = arena_push(G.perm_arena, struct sprite_texture);
|
||||
G.loading_texture = arena_push(G.perm_arena, S_Texture);
|
||||
|
||||
/* Init nil texture */
|
||||
G.nil_texture = arena_push(G.perm_arena, struct sprite_texture);
|
||||
G.nil_texture = arena_push(G.perm_arena, S_Texture);
|
||||
G.nil_texture->loaded = 1;
|
||||
{
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -213,12 +213,12 @@ struct sprite_startup_receipt sprite_startup(void)
|
||||
}
|
||||
|
||||
/* Init loading sheet */
|
||||
G.loading_sheet = arena_push(G.perm_arena, struct sprite_sheet);
|
||||
G.loading_sheet = arena_push(G.perm_arena, S_Sheet);
|
||||
G.loading_sheet->image_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||
G.loading_sheet->frame_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||
|
||||
/* Init nil sheet */
|
||||
G.nil_sheet = arena_push(G.perm_arena, struct sprite_sheet);
|
||||
G.nil_sheet = arena_push(G.perm_arena, S_Sheet);
|
||||
G.nil_sheet->image_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||
G.nil_sheet->frame_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||
G.nil_sheet->loaded = 1;
|
||||
@ -232,20 +232,20 @@ struct sprite_startup_receipt sprite_startup(void)
|
||||
|
||||
G.scopes_arena = arena_alloc(GIBI(64));
|
||||
|
||||
sys_run(1, sprite_evictor_job, 0, SYS_POOL_BACKGROUND, SYS_PRIORITY_LOW, &G.shutdown_counter);
|
||||
P_Run(1, sprite_evictor_job, 0, P_Pool_Background, P_Priority_Low, &G.shutdown_counter);
|
||||
|
||||
sys_on_exit(&sprite_shutdown);
|
||||
P_OnExit(&sprite_shutdown);
|
||||
watch_register_callback(&sprite_watch_callback);
|
||||
|
||||
return (struct sprite_startup_receipt) { 0 };
|
||||
return (S_StartupReceipt) { 0 };
|
||||
}
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(sprite_shutdown)
|
||||
INTERNAL P_ExitFuncDef(sprite_shutdown)
|
||||
{
|
||||
__prof;
|
||||
/* Signal evictor shutdown */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.evictor_scheduler_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.evictor_scheduler_mutex);
|
||||
G.evictor_scheduler_shutdown = 1;
|
||||
snc_cv_signal(&G.evictor_scheduler_shutdown_cv, I32_MAX);
|
||||
snc_unlock(&lock);
|
||||
@ -258,20 +258,20 @@ INTERNAL SYS_EXIT_FUNC(sprite_shutdown)
|
||||
* Tag
|
||||
* ========================== */
|
||||
|
||||
struct sprite_tag sprite_tag_from_path(String path)
|
||||
S_Tag sprite_tag_from_path(String path)
|
||||
{
|
||||
struct sprite_tag res = ZI;
|
||||
S_Tag res = ZI;
|
||||
res.hash = hash_fnv64(HASH_FNV64_BASIS, path);
|
||||
res.path = path;
|
||||
return res;
|
||||
}
|
||||
|
||||
b32 sprite_tag_is_nil(struct sprite_tag tag)
|
||||
b32 sprite_tag_is_nil(S_Tag tag)
|
||||
{
|
||||
return tag.hash == 0;
|
||||
}
|
||||
|
||||
b32 sprite_tag_eq(struct sprite_tag t1, struct sprite_tag t2)
|
||||
b32 sprite_tag_eq(S_Tag t1, S_Tag t2)
|
||||
{
|
||||
return t1.hash == t2.hash;
|
||||
}
|
||||
@ -285,12 +285,12 @@ INTERNAL struct cache_entry_hash cache_entry_hash_from_tag_hash(u64 tag_hash, en
|
||||
* Load
|
||||
* ========================== */
|
||||
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_from_ref(struct sprite_scope *scope, struct cache_ref ref);
|
||||
INTERNAL void push_load_job(struct cache_ref ref, struct sprite_tag tag)
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_from_ref(S_Scope *scope, struct cache_ref ref);
|
||||
INTERNAL void push_load_job(struct cache_ref ref, S_Tag tag)
|
||||
{
|
||||
struct load_cmd *cmd = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.load_cmds_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.load_cmds_mutex);
|
||||
if (G.first_free_load_cmd) {
|
||||
cmd = G.first_free_load_cmd;
|
||||
G.first_free_load_cmd = cmd->next_free;
|
||||
@ -312,10 +312,10 @@ INTERNAL void push_load_job(struct cache_ref ref, struct sprite_tag tag)
|
||||
}
|
||||
|
||||
/* Push work */
|
||||
sys_run(1, sprite_load_job, cmd, SYS_POOL_BACKGROUND, SYS_PRIORITY_INHERIT, 0);
|
||||
P_Run(1, sprite_load_job, cmd, P_Pool_Background, P_Priority_Inherit, 0);
|
||||
}
|
||||
|
||||
INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag tag)
|
||||
INTERNAL void cache_entry_load_texture(struct cache_ref ref, S_Tag tag)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -326,7 +326,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
||||
|
||||
logf_info("Loading sprite texture [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
b32 success = 0;
|
||||
i64 start_ns = sys_time_ns();
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
ASSERT(string_ends_with(path, LIT(".ase")));
|
||||
ASSERT(e->kind == CACHE_ENTRY_KIND_TEXTURE);
|
||||
@ -350,7 +350,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
||||
|
||||
if (decoded.success) {
|
||||
/* Initialize */
|
||||
e->texture = arena_push(e->arena, struct sprite_texture);
|
||||
e->texture = arena_push(e->arena, S_Texture);
|
||||
e->texture->width = decoded.image.width;
|
||||
e->texture->height = decoded.image.height;
|
||||
e->texture->valid = 1;
|
||||
@ -369,7 +369,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
||||
logf_success("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(sys_time_ns() - start_ns)),
|
||||
FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)),
|
||||
FMT_UINT(e->memory_usage));
|
||||
}
|
||||
|
||||
@ -377,14 +377,14 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
struct cache_bin *bin = &G.cache.bins[e->hash.v % CACHE_BINS_COUNT];
|
||||
struct snc_lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = snc_lock_e(&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) {
|
||||
atomic32_fetch_set(&old_entry->out_of_date, 1);
|
||||
}
|
||||
}
|
||||
e->load_time_ns = sys_time_ns();
|
||||
e->load_time_ns = P_TimeNs();
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
#endif
|
||||
@ -392,10 +392,10 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_DecodedSheet ase)
|
||||
INTERNAL S_Sheet init_sheet_from_ase_result(Arena *arena, Ase_DecodedSheet ase)
|
||||
{
|
||||
__prof;
|
||||
struct sprite_sheet sheet = ZI;
|
||||
S_Sheet sheet = ZI;
|
||||
|
||||
ASSERT(ase.num_frames >= 1);
|
||||
|
||||
@ -407,7 +407,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
__profn("Init frames");
|
||||
sheet.image_size = ase.image_size;
|
||||
sheet.frame_size = ase.frame_size;
|
||||
sheet.frames = arena_push_array(arena, struct sprite_sheet_frame, ase.num_frames);
|
||||
sheet.frames = arena_push_array(arena, S_SheetFrame, ase.num_frames);
|
||||
sheet.frames_count = ase.num_frames;
|
||||
for (Ase_Frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) {
|
||||
u32 index = ase_frame->index;
|
||||
@ -415,7 +415,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
V2 clip_p1 = { (f32)ase_frame->x1 / (f32)ase.image_size.x, (f32)ase_frame->y1 / (f32)ase.image_size.y };
|
||||
V2 clip_p2 = { (f32)ase_frame->x2 / (f32)ase.image_size.x, (f32)ase_frame->y2 / (f32)ase.image_size.y };
|
||||
|
||||
sheet.frames[index] = (struct sprite_sheet_frame) {
|
||||
sheet.frames[index] = (S_SheetFrame) {
|
||||
.index = index,
|
||||
.duration = ase_frame->duration,
|
||||
.clip = (ClipRect) { clip_p1, clip_p2 }
|
||||
@ -427,12 +427,12 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
sheet.spans_count = ase.num_spans;
|
||||
if (ase.num_spans > 0) {
|
||||
__profn("Init spans");
|
||||
sheet.spans = arena_push_array(arena, struct sprite_sheet_span, sheet.spans_count);
|
||||
sheet.spans = arena_push_array(arena, S_SheetSpan, sheet.spans_count);
|
||||
sheet.spans_dict = dict_init(arena, (u64)(ase.num_spans * SHEET_SPAN_LOOKUP_TABLE_BIN_RATIO));
|
||||
u64 index = 0;
|
||||
for (Ase_Span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) {
|
||||
String name = string_copy(arena, ase_span->name);
|
||||
struct sprite_sheet_span *span = &sheet.spans[index];
|
||||
S_SheetSpan *span = &sheet.spans[index];
|
||||
span->name = name;
|
||||
span->start = ase_span->start;
|
||||
span->end = ase_span->end;
|
||||
@ -461,7 +461,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
struct temp_ase_slice_key_node *temp_ase_slice_key_head;
|
||||
struct temp_slice_group_node *next;
|
||||
|
||||
struct sprite_sheet_slice_group *final_slice_group;
|
||||
S_SheetSliceGroup *final_slice_group;
|
||||
};
|
||||
|
||||
/* Group slices by name and find out counts per frame */
|
||||
@ -496,16 +496,16 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
|
||||
/* Allocate slice groups & fill originals in 2d array */
|
||||
sheet.slice_groups_count = num_temp_slice_group_nodes;
|
||||
sheet.slice_groups = arena_push_array(arena, struct sprite_sheet_slice_group, sheet.slice_groups_count);
|
||||
sheet.slice_groups = arena_push_array(arena, S_SheetSliceGroup, sheet.slice_groups_count);
|
||||
sheet.slice_groups_dict = dict_init(arena, (u64)(num_temp_slice_group_nodes * SHEET_SLICE_LOOKUP_TABLE_BIN_RATIO));
|
||||
|
||||
u64 index = 0;
|
||||
for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) {
|
||||
struct sprite_sheet_slice_group *slice_group = &sheet.slice_groups[index];
|
||||
S_SheetSliceGroup *slice_group = &sheet.slice_groups[index];
|
||||
slice_group->name = string_copy(arena, temp_slice_group_node->name);
|
||||
slice_group->per_frame_count = temp_slice_group_node->per_frame_count;
|
||||
|
||||
slice_group->frame_slices = arena_push_array(arena, struct sprite_sheet_slice, ase.num_frames * slice_group->per_frame_count);
|
||||
slice_group->frame_slices = arena_push_array(arena, S_SheetSlice, ase.num_frames * slice_group->per_frame_count);
|
||||
|
||||
u64 index_in_frame = 0;
|
||||
for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) {
|
||||
@ -514,7 +514,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
for (Ase_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) {
|
||||
u32 start = ase_slice->start;
|
||||
|
||||
struct sprite_sheet_slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
||||
S_SheetSlice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
||||
slice->original = 1;
|
||||
|
||||
f32 x1_px = ase_slice->x1;
|
||||
@ -566,7 +566,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
|
||||
/* Propagate original slices into next frames (and first slices into previous frames) */
|
||||
for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) {
|
||||
struct sprite_sheet_slice_group *slice_group = temp_slice_group_node->final_slice_group;
|
||||
S_SheetSliceGroup *slice_group = temp_slice_group_node->final_slice_group;
|
||||
|
||||
for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) {
|
||||
Ase_SliceKey *key = node->key;
|
||||
@ -574,12 +574,12 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
for (Ase_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) {
|
||||
u32 start = ase_slice->start;
|
||||
|
||||
struct sprite_sheet_slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
||||
S_SheetSlice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
||||
|
||||
/* Propagate earliest slice to all previous frames */
|
||||
if (start == node->earliest_frame && start > 0) {
|
||||
for (u32 i = start; i-- > 0;) {
|
||||
struct sprite_sheet_slice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame];
|
||||
S_SheetSlice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame];
|
||||
*target = *slice;
|
||||
target->original = 0;
|
||||
}
|
||||
@ -587,7 +587,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
|
||||
/* Propagate slice to forward frames until original is found */
|
||||
for (u32 i = start + 1; i < ase.num_frames; ++i) {
|
||||
struct sprite_sheet_slice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame];
|
||||
S_SheetSlice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame];
|
||||
if (target->original) {
|
||||
break;
|
||||
} else {
|
||||
@ -603,25 +603,25 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) {
|
||||
String ray_suffix = LIT(".ray");
|
||||
|
||||
struct sprite_sheet_slice_group *ray_slice_group = temp_slice_group_node->final_slice_group;
|
||||
S_SheetSliceGroup *ray_slice_group = temp_slice_group_node->final_slice_group;
|
||||
String ray_slice_name = ray_slice_group->name;
|
||||
if (string_ends_with(ray_slice_name, ray_suffix)) {
|
||||
String point_slice_name = ray_slice_name;
|
||||
point_slice_name.len -= ray_suffix.len;
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, point_slice_name);
|
||||
struct sprite_sheet_slice_group *point_slice_group = (struct sprite_sheet_slice_group *)dict_get(sheet.slice_groups_dict, hash);
|
||||
S_SheetSliceGroup *point_slice_group = (S_SheetSliceGroup *)dict_get(sheet.slice_groups_dict, hash);
|
||||
if (point_slice_group) {
|
||||
u32 point_slices_per_frame = point_slice_group->per_frame_count;
|
||||
|
||||
for (u32 i = 0; i < ase.num_frames; ++i) {
|
||||
/* Use ray slice in ray group */
|
||||
struct sprite_sheet_slice *ray_slice = &ray_slice_group->frame_slices[i * point_slices_per_frame];
|
||||
S_SheetSlice *ray_slice = &ray_slice_group->frame_slices[i * point_slices_per_frame];
|
||||
V2 ray_end = ray_slice->center_px;
|
||||
V2 ray_end_norm = ray_slice->center;
|
||||
|
||||
/* Apply to each point slice in point group */
|
||||
for (u32 j = 0; j < point_slices_per_frame; ++j) {
|
||||
struct sprite_sheet_slice *point_slice = &point_slice_group->frame_slices[(i * point_slices_per_frame) + j];
|
||||
S_SheetSlice *point_slice = &point_slice_group->frame_slices[(i * point_slices_per_frame) + j];
|
||||
point_slice->dir_px = v2_sub(ray_end, point_slice->center_px);
|
||||
point_slice->dir = v2_sub(ray_end_norm, point_slice->center);
|
||||
point_slice->has_ray = 1;
|
||||
@ -638,7 +638,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_Decode
|
||||
return sheet;
|
||||
}
|
||||
|
||||
INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag)
|
||||
INTERNAL void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -649,7 +649,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
||||
|
||||
logf_info("Loading sprite sheet [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
b32 success = 0;
|
||||
i64 start_ns = sys_time_ns();
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
ASSERT(e->kind == CACHE_ENTRY_KIND_SHEET);
|
||||
|
||||
@ -674,7 +674,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
||||
resource_close(&sheet_rs);
|
||||
|
||||
/* Initialize */
|
||||
e->sheet = arena_push_no_zero(e->arena, struct sprite_sheet);
|
||||
e->sheet = arena_push_no_zero(e->arena, S_Sheet);
|
||||
*e->sheet = init_sheet_from_ase_result(e->arena, decoded);
|
||||
e->sheet->loaded = 1;
|
||||
e->sheet->valid = 1;
|
||||
@ -690,7 +690,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
||||
logf_success("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(sys_time_ns() - start_ns)),
|
||||
FMT_FLOAT(SECONDS_FROM_NS(P_TimeNs() - start_ns)),
|
||||
FMT_UINT(e->memory_usage));
|
||||
}
|
||||
|
||||
@ -698,14 +698,14 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
struct cache_bin *bin = &G.cache.bins[e->hash.v % CACHE_BINS_COUNT];
|
||||
struct snc_lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = snc_lock_e(&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) {
|
||||
atomic32_fetch_set(&old_entry->out_of_date, 1);
|
||||
}
|
||||
}
|
||||
e->load_time_ns = sys_time_ns();
|
||||
e->load_time_ns = P_TimeNs();
|
||||
}
|
||||
snc_unlock(&bin_lock);
|
||||
#endif
|
||||
@ -735,7 +735,7 @@ INTERNAL void refcount_add(struct cache_entry *e, i32 amount)
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_unsafe(struct sprite_scope *scope, struct cache_entry *e)
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_unsafe(S_Scope *scope, struct cache_entry *e)
|
||||
{
|
||||
u64 bin_index = e->hash.v % CACHE_BINS_COUNT;
|
||||
|
||||
@ -751,7 +751,7 @@ INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_unsafe(struct sprite_sc
|
||||
|
||||
if (*slot == 0) {
|
||||
if (scope->num_references >= MAX_SCOPE_REFERENCES) {
|
||||
sys_panic(LIT("Max sprite scope references reached"));
|
||||
P_Panic(LIT("Max sprite scope references reached"));
|
||||
}
|
||||
|
||||
/* Increment refcount */
|
||||
@ -768,27 +768,27 @@ INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_unsafe(struct sprite_sc
|
||||
return *slot;
|
||||
}
|
||||
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_from_entry(struct sprite_scope *scope, struct cache_entry *e, struct snc_lock *bin_lock)
|
||||
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);
|
||||
return scope_ensure_ref_unsafe(scope, e);
|
||||
}
|
||||
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_from_ref(struct sprite_scope *scope, struct cache_ref ref)
|
||||
INTERNAL struct sprite_scope_cache_ref *scope_ensure_ref_from_ref(S_Scope *scope, struct cache_ref ref)
|
||||
{
|
||||
/* Safe since caller has ref */
|
||||
return scope_ensure_ref_unsafe(scope, ref.e);
|
||||
}
|
||||
|
||||
struct sprite_scope *sprite_scope_begin(void)
|
||||
S_Scope *sprite_scope_begin(void)
|
||||
{
|
||||
/* Alloc scope */
|
||||
struct sprite_scope *res = 0;
|
||||
S_Scope *res = 0;
|
||||
struct sprite_scope_cache_ref **bins = 0;
|
||||
struct sprite_scope_cache_ref *pool = 0;
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.scopes_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.scopes_mutex);
|
||||
{
|
||||
if (G.first_free_scope) {
|
||||
res = G.first_free_scope;
|
||||
@ -796,7 +796,7 @@ struct sprite_scope *sprite_scope_begin(void)
|
||||
bins = res->ref_node_bins;
|
||||
pool = res->ref_node_pool;
|
||||
} else {
|
||||
res = arena_push_no_zero(G.scopes_arena, struct sprite_scope);
|
||||
res = arena_push_no_zero(G.scopes_arena, S_Scope);
|
||||
bins = arena_push_array_no_zero(G.scopes_arena, struct sprite_scope_cache_ref *, CACHE_BINS_COUNT);
|
||||
pool = arena_push_array_no_zero(G.scopes_arena, struct sprite_scope_cache_ref, MAX_SCOPE_REFERENCES);
|
||||
}
|
||||
@ -810,7 +810,7 @@ struct sprite_scope *sprite_scope_begin(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
void sprite_scope_end(struct sprite_scope *scope)
|
||||
void sprite_scope_end(S_Scope *scope)
|
||||
{
|
||||
/* Dereference entries */
|
||||
u64 num_references = scope->num_references;
|
||||
@ -820,7 +820,7 @@ void sprite_scope_end(struct sprite_scope *scope)
|
||||
}
|
||||
|
||||
/* Release scope */
|
||||
struct snc_lock lock = snc_lock_e(&G.scopes_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.scopes_mutex);
|
||||
{
|
||||
scope->next_free = G.first_free_scope;
|
||||
G.first_free_scope = scope;
|
||||
@ -832,7 +832,7 @@ void sprite_scope_end(struct sprite_scope *scope)
|
||||
* Cache interface
|
||||
* ========================== */
|
||||
|
||||
INTERNAL struct sprite_scope_cache_ref *cache_lookup(struct sprite_scope *scope, struct cache_entry_hash hash, struct snc_lock *bin_lock)
|
||||
INTERNAL struct sprite_scope_cache_ref *cache_lookup(S_Scope *scope, struct cache_entry_hash hash, P_Lock *bin_lock)
|
||||
{
|
||||
struct sprite_scope_cache_ref *scope_ref = 0;
|
||||
|
||||
@ -869,7 +869,7 @@ INTERNAL struct sprite_scope_cache_ref *cache_lookup(struct sprite_scope *scope,
|
||||
return scope_ref;
|
||||
}
|
||||
|
||||
INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope *scope, struct sprite_tag tag, enum cache_entry_kind kind, b32 force_new)
|
||||
INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(S_Scope *scope, S_Tag tag, enum cache_entry_kind kind, b32 force_new)
|
||||
{
|
||||
struct cache_entry_hash hash = cache_entry_hash_from_tag_hash(tag.hash, kind);
|
||||
u64 bin_index = hash.v % CACHE_BINS_COUNT;
|
||||
@ -892,7 +892,7 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope
|
||||
|
||||
/* Search in cache */
|
||||
if (!force_new) {
|
||||
struct snc_lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
P_Lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
{
|
||||
scope_ref = cache_lookup(scope, hash, &bin_lock);
|
||||
}
|
||||
@ -901,7 +901,7 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope
|
||||
|
||||
/* If not in cache, allocate new entry */
|
||||
if (!scope_ref) {
|
||||
struct snc_lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
{
|
||||
/* Search cache one more time in case an entry was allocated between locks */
|
||||
if (!force_new) {
|
||||
@ -912,7 +912,7 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope
|
||||
/* Cache entry still absent, allocate new entry */
|
||||
struct cache_entry *entry = 0;
|
||||
{
|
||||
struct snc_lock pool_lock = snc_lock_e(&G.cache.entry_pool_mutex);
|
||||
P_Lock pool_lock = snc_lock_e(&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;
|
||||
@ -948,14 +948,14 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope
|
||||
return scope_ref;
|
||||
}
|
||||
|
||||
INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_tag tag, enum cache_entry_kind kind, b32 await)
|
||||
INTERNAL void *data_from_tag_internal(S_Scope *scope, S_Tag tag, enum cache_entry_kind kind, b32 await)
|
||||
{
|
||||
/* TODO: Replace switch statements */
|
||||
void *res = 0;
|
||||
switch (kind) {
|
||||
case CACHE_ENTRY_KIND_TEXTURE: { res = G.loading_texture; } break;
|
||||
case CACHE_ENTRY_KIND_SHEET: { res = G.loading_sheet; } break;
|
||||
default: { sys_panic(LIT("Unknown sprite cache entry kind")); } break;
|
||||
default: { P_Panic(LIT("Unknown sprite cache entry kind")); } break;
|
||||
}
|
||||
|
||||
struct sprite_scope_cache_ref *scope_ref = cache_entry_from_tag(scope, tag, kind, 0);
|
||||
@ -966,7 +966,7 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
|
||||
switch (kind) {
|
||||
case CACHE_ENTRY_KIND_TEXTURE: { res = ref.e->texture; } break;
|
||||
case CACHE_ENTRY_KIND_SHEET: { res = ref.e->sheet; } break;
|
||||
default: { sys_panic(LIT("Unknown sprite cache entry kind")); } break;
|
||||
default: { P_Panic(LIT("Unknown sprite cache entry kind")); } break;
|
||||
}
|
||||
} else if (state == CACHE_ENTRY_STATE_NONE) {
|
||||
/* If entry is new, load texture */
|
||||
@ -982,7 +982,7 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
|
||||
cache_entry_load_sheet(ref, tag);
|
||||
res = ref.e->sheet;
|
||||
} break;
|
||||
default: { sys_panic(LIT("Unknown sprite cache entry kind")); } break;
|
||||
default: { P_Panic(LIT("Unknown sprite cache entry kind")); } break;
|
||||
}
|
||||
} else {
|
||||
/* Allocate cmd */
|
||||
@ -1005,18 +1005,18 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
|
||||
* Texture
|
||||
* ========================== */
|
||||
|
||||
struct sprite_texture *sprite_texture_from_tag_await(struct sprite_scope *scope, struct sprite_tag tag)
|
||||
S_Texture *sprite_texture_from_tag_await(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (struct sprite_texture *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 1);
|
||||
return (S_Texture *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 1);
|
||||
}
|
||||
|
||||
struct sprite_texture *sprite_texture_from_tag_async(struct sprite_scope *scope, struct sprite_tag tag)
|
||||
S_Texture *sprite_texture_from_tag_async(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (struct sprite_texture *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0);
|
||||
return (S_Texture *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0);
|
||||
}
|
||||
|
||||
|
||||
void sprite_texture_from_tag_prefetch(struct sprite_scope *scope, struct sprite_tag tag)
|
||||
void sprite_texture_from_tag_prefetch(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0);
|
||||
}
|
||||
@ -1025,40 +1025,40 @@ void sprite_texture_from_tag_prefetch(struct sprite_scope *scope, struct sprite_
|
||||
* Sheet
|
||||
* ========================== */
|
||||
|
||||
struct sprite_sheet *sprite_sheet_from_tag_await(struct sprite_scope *scope, struct sprite_tag tag)
|
||||
S_Sheet *sprite_sheet_from_tag_await(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (struct sprite_sheet *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 1);
|
||||
return (S_Sheet *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 1);
|
||||
}
|
||||
|
||||
struct sprite_sheet *sprite_sheet_from_tag_async(struct sprite_scope *scope, struct sprite_tag tag)
|
||||
S_Sheet *sprite_sheet_from_tag_async(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (struct sprite_sheet *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 0);
|
||||
return (S_Sheet *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 0);
|
||||
}
|
||||
|
||||
void sprite_sheet_from_tag_prefetch(struct sprite_scope *scope, struct sprite_tag tag)
|
||||
void sprite_sheet_from_tag_prefetch(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 0);
|
||||
}
|
||||
|
||||
|
||||
struct sprite_sheet_frame sprite_sheet_get_frame(struct sprite_sheet *sheet, u32 index)
|
||||
S_SheetFrame sprite_sheet_get_frame(S_Sheet *sheet, u32 index)
|
||||
{
|
||||
if (index < sheet->frames_count ) {
|
||||
return sheet->frames[index];
|
||||
}
|
||||
struct sprite_sheet_frame res = ZI;
|
||||
S_SheetFrame res = ZI;
|
||||
res.index = 0;
|
||||
res.duration = 0.1;
|
||||
res.clip = CLIP_ALL;
|
||||
return res;
|
||||
}
|
||||
|
||||
struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, String name)
|
||||
S_SheetSpan sprite_sheet_get_span(S_Sheet *sheet, String name)
|
||||
{
|
||||
struct sprite_sheet_span res = ZI;
|
||||
S_SheetSpan res = ZI;
|
||||
if (sheet->spans_count > 0) {
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
struct sprite_sheet_span *entry = (struct sprite_sheet_span *)dict_get(sheet->spans_dict, hash);
|
||||
S_SheetSpan *entry = (S_SheetSpan *)dict_get(sheet->spans_dict, hash);
|
||||
if (entry) {
|
||||
res = *entry;
|
||||
}
|
||||
@ -1066,18 +1066,18 @@ struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, Strin
|
||||
return res;
|
||||
}
|
||||
|
||||
struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, String name, u32 frame_index)
|
||||
S_SheetSlice sprite_sheet_get_slice(S_Sheet *sheet, String name, u32 frame_index)
|
||||
{
|
||||
if (sheet->slice_groups_count > 0) {
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
struct sprite_sheet_slice_group *group = (struct sprite_sheet_slice_group *)dict_get(sheet->slice_groups_dict, hash);
|
||||
S_SheetSliceGroup *group = (S_SheetSliceGroup *)dict_get(sheet->slice_groups_dict, hash);
|
||||
if (group) {
|
||||
return group->frame_slices[frame_index * group->per_frame_count];
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 'pivot' by default */
|
||||
struct sprite_sheet_slice res = ZI;
|
||||
S_SheetSlice res = ZI;
|
||||
if (string_eq(name, LIT("pivot"))) {
|
||||
/* 'pivot' slice does not exist, return center */
|
||||
res.center = V2FromXY(0, 0);
|
||||
@ -1091,12 +1091,12 @@ struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, Str
|
||||
return res;
|
||||
}
|
||||
|
||||
struct sprite_sheet_slice_array sprite_sheet_get_slices(struct sprite_sheet *sheet, String name, u32 frame_index)
|
||||
S_SheetSliceArray sprite_sheet_get_slices(S_Sheet *sheet, String name, u32 frame_index)
|
||||
{
|
||||
struct sprite_sheet_slice_array res = ZI;
|
||||
S_SheetSliceArray res = ZI;
|
||||
if (sheet->slice_groups_count > 0) {
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
struct sprite_sheet_slice_group *group = (struct sprite_sheet_slice_group *)dict_get(sheet->slice_groups_dict, hash);
|
||||
S_SheetSliceGroup *group = (S_SheetSliceGroup *)dict_get(sheet->slice_groups_dict, hash);
|
||||
if (group) {
|
||||
res.count = group->per_frame_count;
|
||||
res.slices = &group->frame_slices[frame_index * group->per_frame_count];
|
||||
@ -1109,7 +1109,7 @@ struct sprite_sheet_slice_array sprite_sheet_get_slices(struct sprite_sheet *she
|
||||
* Load job
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(sprite_load_job, job)
|
||||
INTERNAL P_JobDef(sprite_load_job, job)
|
||||
{
|
||||
__prof;
|
||||
struct load_cmd *cmd = job.sig;
|
||||
@ -1122,11 +1122,11 @@ INTERNAL SYS_JOB_DEF(sprite_load_job, job)
|
||||
case CACHE_ENTRY_KIND_SHEET: {
|
||||
cache_entry_load_sheet(ref, cmd->tag);
|
||||
} break;
|
||||
default: { sys_panic(LIT("Unknown sprite cache node kind")); } break;
|
||||
default: { P_Panic(LIT("Unknown sprite cache node kind")); } break;
|
||||
}
|
||||
|
||||
/* Free cmd */
|
||||
struct snc_lock lock = snc_lock_e(&G.load_cmds_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.load_cmds_mutex);
|
||||
{
|
||||
sprite_scope_end(cmd->scope);
|
||||
cmd->next_free = G.first_free_load_cmd;
|
||||
@ -1141,12 +1141,12 @@ INTERNAL SYS_JOB_DEF(sprite_load_job, job)
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
|
||||
INTERNAL void reload_if_exists(struct sprite_scope *scope, struct sprite_tag tag, enum cache_entry_kind kind)
|
||||
INTERNAL void reload_if_exists(S_Scope *scope, S_Tag tag, enum cache_entry_kind 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;
|
||||
struct snc_lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
P_Lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
{
|
||||
existing_ref = cache_lookup(scope, hash, &bin_lock);
|
||||
}
|
||||
@ -1161,14 +1161,14 @@ INTERNAL void reload_if_exists(struct sprite_scope *scope, struct sprite_tag tag
|
||||
|
||||
INTERNAL WATCH_CALLBACK_FUNC_DEF(sprite_watch_callback, name)
|
||||
{
|
||||
struct sprite_scope *scope = sprite_scope_begin();
|
||||
S_Scope *scope = sprite_scope_begin();
|
||||
|
||||
if (string_starts_with(name, LIT("res/"))) {
|
||||
name.len -= LIT("res/").len;
|
||||
name.text += LIT("res/").len;
|
||||
}
|
||||
|
||||
struct sprite_tag tag = sprite_tag_from_path(name);
|
||||
S_Tag tag = sprite_tag_from_path(name);
|
||||
for (enum cache_entry_kind kind = 0; kind < NUM_CACHE_ENTRY_KINDS; ++kind) {
|
||||
reload_if_exists(scope, tag, kind);
|
||||
}
|
||||
@ -1210,7 +1210,7 @@ INTERNAL SORT_COMPARE_FUNC_DEF(evict_sort, arg_a, arg_b, udata)
|
||||
* - The cache is over its memory budget and the node's last reference is longer ago than the grace period
|
||||
* - Resource reloading is enabled and the node is out of date due to a change to its original resource file
|
||||
*/
|
||||
INTERNAL SYS_JOB_DEF(sprite_evictor_job, _)
|
||||
INTERNAL P_JobDef(sprite_evictor_job, _)
|
||||
{
|
||||
(UNUSED)_;
|
||||
b32 shutdown = 0;
|
||||
@ -1229,7 +1229,7 @@ INTERNAL SYS_JOB_DEF(sprite_evictor_job, _)
|
||||
__profn("Evictor scan");
|
||||
for (u64 i = 0; i < CACHE_BINS_COUNT; ++i) {
|
||||
struct cache_bin *bin = &G.cache.bins[i];
|
||||
struct snc_lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
P_Lock bin_lock = snc_lock_s(&bin->mutex);
|
||||
{
|
||||
struct cache_entry *n = bin->first;
|
||||
while (n) {
|
||||
@ -1282,7 +1282,7 @@ INTERNAL SYS_JOB_DEF(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;
|
||||
struct snc_lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
P_Lock bin_lock = snc_lock_e(&bin->mutex);
|
||||
{
|
||||
u64 refcount_uncast = atomic64_fetch(&entry->refcount_struct.v);
|
||||
struct cache_refcount refcount = *(struct cache_refcount *)&refcount_uncast;
|
||||
@ -1333,7 +1333,7 @@ INTERNAL SYS_JOB_DEF(sprite_evictor_job, _)
|
||||
/* Add evicted nodes to free list */
|
||||
{
|
||||
__profn("Evictor free list append");
|
||||
struct snc_lock pool_lock = snc_lock_e(&G.cache.entry_pool_mutex);
|
||||
P_Lock pool_lock = snc_lock_e(&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;
|
||||
@ -1349,7 +1349,7 @@ INTERNAL SYS_JOB_DEF(sprite_evictor_job, _)
|
||||
|
||||
/* Evictor sleep */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.evictor_scheduler_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.evictor_scheduler_mutex);
|
||||
{
|
||||
if (!G.evictor_scheduler_shutdown) {
|
||||
snc_cv_wait_time(&G.evictor_scheduler_shutdown_cv, &lock, EVICTOR_CYCLE_INTERVAL_NS);
|
||||
|
||||
@ -1,47 +1,48 @@
|
||||
struct sprite_sheet_span;
|
||||
struct sprite_sheet_slice_group;
|
||||
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
struct sprite_startup_receipt { i32 _; };
|
||||
struct sprite_startup_receipt sprite_startup(void);
|
||||
typedef struct S_StartupReceipt S_StartupReceipt;
|
||||
struct S_StartupReceipt { i32 _; };
|
||||
S_StartupReceipt sprite_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
* Tag
|
||||
* ========================== */
|
||||
|
||||
struct sprite_tag {
|
||||
typedef struct S_Tag S_Tag;
|
||||
struct S_Tag {
|
||||
u64 hash;
|
||||
String path;
|
||||
};
|
||||
|
||||
INLINE struct sprite_tag sprite_tag_nil(void) { return (struct sprite_tag) { 0 }; }
|
||||
INLINE S_Tag sprite_tag_nil(void) { return (S_Tag) { 0 }; }
|
||||
|
||||
struct sprite_tag sprite_tag_from_path(String path);
|
||||
b32 sprite_tag_is_nil(struct sprite_tag tag);
|
||||
b32 sprite_tag_eq(struct sprite_tag t1, struct sprite_tag t2);
|
||||
S_Tag sprite_tag_from_path(String path);
|
||||
b32 sprite_tag_is_nil(S_Tag tag);
|
||||
b32 sprite_tag_eq(S_Tag t1, S_Tag t2);
|
||||
|
||||
/* ========================== *
|
||||
* Scope
|
||||
* ========================== */
|
||||
|
||||
struct sprite_scope {
|
||||
typedef struct S_Scope S_Scope;
|
||||
struct S_Scope {
|
||||
struct sprite_scope_cache_ref **ref_node_bins;
|
||||
struct sprite_scope_cache_ref *ref_node_pool;
|
||||
u64 num_references;
|
||||
struct sprite_scope *next_free;
|
||||
S_Scope *next_free;
|
||||
};
|
||||
|
||||
struct sprite_scope *sprite_scope_begin(void);
|
||||
void sprite_scope_end(struct sprite_scope *scope);
|
||||
S_Scope *sprite_scope_begin(void);
|
||||
void sprite_scope_end(S_Scope *scope);
|
||||
|
||||
/* ========================== *
|
||||
* Texture load
|
||||
* ========================== */
|
||||
|
||||
struct sprite_texture {
|
||||
typedef struct S_Texture S_Texture;
|
||||
struct S_Texture {
|
||||
b32 loaded;
|
||||
b32 valid;
|
||||
G_Resource *gp_texture;
|
||||
@ -49,53 +50,60 @@ struct sprite_texture {
|
||||
u32 height;
|
||||
};
|
||||
|
||||
struct sprite_texture *sprite_texture_from_tag_await(struct sprite_scope *scope, struct sprite_tag tag);
|
||||
struct sprite_texture *sprite_texture_from_tag_async(struct sprite_scope *scope, struct sprite_tag tag);
|
||||
void sprite_texture_from_tag_prefetch(struct sprite_scope *scope, struct sprite_tag tag);
|
||||
S_Texture *sprite_texture_from_tag_await(S_Scope *scope, S_Tag tag);
|
||||
S_Texture *sprite_texture_from_tag_async(S_Scope *scope, S_Tag tag);
|
||||
void sprite_texture_from_tag_prefetch(S_Scope *scope, S_Tag tag);
|
||||
|
||||
/* ========================== *
|
||||
* Sheet load
|
||||
* ========================== */
|
||||
|
||||
struct sprite_sheet {
|
||||
typedef struct S_SheetSliceGroup S_SheetSliceGroup;
|
||||
typedef struct S_SheetSpan S_SheetSpan;
|
||||
typedef struct S_SheetFrame S_SheetFrame;
|
||||
typedef struct S_Sheet S_Sheet;
|
||||
struct S_Sheet {
|
||||
b32 loaded;
|
||||
b32 valid;
|
||||
V2 image_size;
|
||||
V2 frame_size;
|
||||
|
||||
u32 frames_count;
|
||||
struct sprite_sheet_frame *frames;
|
||||
S_SheetFrame *frames;
|
||||
|
||||
u32 spans_count;
|
||||
struct sprite_sheet_span *spans;
|
||||
S_SheetSpan *spans;
|
||||
Dict *spans_dict;
|
||||
|
||||
u32 slice_groups_count;
|
||||
struct sprite_sheet_slice_group *slice_groups;
|
||||
S_SheetSliceGroup *slice_groups;
|
||||
Dict *slice_groups_dict;
|
||||
};
|
||||
|
||||
struct sprite_sheet *sprite_sheet_from_tag_await(struct sprite_scope *scope, struct sprite_tag tag);
|
||||
struct sprite_sheet *sprite_sheet_from_tag_async(struct sprite_scope *scope, struct sprite_tag tag);
|
||||
void sprite_sheet_from_tag_prefetch(struct sprite_scope *scope, struct sprite_tag tag);
|
||||
S_Sheet *sprite_sheet_from_tag_await(S_Scope *scope, S_Tag tag);
|
||||
S_Sheet *sprite_sheet_from_tag_async(S_Scope *scope, S_Tag tag);
|
||||
void sprite_sheet_from_tag_prefetch(S_Scope *scope, S_Tag tag);
|
||||
|
||||
/* ========================== *
|
||||
* Sheet query
|
||||
* ========================== */
|
||||
|
||||
struct sprite_sheet_frame {
|
||||
typedef struct S_SheetFrame S_SheetFrame;
|
||||
struct S_SheetFrame {
|
||||
u32 index;
|
||||
f64 duration;
|
||||
ClipRect clip;
|
||||
};
|
||||
|
||||
struct sprite_sheet_span {
|
||||
typedef struct S_SheetSpan S_SheetSpan;
|
||||
struct S_SheetSpan {
|
||||
String name;
|
||||
u32 start;
|
||||
u32 end;
|
||||
};
|
||||
|
||||
struct sprite_sheet_slice {
|
||||
typedef struct S_SheetSlice S_SheetSlice;
|
||||
struct S_SheetSlice {
|
||||
/* If 1, this slice was not copied over from another frame in the sprite sheet */
|
||||
b32 original;
|
||||
|
||||
@ -113,26 +121,28 @@ struct sprite_sheet_slice {
|
||||
V2 dir_px;
|
||||
};
|
||||
|
||||
struct sprite_sheet_slice_array {
|
||||
typedef struct S_SheetSliceArray S_SheetSliceArray;
|
||||
struct S_SheetSliceArray {
|
||||
u64 count;
|
||||
struct sprite_sheet_slice *slices;
|
||||
S_SheetSlice *slices;
|
||||
};
|
||||
|
||||
struct sprite_sheet_slice_group {
|
||||
typedef struct S_SheetSliceGroup S_SheetSliceGroup;
|
||||
struct S_SheetSliceGroup {
|
||||
String name;
|
||||
u64 per_frame_count;
|
||||
|
||||
/* 2d array of slices with length (num frames) * (num slices per frame).
|
||||
* Index with [(frame index * num slices per frame) + slice index in frame] */
|
||||
struct sprite_sheet_slice *frame_slices;
|
||||
S_SheetSlice *frame_slices;
|
||||
};
|
||||
|
||||
struct sprite_sheet_frame sprite_sheet_get_frame(struct sprite_sheet *sheet, u32 index);
|
||||
S_SheetFrame sprite_sheet_get_frame(S_Sheet *sheet, u32 index);
|
||||
|
||||
struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, String name);
|
||||
S_SheetSpan sprite_sheet_get_span(S_Sheet *sheet, String name);
|
||||
|
||||
/* Returns first slice with name in frame */
|
||||
struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, String name, u32 frame_index);
|
||||
S_SheetSlice sprite_sheet_get_slice(S_Sheet *sheet, String name, u32 frame_index);
|
||||
|
||||
/* Returns all slices with name in frame */
|
||||
struct sprite_sheet_slice_array sprite_sheet_get_slices(struct sprite_sheet *sheet, String name, u32 frame_index);
|
||||
S_SheetSliceArray sprite_sheet_get_slices(S_Sheet *sheet, String name, u32 frame_index);
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
#include "sys.h"
|
||||
|
||||
#include "sys_snc.c"
|
||||
#include "sys_sleep.c"
|
||||
#include "sys_core.c"
|
||||
#include "sys_log.c"
|
||||
@ -1,11 +0,0 @@
|
||||
#ifndef SYS_H
|
||||
#define SYS_H
|
||||
|
||||
#include "../base/base.h"
|
||||
|
||||
#include "sys_snc.h"
|
||||
#include "sys_sleep.h"
|
||||
#include "sys_core.h"
|
||||
#include "sys_log.h"
|
||||
|
||||
#endif
|
||||
@ -1,5 +0,0 @@
|
||||
#if PLATFORM_WINDOWS
|
||||
# include "sys_core_win32.c"
|
||||
#else
|
||||
# error System core layer not implemented
|
||||
#endif
|
||||
@ -1,482 +0,0 @@
|
||||
/* ========================== *
|
||||
* Wait
|
||||
* ========================== */
|
||||
|
||||
/* Futex-like wait & wake */
|
||||
void sys_wait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns);
|
||||
void sys_wake(void *addr, i32 count);
|
||||
|
||||
/* ========================== *
|
||||
* Job
|
||||
* ========================== */
|
||||
|
||||
/* Work pools contain their own worker threads with their own thread priority/affinity based on the intended context of the pool. */
|
||||
enum sys_pool {
|
||||
SYS_POOL_INHERIT = -1,
|
||||
|
||||
/* The floating pool contains a large number of lower priority threads that have affinity over the entire CPU.
|
||||
* Other pools should push jobs that only block and do no work here so that they can yield on the blocking job rather than blocking themselves. */
|
||||
SYS_POOL_FLOATING = 0,
|
||||
|
||||
SYS_POOL_BACKGROUND = 1,
|
||||
SYS_POOL_AUDIO = 2,
|
||||
SYS_POOL_USER = 3,
|
||||
SYS_POOL_SIM = 4,
|
||||
|
||||
NUM_SYS_POOLS
|
||||
};
|
||||
|
||||
/* Job execution order within a pool is based on priority. */
|
||||
enum sys_priority {
|
||||
SYS_PRIORITY_INHERIT = -1,
|
||||
SYS_PRIORITY_HIGH = 0,
|
||||
SYS_PRIORITY_NORMAL = 1,
|
||||
SYS_PRIORITY_LOW = 2,
|
||||
|
||||
NUM_SYS_PRIORITIES
|
||||
};
|
||||
|
||||
struct sys_job_data {
|
||||
i32 id;
|
||||
void *sig;
|
||||
};
|
||||
|
||||
#define SYS_JOB_DEF(job_name, arg_name) void job_name(struct sys_job_data arg_name)
|
||||
typedef SYS_JOB_DEF(sys_job_func, job_data);
|
||||
|
||||
void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_pool pool_kind, enum sys_priority priority, struct snc_counter *counter);
|
||||
|
||||
/* ========================== *
|
||||
* Time
|
||||
* ========================== */
|
||||
|
||||
struct sys_datetime {
|
||||
u32 year;
|
||||
u32 month;
|
||||
u32 day_of_week;
|
||||
u32 day;
|
||||
u32 hour;
|
||||
u32 minute;
|
||||
u32 second;
|
||||
u32 milliseconds;
|
||||
};
|
||||
|
||||
struct sys_datetime sys_local_time(void);
|
||||
|
||||
i64 sys_time_ns(void);
|
||||
|
||||
/* ========================== *
|
||||
* File system
|
||||
*
|
||||
* NOTE: File paths use forward slash '/' as delimiter
|
||||
* ========================== */
|
||||
|
||||
struct sys_file {
|
||||
u64 handle;
|
||||
b32 valid;
|
||||
};
|
||||
|
||||
struct sys_file_time {
|
||||
struct sys_datetime created;
|
||||
struct sys_datetime accessed;
|
||||
struct sys_datetime modified;
|
||||
};
|
||||
|
||||
String sys_get_write_path(Arena *arena);
|
||||
|
||||
b32 sys_is_file(String path);
|
||||
|
||||
b32 sys_is_dir(String path);
|
||||
|
||||
void sys_mkdir(String path);
|
||||
|
||||
struct sys_file sys_file_open_read(String path);
|
||||
|
||||
struct sys_file sys_file_open_read_wait(String path); /* Waits until file is not being used by another program */
|
||||
|
||||
struct sys_file sys_file_open_write(String path);
|
||||
|
||||
struct sys_file sys_file_open_append(String path);
|
||||
|
||||
void sys_file_close(struct sys_file file);
|
||||
|
||||
String sys_file_read_all(Arena *arena, struct sys_file file);
|
||||
|
||||
void sys_file_write(struct sys_file file, String data);
|
||||
|
||||
u64 sys_file_get_size(struct sys_file file);
|
||||
|
||||
struct sys_file_time sys_file_get_time(struct sys_file file);
|
||||
|
||||
/* ========================== *
|
||||
* File map
|
||||
* ========================== */
|
||||
|
||||
struct sys_file_map {
|
||||
String mapped_memory;
|
||||
u64 handle;
|
||||
b32 valid;
|
||||
};
|
||||
|
||||
struct sys_file_map sys_file_map_open_read(struct sys_file file);
|
||||
|
||||
void sys_file_map_close(struct sys_file_map map);
|
||||
|
||||
String sys_file_map_data(struct sys_file_map map);
|
||||
|
||||
/* ========================== *
|
||||
* Dir iter
|
||||
* ========================== */
|
||||
|
||||
struct sys_file_filter_result {
|
||||
String filename;
|
||||
b32 is_dir;
|
||||
};
|
||||
|
||||
struct sys_file_filter {
|
||||
struct sys_file_filter_result info;
|
||||
u64 handle;
|
||||
};
|
||||
|
||||
/* Iterate all files in a directory */
|
||||
struct sys_file_filter sys_file_filter_begin(Arena *arena, String pattern);
|
||||
|
||||
b32 sys_file_filter_next(Arena *arena, struct sys_file_filter *iter);
|
||||
|
||||
void sys_file_filter_end(struct sys_file_filter *iter);
|
||||
|
||||
/* ========================== *
|
||||
* Watch
|
||||
* ========================== */
|
||||
|
||||
enum sys_watch_info_kind {
|
||||
SYS_WATCH_INFO_KIND_UNKNOWN,
|
||||
SYS_WATCH_INFO_KIND_ADDED,
|
||||
SYS_WATCH_INFO_KIND_REMOVED,
|
||||
SYS_WATCH_INFO_KIND_MODIFIED,
|
||||
SYS_WATCH_INFO_KIND_RENAMED_OLD,
|
||||
SYS_WATCH_INFO_KIND_RENAMED_NEW
|
||||
|
||||
};
|
||||
|
||||
struct sys_watch_info {
|
||||
enum sys_watch_info_kind kind;
|
||||
String name;
|
||||
struct sys_watch_info *next;
|
||||
struct sys_watch_info *prev;
|
||||
};
|
||||
|
||||
struct sys_watch_info_list {
|
||||
struct sys_watch_info *first;
|
||||
struct sys_watch_info *last;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
struct sys_watch *sys_watch_alloc(String path);
|
||||
|
||||
void sys_watch_release(struct sys_watch *dw);
|
||||
|
||||
struct sys_watch_info_list sys_watch_read_wait(Arena *arena, struct sys_watch *dw);
|
||||
|
||||
void sys_watch_wake(struct sys_watch *dw);
|
||||
|
||||
/* ========================== *
|
||||
* Window
|
||||
* ========================== */
|
||||
|
||||
enum sys_btn {
|
||||
SYS_BTN_NONE,
|
||||
|
||||
SYS_BTN_M1,
|
||||
SYS_BTN_M2,
|
||||
SYS_BTN_M3,
|
||||
SYS_BTN_M4,
|
||||
SYS_BTN_M5,
|
||||
|
||||
SYS_BTN_MWHEELUP,
|
||||
SYS_BTN_MWHEELDOWN,
|
||||
|
||||
SYS_BTN_ESC,
|
||||
SYS_BTN_F1,
|
||||
SYS_BTN_F2,
|
||||
SYS_BTN_F3,
|
||||
SYS_BTN_F4,
|
||||
SYS_BTN_F5,
|
||||
SYS_BTN_F6,
|
||||
SYS_BTN_F7,
|
||||
SYS_BTN_F8,
|
||||
SYS_BTN_F9,
|
||||
SYS_BTN_F10,
|
||||
SYS_BTN_F11,
|
||||
SYS_BTN_F12,
|
||||
SYS_BTN_F13,
|
||||
SYS_BTN_F14,
|
||||
SYS_BTN_F15,
|
||||
SYS_BTN_F16,
|
||||
SYS_BTN_F17,
|
||||
SYS_BTN_F18,
|
||||
SYS_BTN_F19,
|
||||
SYS_BTN_F20,
|
||||
SYS_BTN_F21,
|
||||
SYS_BTN_F22,
|
||||
SYS_BTN_F23,
|
||||
SYS_BTN_F24,
|
||||
SYS_BTN_GRAVE_ACCENT,
|
||||
SYS_BTN_0,
|
||||
SYS_BTN_1,
|
||||
SYS_BTN_2,
|
||||
SYS_BTN_3,
|
||||
SYS_BTN_4,
|
||||
SYS_BTN_5,
|
||||
SYS_BTN_6,
|
||||
SYS_BTN_7,
|
||||
SYS_BTN_8,
|
||||
SYS_BTN_9,
|
||||
SYS_BTN_MINUS,
|
||||
SYS_BTN_EQUAL,
|
||||
SYS_BTN_BACKSPACE,
|
||||
SYS_BTN_DELETE,
|
||||
SYS_BTN_TAB,
|
||||
SYS_BTN_A,
|
||||
SYS_BTN_B,
|
||||
SYS_BTN_C,
|
||||
SYS_BTN_D,
|
||||
SYS_BTN_E,
|
||||
SYS_BTN_F,
|
||||
SYS_BTN_G,
|
||||
SYS_BTN_H,
|
||||
SYS_BTN_I,
|
||||
SYS_BTN_J,
|
||||
SYS_BTN_K,
|
||||
SYS_BTN_L,
|
||||
SYS_BTN_M,
|
||||
SYS_BTN_N,
|
||||
SYS_BTN_O,
|
||||
SYS_BTN_P,
|
||||
SYS_BTN_Q,
|
||||
SYS_BTN_R,
|
||||
SYS_BTN_S,
|
||||
SYS_BTN_T,
|
||||
SYS_BTN_U,
|
||||
SYS_BTN_V,
|
||||
SYS_BTN_W,
|
||||
SYS_BTN_X,
|
||||
SYS_BTN_Y,
|
||||
SYS_BTN_Z,
|
||||
SYS_BTN_SPACE,
|
||||
SYS_BTN_ENTER,
|
||||
SYS_BTN_CTRL,
|
||||
SYS_BTN_SHIFT,
|
||||
SYS_BTN_ALT,
|
||||
SYS_BTN_UP,
|
||||
SYS_BTN_LEFT,
|
||||
SYS_BTN_DOWN,
|
||||
SYS_BTN_RIGHT,
|
||||
SYS_BTN_PAGE_UP,
|
||||
SYS_BTN_PAGE_DOWN,
|
||||
SYS_BTN_HOME,
|
||||
SYS_BTN_END,
|
||||
SYS_BTN_FORWARD_SLASH,
|
||||
SYS_BTN_PERIOD,
|
||||
SYS_BTN_COMMA,
|
||||
SYS_BTN_QUOTE,
|
||||
SYS_BTN_LEFT_BRACKET,
|
||||
SYS_BTN_RIGHT_BRACKET,
|
||||
SYS_BTN_INSERT,
|
||||
SYS_BTN_SEMICOLON,
|
||||
|
||||
SYS_BTN_COUNT
|
||||
};
|
||||
|
||||
enum sys_window_event_kind {
|
||||
SYS_EVENT_KIND_NONE,
|
||||
|
||||
SYS_EVENT_KIND_BUTTON_DOWN,
|
||||
SYS_EVENT_KIND_BUTTON_UP,
|
||||
SYS_EVENT_KIND_CURSOR_MOVE,
|
||||
SYS_EVENT_KIND_MOUSE_MOVE,
|
||||
SYS_EVENT_KIND_TEXT,
|
||||
SYS_EVENT_KIND_QUIT,
|
||||
|
||||
SYS_EVENT_KIND_COUNT
|
||||
};
|
||||
|
||||
struct sys_window_event {
|
||||
enum sys_window_event_kind kind;
|
||||
|
||||
/* SYS_EVENT_KIND_BUTTON_DOWN */
|
||||
/* SYS_EVENT_KIND_BUTTON_UP */
|
||||
enum sys_btn button;
|
||||
b32 is_repeat;
|
||||
|
||||
/* SYS_EVENT_KIND_TEXT */
|
||||
u32 text_codepoint;
|
||||
|
||||
/* SYS_EVENT_KIND_CURSOR_MOVE */
|
||||
V2 cursor_position;
|
||||
|
||||
/* SYS_EVENT_KIND_MOUSE_MOVE */
|
||||
V2 mouse_delta;
|
||||
};
|
||||
|
||||
struct sys_window_event_array {
|
||||
u64 count;
|
||||
struct sys_window_event *events;
|
||||
};
|
||||
|
||||
/* 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. */
|
||||
|
||||
enum sys_window_settings_flags {
|
||||
SYS_WINDOW_SETTINGS_FLAG_NONE = 0x00,
|
||||
SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN = 0x01,
|
||||
|
||||
/* NOTE: Both maximized and minimized can be true at the same time. This
|
||||
* means that the window was minimized from a maximized state, and will
|
||||
* restore to being maximized once it's un-minimized. */
|
||||
SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED = 0x02,
|
||||
SYS_WINDOW_SETTINGS_FLAG_MINIMIZED = 0x04
|
||||
};
|
||||
|
||||
enum sys_window_flags {
|
||||
SYS_WINDOW_FLAG_NONE = 0x00,
|
||||
SYS_WINDOW_FLAG_SHOWING = 0x02
|
||||
};
|
||||
|
||||
/* sys_window_update_settings should be used when altering settings values */
|
||||
struct sys_window_settings {
|
||||
char title[256];
|
||||
u32 flags;
|
||||
|
||||
/* NOTE: Below fields are NOT representative of actual window dimensions.
|
||||
* These values represent the window dimensions when the window is not
|
||||
* maximized, minimized, or fullscreen. AKA 'floating'. Use
|
||||
* `sys_window_get_size` for rendering instead. */
|
||||
i32 floating_x;
|
||||
i32 floating_y;
|
||||
i32 floating_width;
|
||||
i32 floating_height;
|
||||
};
|
||||
|
||||
struct sys_window *sys_window_alloc(void);
|
||||
|
||||
void sys_window_release(struct sys_window *sys_window);
|
||||
|
||||
struct sys_window_event_array sys_window_pop_events(Arena *arena, struct sys_window *sys_window);
|
||||
|
||||
void sys_window_update_settings(struct sys_window *sys_window, struct sys_window_settings *settings);
|
||||
|
||||
struct sys_window_settings sys_window_get_settings(struct sys_window *sys_window);
|
||||
|
||||
void sys_window_show(struct sys_window *sys_window);
|
||||
|
||||
V2 sys_window_get_size(struct sys_window *sys_window);
|
||||
|
||||
V2 sys_window_get_monitor_size(struct sys_window *sys_window);
|
||||
|
||||
/* Returns a platform specific representation of the window. E.g. `hwnd` on win32. */
|
||||
u64 sys_window_get_internal_handle(struct sys_window *sys_window);
|
||||
|
||||
void sys_window_cursor_set_pos(struct sys_window *sys_window, V2 pos);
|
||||
|
||||
void sys_window_cursor_show(struct sys_window *sys_window);
|
||||
|
||||
void sys_window_cursor_hide(struct sys_window *sys_window);
|
||||
|
||||
void sys_window_cursor_enable_clip(struct sys_window *sys_window, Rect bounds);
|
||||
|
||||
void sys_window_cursor_disable_clip(struct sys_window *sys_window);
|
||||
|
||||
void sys_window_toggle_topmost(struct sys_window *sys_window);
|
||||
|
||||
/* ========================== *
|
||||
* Address
|
||||
* ========================== */
|
||||
|
||||
enum sys_address_family {
|
||||
SYS_ADDRESS_FAMILY_IPV4,
|
||||
SYS_ADDRESS_FAMILY_IPV6
|
||||
};
|
||||
|
||||
struct sys_address {
|
||||
b32 valid;
|
||||
enum sys_address_family family;
|
||||
/* NOTE: ipnb & portnb are stored in network byte order */
|
||||
u8 ipnb[16];
|
||||
u16 portnb;
|
||||
};
|
||||
|
||||
struct sys_address sys_address_from_string(String str);
|
||||
|
||||
struct sys_address sys_address_from_port(u16 port);
|
||||
|
||||
String sys_string_from_address(Arena *arena, struct sys_address address);
|
||||
|
||||
b32 sys_address_eq(struct sys_address a, struct sys_address b);
|
||||
|
||||
/* ========================== *
|
||||
* Sock
|
||||
* ========================== */
|
||||
|
||||
struct sys_sock_read_result {
|
||||
b32 valid; /* Since data.len = 0 can be valid */
|
||||
struct sys_address address;
|
||||
String data;
|
||||
};
|
||||
|
||||
struct sys_sock *sys_sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
|
||||
|
||||
void sys_sock_release(struct sys_sock *sock);
|
||||
|
||||
struct sys_sock_read_result sys_sock_read(Arena *arena, struct sys_sock *sock);
|
||||
|
||||
void sys_sock_write(struct sys_sock *sock, struct sys_address address, String data);
|
||||
|
||||
/* ========================== *
|
||||
* Util
|
||||
* ========================== */
|
||||
|
||||
enum sys_message_box_kind {
|
||||
SYS_MESSAGE_BOX_KIND_OK,
|
||||
SYS_MESSAGE_BOX_KIND_WARNING,
|
||||
SYS_MESSAGE_BOX_KIND_ERROR,
|
||||
SYS_MESSAGE_BOX_KIND_FATAL
|
||||
};
|
||||
|
||||
void sys_message_box(enum sys_message_box_kind kind, String message);
|
||||
|
||||
void sys_set_clipboard_text(String str);
|
||||
|
||||
String sys_get_clipboard_text(Arena *arena);
|
||||
|
||||
u32 sys_num_logical_processors(void);
|
||||
|
||||
u32 sys_current_thread_id(void);
|
||||
|
||||
i64 sys_current_scheduler_period_ns(void);
|
||||
|
||||
/* ========================== *
|
||||
* Exit
|
||||
* ========================== */
|
||||
|
||||
|
||||
#define SYS_EXIT_FUNC(name) void name(void)
|
||||
typedef SYS_EXIT_FUNC(sys_exit_func);
|
||||
|
||||
/* Registers a function to be called during graceful shutdown (in reverse order) */
|
||||
void sys_on_exit(sys_exit_func *func);
|
||||
|
||||
/* Signals the program to shut down gracefully and run exit callbacks */
|
||||
void sys_exit(void);
|
||||
|
||||
/* Forcefully exits the program and displays `msg` to the user */
|
||||
void sys_panic(String msg);
|
||||
|
||||
/* ========================== *
|
||||
* App entry point
|
||||
* ========================== */
|
||||
|
||||
/* Must be defined by app */
|
||||
void sys_app_startup(String args_str);
|
||||
@ -1,68 +0,0 @@
|
||||
/* ========================== *
|
||||
* Mutex
|
||||
* ========================== */
|
||||
|
||||
struct snc_lock {
|
||||
struct snc_mutex *mutex;
|
||||
b32 exclusive;
|
||||
};
|
||||
|
||||
struct alignas(64) snc_mutex {
|
||||
/* Bit 31 = Exclusive lock is held
|
||||
* Bit 30 = Exclusive lock is pending
|
||||
* Bit 0-30 = Shared locks count
|
||||
*/
|
||||
Atomic32 v;
|
||||
|
||||
#if RTC
|
||||
Atomic32 exclusive_fiber_id;
|
||||
u8 _pad[56];
|
||||
#else
|
||||
u8 _pad[60];
|
||||
#endif
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct snc_mutex) == 64); /* Padding validation */
|
||||
STATIC_ASSERT(alignof(struct snc_mutex) == 64); /* Prevent false sharing */
|
||||
|
||||
struct snc_lock snc_lock_spin_e(struct snc_mutex *m, i32 spin);
|
||||
struct snc_lock snc_lock_spin_s(struct snc_mutex *m, i32 spin);
|
||||
struct snc_lock snc_lock_e(struct snc_mutex *m);
|
||||
struct snc_lock snc_lock_s(struct snc_mutex *m);
|
||||
void snc_unlock(struct snc_lock *lock);
|
||||
|
||||
#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
|
||||
* ========================== */
|
||||
|
||||
struct alignas(64) snc_cv {
|
||||
Atomic64 wake_gen;
|
||||
u8 _pad[56];
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct snc_cv) == 64); /* Padding validation */
|
||||
STATIC_ASSERT(alignof(struct snc_cv) == 64); /* Prevent false sharing */
|
||||
|
||||
void snc_cv_wait(struct snc_cv *cv, struct snc_lock *lock);
|
||||
void snc_cv_wait_time(struct snc_cv *cv, struct snc_lock *l, i64 timeout_ns);
|
||||
void snc_cv_signal(struct snc_cv *cv, i32 count);
|
||||
|
||||
/* ========================== *
|
||||
* Counter
|
||||
* ========================== */
|
||||
|
||||
struct alignas(64) snc_counter {
|
||||
Atomic64 v;
|
||||
u8 _pad[56];
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct snc_counter) == 64); /* Padding validation */
|
||||
STATIC_ASSERT(alignof(struct snc_counter) == 64); /* Prevent false sharing */
|
||||
|
||||
void snc_counter_add(struct snc_counter *counter, i64 x);
|
||||
void snc_counter_wait(struct snc_counter *counter);
|
||||
@ -2,7 +2,7 @@
|
||||
#define TAR_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
|
||||
#include "tar_core.h"
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ TTF_StartupReceipt ttf_startup(void)
|
||||
#endif
|
||||
if (error != S_OK) {
|
||||
/* FIXME: Enable this */
|
||||
//sys_panic(LIT("Error creating DWrite factory"));
|
||||
//P_Panic(LIT("Error creating DWrite factory"));
|
||||
(*(volatile int *)0) = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ struct console_log {
|
||||
String msg;
|
||||
i32 level;
|
||||
i32 color_index;
|
||||
struct sys_datetime datetime;
|
||||
P_DateTime datetime;
|
||||
i64 time_ns;
|
||||
Rect bounds;
|
||||
struct console_log *prev;
|
||||
@ -25,8 +25,8 @@ struct console_log {
|
||||
|
||||
GLOBAL struct {
|
||||
Atomic32 shutdown;
|
||||
struct snc_counter shutdown_job_counters;
|
||||
struct sys_window *window;
|
||||
P_Counter shutdown_job_counters;
|
||||
P_Window *window;
|
||||
G_Swapchain *swapchain;
|
||||
|
||||
struct sim_ctx *local_sim_ctx;
|
||||
@ -34,10 +34,10 @@ GLOBAL struct {
|
||||
Arena *arena;
|
||||
String connect_address_str;
|
||||
|
||||
struct sim_client_store *user_client_store;
|
||||
struct sim_client *user_unblended_client; /* Contains snapshots received from local sim */
|
||||
struct sim_client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
||||
struct sim_snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
||||
ClientStore *user_client_store;
|
||||
Client *user_unblended_client; /* Contains snapshots received from local sim */
|
||||
Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
||||
Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
||||
|
||||
/* Usage stats */
|
||||
i64 last_second_reset_ns;
|
||||
@ -50,14 +50,14 @@ GLOBAL struct {
|
||||
struct bind_state bind_states[USER_BIND_KIND_COUNT];
|
||||
|
||||
/* Debug camera */
|
||||
struct sim_ent_id debug_following;
|
||||
EntId debug_following;
|
||||
b32 debug_camera;
|
||||
b32 debug_camera_panning;
|
||||
V2 debug_camera_pan_start;
|
||||
b32 debug_draw;
|
||||
|
||||
/* Debug console */
|
||||
struct snc_mutex console_logs_mutex;
|
||||
P_Mutex console_logs_mutex;
|
||||
Arena *console_logs_arena;
|
||||
struct console_log *first_console_log;
|
||||
struct console_log *last_console_log;
|
||||
@ -66,13 +66,13 @@ GLOBAL struct {
|
||||
b32 debug_console;
|
||||
|
||||
/* Window -> user */
|
||||
struct snc_mutex sys_window_events_mutex;
|
||||
P_Mutex sys_window_events_mutex;
|
||||
Arena *sys_window_events_arena;
|
||||
|
||||
/* User -> local sim */
|
||||
struct snc_mutex user_sim_cmd_mutex;
|
||||
struct sim_control user_sim_cmd_control;
|
||||
struct sim_ent_id user_hovered_ent;
|
||||
P_Mutex user_sim_cmd_mutex;
|
||||
ControlData user_sim_cmd_control;
|
||||
EntId user_hovered_ent;
|
||||
u64 last_user_sim_cmd_gen;
|
||||
u64 user_sim_cmd_gen;
|
||||
|
||||
@ -80,9 +80,9 @@ GLOBAL struct {
|
||||
Atomic32 user_paused_steps;
|
||||
|
||||
/* Local sim -> user */
|
||||
struct snc_mutex local_to_user_client_mutex;
|
||||
struct sim_client_store *local_to_user_client_store;
|
||||
struct sim_client *local_to_user_client;
|
||||
P_Mutex local_to_user_client_mutex;
|
||||
ClientStore *local_to_user_client_store;
|
||||
Client *local_to_user_client;
|
||||
i64 local_to_user_client_publish_dt_ns;
|
||||
i64 local_to_user_client_publish_time_ns;
|
||||
|
||||
@ -125,47 +125,47 @@ GLOBAL struct {
|
||||
|
||||
/* TODO: Remove this */
|
||||
|
||||
GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
||||
[SYS_BTN_W] = USER_BIND_KIND_MOVE_UP,
|
||||
[SYS_BTN_S] = USER_BIND_KIND_MOVE_DOWN,
|
||||
[SYS_BTN_A] = USER_BIND_KIND_MOVE_LEFT,
|
||||
[SYS_BTN_D] = USER_BIND_KIND_MOVE_RIGHT,
|
||||
//[SYS_BTN_ALT] = USER_BIND_KIND_WALK,
|
||||
[SYS_BTN_M1] = USER_BIND_KIND_FIRE,
|
||||
[SYS_BTN_M2] = USER_BIND_KIND_FIRE_ALT,
|
||||
GLOBAL READONLY enum user_bind_kind g_binds[P_Btn_Count] = {
|
||||
[P_Btn_W] = USER_BIND_KIND_MOVE_UP,
|
||||
[P_Btn_S] = USER_BIND_KIND_MOVE_DOWN,
|
||||
[P_Btn_A] = USER_BIND_KIND_MOVE_LEFT,
|
||||
[P_Btn_D] = USER_BIND_KIND_MOVE_RIGHT,
|
||||
//[P_Btn_Alt] = USER_BIND_KIND_WALK,
|
||||
[P_Btn_M1] = USER_BIND_KIND_FIRE,
|
||||
[P_Btn_M2] = USER_BIND_KIND_FIRE_ALT,
|
||||
|
||||
/* Testing */
|
||||
|
||||
[SYS_BTN_Z] = USER_BIND_KIND_TILE_TEST,
|
||||
[P_Btn_Z] = USER_BIND_KIND_TILE_TEST,
|
||||
|
||||
[SYS_BTN_M5] = USER_BIND_KIND_DEBUG_DRAG,
|
||||
[SYS_BTN_M4] = USER_BIND_KIND_DEBUG_DELETE,
|
||||
[SYS_BTN_F] = USER_BIND_KIND_DEBUG_EXPLODE,
|
||||
[SYS_BTN_T] = USER_BIND_KIND_DEBUG_TELEPORT,
|
||||
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
||||
[SYS_BTN_1] = USER_BIND_KIND_DEBUG_SPAWN1,
|
||||
[SYS_BTN_2] = USER_BIND_KIND_DEBUG_SPAWN2,
|
||||
[SYS_BTN_3] = USER_BIND_KIND_DEBUG_SPAWN3,
|
||||
[SYS_BTN_4] = USER_BIND_KIND_DEBUG_SPAWN4,
|
||||
[SYS_BTN_G] = USER_BIND_KIND_DEBUG_WALLS,
|
||||
[SYS_BTN_N] = USER_BIND_KIND_DEBUG_STEP,
|
||||
[SYS_BTN_Q] = USER_BIND_KIND_DEBUG_FOLLOW,
|
||||
[SYS_BTN_F1] = USER_BIND_KIND_DEBUG_PAUSE,
|
||||
[SYS_BTN_F2] = USER_BIND_KIND_DEBUG_CAMERA,
|
||||
[SYS_BTN_F3] = USER_BIND_KIND_DEBUG_DRAW,
|
||||
[SYS_BTN_F4] = USER_BIND_KIND_DEBUG_TOGGLE_TOPMOST,
|
||||
[SYS_BTN_GRAVE_ACCENT] = USER_BIND_KIND_DEBUG_CONSOLE,
|
||||
[SYS_BTN_ALT] = USER_BIND_KIND_FULLSCREEN_MOD,
|
||||
[SYS_BTN_ENTER] = USER_BIND_KIND_FULLSCREEN,
|
||||
[SYS_BTN_MWHEELUP] = USER_BIND_KIND_ZOOM_IN,
|
||||
[SYS_BTN_MWHEELDOWN] = USER_BIND_KIND_ZOOM_OUT,
|
||||
[SYS_BTN_M3] = USER_BIND_KIND_PAN,
|
||||
[P_Btn_M5] = USER_BIND_KIND_DEBUG_DRAG,
|
||||
[P_Btn_M4] = USER_BIND_KIND_DEBUG_DELETE,
|
||||
[P_Btn_F] = USER_BIND_KIND_DEBUG_EXPLODE,
|
||||
[P_Btn_T] = USER_BIND_KIND_DEBUG_TELEPORT,
|
||||
[P_Btn_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
||||
[P_Btn_1] = USER_BIND_KIND_DEBUG_SPAWN1,
|
||||
[P_Btn_2] = USER_BIND_KIND_DEBUG_SPAWN2,
|
||||
[P_Btn_3] = USER_BIND_KIND_DEBUG_SPAWN3,
|
||||
[P_Btn_4] = USER_BIND_KIND_DEBUG_SPAWN4,
|
||||
[P_Btn_G] = USER_BIND_KIND_DEBUG_WALLS,
|
||||
[P_Btn_N] = USER_BIND_KIND_DEBUG_STEP,
|
||||
[P_Btn_Q] = USER_BIND_KIND_DEBUG_FOLLOW,
|
||||
[P_Btn_F1] = USER_BIND_KIND_DEBUG_PAUSE,
|
||||
[P_Btn_F2] = USER_BIND_KIND_DEBUG_CAMERA,
|
||||
[P_Btn_F3] = USER_BIND_KIND_DEBUG_DRAW,
|
||||
[P_Btn_F4] = USER_BIND_KIND_DEBUG_TOGGLE_TOPMOST,
|
||||
[P_Btn_GraveAccent] = USER_BIND_KIND_DEBUG_CONSOLE,
|
||||
[P_Btn_Alt] = USER_BIND_KIND_FULLSCREEN_MOD,
|
||||
[P_Btn_Enter] = USER_BIND_KIND_FULLSCREEN,
|
||||
[P_Btn_MWheelUp] = USER_BIND_KIND_ZOOM_IN,
|
||||
[P_Btn_MWheelDown] = USER_BIND_KIND_ZOOM_OUT,
|
||||
[P_Btn_M3] = USER_BIND_KIND_PAN,
|
||||
|
||||
#if RTC
|
||||
/* Debug */
|
||||
[SYS_BTN_FORWARD_SLASH] = USER_BIND_KIND_RESET_DEBUG_STEPS,
|
||||
[SYS_BTN_COMMA] = USER_BIND_KIND_DECR_DEBUG_STEPS,
|
||||
[SYS_BTN_PERIOD] = USER_BIND_KIND_INCR_DEBUG_STEPS
|
||||
[P_Btn_ForwardSlash] = USER_BIND_KIND_RESET_DEBUG_STEPS,
|
||||
[P_Btn_Comma] = USER_BIND_KIND_DECR_DEBUG_STEPS,
|
||||
[P_Btn_Period] = USER_BIND_KIND_INCR_DEBUG_STEPS
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -173,19 +173,19 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(user_shutdown);
|
||||
INTERNAL P_ExitFuncDef(user_shutdown);
|
||||
INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log);
|
||||
INTERNAL SYS_JOB_DEF(user_update_job, _);
|
||||
INTERNAL SYS_JOB_DEF(local_sim_job , _);
|
||||
INTERNAL P_JobDef(user_update_job, _);
|
||||
INTERNAL P_JobDef(local_sim_job , _);
|
||||
|
||||
struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
struct sprite_startup_receipt *sprite_sr,
|
||||
S_StartupReceipt *sprite_sr,
|
||||
D_StartupReceipt *draw_sr,
|
||||
AC_StartupReceipt *asset_cache_sr,
|
||||
struct sound_startup_receipt *sound_sr,
|
||||
SND_StartupReceipt *sound_sr,
|
||||
M_StartupReceipt *mixer_sr,
|
||||
N_StartupReceipt *host_sr,
|
||||
struct sim_startup_receipt *sim_sr,
|
||||
SimStartupReceipt *sim_sr,
|
||||
String connect_address_str)
|
||||
{
|
||||
__prof;
|
||||
@ -201,7 +201,7 @@ struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
gstat_set(GSTAT_DEBUG_STEPS, U64_MAX);
|
||||
|
||||
G.arena = arena_alloc(GIBI(64));
|
||||
G.real_time_ns = sys_time_ns();
|
||||
G.real_time_ns = P_TimeNs();
|
||||
|
||||
/* TODO: Remove this */
|
||||
G.connect_address_str = string_copy(G.arena, connect_address_str);
|
||||
@ -228,24 +228,24 @@ struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
//log_register_callback(debug_console_log_callback, LOG_LEVEL_SUCCESS);
|
||||
log_register_callback(debug_console_log_callback, LOG_LEVEL_DEBUG);
|
||||
|
||||
G.window = sys_window_alloc();
|
||||
G.window = P_AllocWindow();
|
||||
G.swapchain = gp_swapchain_alloc(G.window, V2i32FromXY(100, 100));
|
||||
sys_window_show(G.window);
|
||||
P_ShowWindow(G.window);
|
||||
|
||||
/* Start jobs */
|
||||
sys_run(1, user_update_job, 0, SYS_POOL_USER, SYS_PRIORITY_HIGH, &G.shutdown_job_counters);
|
||||
sys_run(1, local_sim_job, 0, SYS_POOL_SIM, SYS_PRIORITY_HIGH, &G.shutdown_job_counters);
|
||||
sys_on_exit(&user_shutdown);
|
||||
P_Run(1, user_update_job, 0, P_Pool_User, P_Priority_High, &G.shutdown_job_counters);
|
||||
P_Run(1, local_sim_job, 0, P_Pool_Sim, P_Priority_High, &G.shutdown_job_counters);
|
||||
P_OnExit(&user_shutdown);
|
||||
|
||||
return (struct user_startup_receipt) { 0 };
|
||||
}
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(user_shutdown)
|
||||
INTERNAL P_ExitFuncDef(user_shutdown)
|
||||
{
|
||||
__prof;
|
||||
atomic32_fetch_set(&G.shutdown, 1);
|
||||
snc_counter_wait(&G.shutdown_job_counters);
|
||||
sys_window_release(G.window);
|
||||
P_ReleaseWindow(G.window);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -296,7 +296,7 @@ INTERNAL void debug_draw_movement(struct sim_ent *ent)
|
||||
INTERNAL String get_ent_debug_text(Arena *arena, struct sim_ent *ent)
|
||||
{
|
||||
TempArena scratch = scratch_begin(arena);
|
||||
struct sim_snapshot *ss = ent->ss;
|
||||
Snapshot *ss = ent->ss;
|
||||
|
||||
const u8 hex[] = "0123456789abcdef";
|
||||
|
||||
@ -388,7 +388,7 @@ INTERNAL String get_ent_debug_text(Arena *arena, struct sim_ent *ent)
|
||||
INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log)
|
||||
{
|
||||
__prof;
|
||||
struct snc_lock lock = snc_lock_e(&G.console_logs_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.console_logs_mutex);
|
||||
{
|
||||
struct console_log *clog = arena_push(G.console_logs_arena, struct console_log);
|
||||
clog->level = log.level;
|
||||
@ -446,10 +446,10 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
|
||||
}
|
||||
G.console_logs_height = 0;
|
||||
|
||||
i64 now_ns = sys_time_ns();
|
||||
i64 now_ns = P_TimeNs();
|
||||
F_Font *font = font_load_async(LIT("font/fixedsys.ttf"), 12.0f);
|
||||
if (font) {
|
||||
struct snc_lock lock = snc_lock_e(&G.console_logs_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.console_logs_mutex);
|
||||
{
|
||||
for (struct console_log *log = G.last_console_log; log; log = log->prev) {
|
||||
f32 opacity = 0.75;
|
||||
@ -466,7 +466,7 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
|
||||
/* Draw text */
|
||||
String text = log->msg;
|
||||
if (!minimized) {
|
||||
struct sys_datetime datetime = log->datetime;
|
||||
P_DateTime datetime = log->datetime;
|
||||
text = string_format(
|
||||
scratch.arena,
|
||||
LIT("[%F:%F:%F.%F] %F"),
|
||||
@ -548,7 +548,7 @@ INTERNAL SORT_COMPARE_FUNC_DEF(ent_draw_order_cmp, arg_a, arg_b, udata)
|
||||
* Update
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void user_update(struct sys_window *window)
|
||||
INTERNAL void user_update(P_Window *window)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -558,11 +558,11 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
* Begin frame
|
||||
* ========================== */
|
||||
|
||||
G.real_dt_ns = sys_time_ns() - G.real_time_ns;
|
||||
G.real_dt_ns = P_TimeNs() - G.real_time_ns;
|
||||
G.real_time_ns += G.real_dt_ns;
|
||||
G.screen_size = sys_window_get_size(window);
|
||||
G.screen_size = P_GetWindowSize(window);
|
||||
|
||||
struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
|
||||
S_Scope *sprite_frame_scope = sprite_scope_begin();
|
||||
|
||||
/* ========================== *
|
||||
* Pull latest local sim snapshot
|
||||
@ -570,11 +570,11 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
|
||||
{
|
||||
__profn("Pull snapshot");
|
||||
struct snc_lock lock = snc_lock_e(&G.local_to_user_client_mutex);
|
||||
P_Lock lock = snc_lock_e(&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) {
|
||||
struct sim_snapshot *src = sim_snapshot_from_tick(G.local_to_user_client, last_tick);
|
||||
Snapshot *src = sim_snapshot_from_tick(G.local_to_user_client, last_tick);
|
||||
sim_snapshot_alloc(G.user_unblended_client, src, src->tick);
|
||||
G.last_local_to_user_snapshot_published_at_ns = G.local_to_user_client_publish_time_ns;
|
||||
G.average_local_to_user_snapshot_publish_dt_ns -= G.average_local_to_user_snapshot_publish_dt_ns / 50;
|
||||
@ -597,7 +597,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
}
|
||||
|
||||
/* Predict local sim time based on average snapshot publish dt. */
|
||||
struct sim_snapshot *newest_snapshot = sim_snapshot_from_tick(G.user_unblended_client, G.user_unblended_client->last_tick);
|
||||
Snapshot *newest_snapshot = sim_snapshot_from_tick(G.user_unblended_client, G.user_unblended_client->last_tick);
|
||||
G.local_sim_last_known_time_ns = newest_snapshot->sim_time_ns;
|
||||
G.local_sim_last_known_tick = newest_snapshot->tick;
|
||||
if (atomic32_fetch(&G.user_paused)) {
|
||||
@ -621,10 +621,10 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
}
|
||||
|
||||
/* Get two snapshots nearest to render time */
|
||||
struct sim_snapshot *left_snapshot = sim_snapshot_nil();
|
||||
struct sim_snapshot *right_snapshot = newest_snapshot;
|
||||
Snapshot *left_snapshot = sim_snapshot_nil();
|
||||
Snapshot *right_snapshot = newest_snapshot;
|
||||
{
|
||||
struct sim_snapshot *ss = sim_snapshot_from_tick(G.user_unblended_client, G.user_unblended_client->first_tick);
|
||||
Snapshot *ss = sim_snapshot_from_tick(G.user_unblended_client, G.user_unblended_client->first_tick);
|
||||
while (ss->valid) {
|
||||
u64 next_tick = ss->next_tick;
|
||||
i64 ss_time_ns = ss->sim_time_ns;
|
||||
@ -678,7 +678,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
{
|
||||
__profn("Process sys events");
|
||||
|
||||
struct sys_window_event_array events = sys_window_pop_events(scratch.arena, window);
|
||||
P_WindowEventArray events = P_PopWindowEvents(scratch.arena, window);
|
||||
|
||||
/* Reset bind pressed / released states */
|
||||
for (u32 i = 0; i < countof(G.bind_states); ++i) {
|
||||
@ -688,32 +688,32 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
}
|
||||
|
||||
for (u64 ent_index = 0; ent_index < events.count; ++ent_index) {
|
||||
struct sys_window_event *event = &events.events[ent_index];
|
||||
if (event->kind == SYS_EVENT_KIND_QUIT) {
|
||||
sys_exit();
|
||||
P_WindowEvent *event = &events.events[ent_index];
|
||||
if (event->kind == P_WindowEventKind_Quit) {
|
||||
P_Exit();
|
||||
}
|
||||
|
||||
if (event->kind == SYS_EVENT_KIND_BUTTON_UP) {
|
||||
if (event->kind == P_WindowEventKind_ButtonUp) {
|
||||
/* Escape quit */
|
||||
if (event->button == SYS_BTN_ESC) {
|
||||
sys_exit();
|
||||
if (event->button == P_Btn_ESC) {
|
||||
P_Exit();
|
||||
}
|
||||
}
|
||||
|
||||
/* Update mouse pos */
|
||||
if (event->kind == SYS_EVENT_KIND_CURSOR_MOVE) {
|
||||
if (event->kind == P_WindowEventKind_CursorMove) {
|
||||
G.screen_cursor = event->cursor_position;
|
||||
}
|
||||
|
||||
/* Update bind states */
|
||||
if ((event->kind == SYS_EVENT_KIND_BUTTON_DOWN || event->kind == SYS_EVENT_KIND_BUTTON_UP)) {
|
||||
enum sys_btn button = event->button;
|
||||
button = button >= SYS_BTN_COUNT ? SYS_BTN_NONE : button;
|
||||
if ((event->kind == P_WindowEventKind_ButtonDown|| event->kind == P_WindowEventKind_ButtonUp)) {
|
||||
P_Btn button = event->button;
|
||||
button = button >= P_Btn_Count ? P_Btn_None : button;
|
||||
enum user_bind_kind bind = g_binds[button];
|
||||
if (bind) {
|
||||
b32 pressed = event->kind == SYS_EVENT_KIND_BUTTON_DOWN;
|
||||
b32 pressed = event->kind == P_WindowEventKind_ButtonDown;
|
||||
#if 0
|
||||
b32 out_of_bounds = button >= SYS_BTN_M1 && button <= SYS_BTN_M5 &&
|
||||
b32 out_of_bounds = button >= P_Btn_M1 && button <= P_Btn_M5 &&
|
||||
(G.ui_cursor.x < 0 ||
|
||||
G.ui_cursor.y < 0 ||
|
||||
G.ui_cursor.x > G.ui_size.x ||
|
||||
@ -782,9 +782,9 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
/* Test fullscreen */
|
||||
{
|
||||
if (G.bind_states[USER_BIND_KIND_FULLSCREEN].num_presses && G.bind_states[USER_BIND_KIND_FULLSCREEN_MOD].is_held) {
|
||||
struct sys_window_settings settings = sys_window_get_settings(window);
|
||||
settings.flags ^= SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN;
|
||||
sys_window_update_settings(window, &settings);
|
||||
P_WindowSettings settings = P_GetWindowSettings(window);
|
||||
settings.flags ^= P_WindowSettingsFlag_Fullscreen;
|
||||
P_UpdateWindowSettings(window, &settings);
|
||||
}
|
||||
}
|
||||
|
||||
@ -793,7 +793,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
}
|
||||
|
||||
if (G.bind_states[USER_BIND_KIND_DEBUG_TOGGLE_TOPMOST].num_presses > 0) {
|
||||
sys_window_toggle_topmost(window);
|
||||
P_ToggleWindowTopmost(window);
|
||||
logf_success("Toggle topmost");
|
||||
}
|
||||
|
||||
@ -1166,7 +1166,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
//if (sprite_tag_is_nil(ent->sprite)) continue;
|
||||
|
||||
struct sprite_tag sprite = ent->sprite;
|
||||
S_Tag sprite = ent->sprite;
|
||||
|
||||
struct sim_ent *parent = sim_ent_from_id(G.ss_blended, ent->parent);
|
||||
|
||||
@ -1223,15 +1223,15 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
|
||||
/* Draw sprite */
|
||||
if (!sprite_tag_is_nil(sprite)) {
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
|
||||
struct sprite_texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite);
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
|
||||
S_Texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite);
|
||||
|
||||
/* TODO: Fade in placeholder if texture isn't loaded */
|
||||
if (sheet->loaded && texture->loaded) {
|
||||
b32 is_light = sim_ent_has_prop(ent, SEPROP_LIGHT_TEST);
|
||||
V3 emittance = ent->sprite_emittance;
|
||||
u32 tint = ent->sprite_tint;
|
||||
struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, ent->animation_frame);
|
||||
S_SheetFrame frame = sprite_sheet_get_frame(sheet, ent->animation_frame);
|
||||
D_MaterialParams params = DRAW_MATERIAL_PARAMS(.xf = sprite_xform, .texture = texture->gp_texture, .tint = tint, .clip = frame.clip, .is_light = is_light, .light_emittance = emittance);
|
||||
draw_material(G.render_sig, params);
|
||||
}
|
||||
@ -1241,14 +1241,14 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
/* TODO: Something better */
|
||||
if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) {
|
||||
V2i32 chunk_index = ent->tile_chunk_index;
|
||||
struct sprite_tag tile_sprite = sprite_tag_from_path(LIT("sprite/tile.ase"));
|
||||
struct sprite_texture *tile_texture = sprite_texture_from_tag_async(sprite_frame_scope, tile_sprite);
|
||||
S_Tag tile_sprite = sprite_tag_from_path(LIT("sprite/tile.ase"));
|
||||
S_Texture *tile_texture = sprite_texture_from_tag_async(sprite_frame_scope, tile_sprite);
|
||||
if (tile_texture->loaded) {
|
||||
f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT;
|
||||
for (i32 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) {
|
||||
for (i32 tile_x = 0; tile_x < SIM_TILES_PER_CHUNK_SQRT; ++tile_x) {
|
||||
V2i32 local_tile_index = V2i32FromXY(tile_x, tile_y);
|
||||
enum sim_tile_kind tile = ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
TileKind tile = ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
//if (tile > -1) {
|
||||
if (tile == SIM_TILE_KIND_WALL) {
|
||||
V2i32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index);
|
||||
@ -1289,8 +1289,8 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
|
||||
/* Draw focus arrow */
|
||||
if (ent == local_control || sim_ent_id_eq(ent->id, G.debug_following)) {
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite);
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite);
|
||||
S_SheetSlice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
|
||||
V2 start = xform_mul_v2(sprite_xform, slice.center);
|
||||
start = xform_mul_v2(G.world_to_ui_xf, start);
|
||||
V2 end = v2_add(xf.og, ent->control.focus);
|
||||
@ -1301,18 +1301,18 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
#if 0
|
||||
/* Draw slices */
|
||||
if (!sprite_tag_is_nil(ent->sprite)) {
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
|
||||
S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
|
||||
|
||||
u32 quad_color = RGBA32_F(1, 0, 0.5, 1);
|
||||
u32 point_color = RGBA32_F(1, 0, 0, 1);
|
||||
u32 ray_color = RGBA32_F(1, 0, 0.5, 1);
|
||||
|
||||
for (u64 i = 0; i < sheet->slice_groups_count; ++i) {
|
||||
struct sprite_sheet_slice_group *group = &sheet->slice_groups[i];
|
||||
S_SheetSliceGroup *group = &sheet->slice_groups[i];
|
||||
if (string_ends_with(group->name, LIT(".ray"))) continue;
|
||||
|
||||
for (u32 j = 0; j < group->per_frame_count; ++j) {
|
||||
struct sprite_sheet_slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j];
|
||||
S_SheetSlice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j];
|
||||
|
||||
V2 center = xform_mul_v2(sprite_xform, slice.center);
|
||||
center = xform_mul_v2(G.world_to_ui_xf, center);
|
||||
@ -1404,7 +1404,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
|
||||
/* Draw contact constraint */
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTACT_CONSTRAINT)) {
|
||||
struct phys_contact_constraint *data = &ent->contact_constraint_data;
|
||||
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);
|
||||
(UNUSED)e0;
|
||||
@ -1416,7 +1416,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
f32 radius = 5;
|
||||
for (u32 i = 0; i < data->num_points; ++i) {
|
||||
u32 color = (data->skip_solve || data->wrong_dir) ? ALPHA32_F(COLOR_YELLOW, 0.3) : RGBA32_F(0.8, 0.2, 0.2, 1);
|
||||
struct phys_contact_point point = data->points[i];
|
||||
ContactPoint point = data->points[i];
|
||||
V2 dbg_pt = point.dbg_pt;
|
||||
|
||||
/* Draw point */
|
||||
@ -1473,7 +1473,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
/* Draw collision debug */
|
||||
#if COLLIDER_DEBUG
|
||||
if (sim_ent_has_prop(ent, SEPROP_COLLISION_DEBUG)) {
|
||||
struct phys_collision_debug *data = &ent->collision_debug_data;
|
||||
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);
|
||||
@ -1693,8 +1693,8 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
if (!G.debug_camera) {
|
||||
__profn("Draw crosshair");
|
||||
V2 crosshair_pos = G.ui_cursor;
|
||||
struct sprite_tag crosshair = sprite_tag_from_path(LIT("sprite/crosshair.ase"));
|
||||
struct sprite_texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair);
|
||||
S_Tag crosshair = sprite_tag_from_path(LIT("sprite/crosshair.ase"));
|
||||
S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair);
|
||||
V2 size = V2FromXY(t->width, t->height);
|
||||
Xform xf = XFORM_TRS(.t = crosshair_pos, .s = size);
|
||||
draw_ui_rect(G.render_sig, DRAW_UI_RECT_PARAMS(.xf = xf, .texture = t->gp_texture));
|
||||
@ -1705,17 +1705,17 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
{
|
||||
__profn("Update window cursor");
|
||||
if (G.debug_camera) {
|
||||
sys_window_cursor_disable_clip(G.window);
|
||||
sys_window_cursor_show(G.window);
|
||||
P_DisableWindoweCursorClip(G.window);
|
||||
P_ShowWindowCursor(G.window);
|
||||
} else {
|
||||
struct sprite_texture *t = sprite_texture_from_tag_async(sprite_frame_scope, sprite_tag_from_path(LIT("sprite/crosshair.ase")));
|
||||
S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, sprite_tag_from_path(LIT("sprite/crosshair.ase")));
|
||||
V2 size = V2FromXY(t->width, t->height);
|
||||
Rect cursor_clip = RECT_FROM_V2(G.ui_screen_offset, G.ui_size);
|
||||
cursor_clip.pos = v2_add(cursor_clip.pos, v2_mul(size, 0.5f));
|
||||
cursor_clip.pos = v2_add(cursor_clip.pos, V2FromXY(1, 1));
|
||||
cursor_clip.size = v2_sub(cursor_clip.size, size);
|
||||
sys_window_cursor_hide(G.window);
|
||||
sys_window_cursor_enable_clip(G.window, cursor_clip);
|
||||
P_HideWindowCursor(G.window);
|
||||
P_EnableWindoweCursorClip(G.window, cursor_clip);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1780,7 +1780,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
|
||||
/* Queue player control cmd */
|
||||
{
|
||||
struct sim_control control = ZI;
|
||||
ControlData control = ZI;
|
||||
control.move = input_move_dir;
|
||||
control.focus = input_aim_dir;
|
||||
control.dbg_cursor = G.world_cursor;
|
||||
@ -1848,7 +1848,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
|
||||
/* Set user sim control */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.user_sim_cmd_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.user_sim_cmd_mutex);
|
||||
|
||||
/* Reset flags */
|
||||
if (G.user_sim_cmd_gen != G.last_user_sim_cmd_gen) {
|
||||
@ -1882,7 +1882,7 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
|
||||
{
|
||||
/* Update network usage stats */
|
||||
i64 stat_now_ns = sys_time_ns();
|
||||
i64 stat_now_ns = P_TimeNs();
|
||||
G.net_bytes_read.last_second_end = gstat_get(GSTAT_SOCK_BYTES_RECEIVED);
|
||||
G.net_bytes_sent.last_second_end = gstat_get(GSTAT_SOCK_BYTES_SENT);
|
||||
if (stat_now_ns - G.last_second_reset_ns > NS_FROM_SECONDS(1)) {
|
||||
@ -2081,12 +2081,12 @@ INTERNAL void user_update(struct sys_window *window)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
INTERNAL SYS_JOB_DEF(user_update_job, _)
|
||||
INTERNAL P_JobDef(user_update_job, _)
|
||||
{
|
||||
(UNUSED)_;
|
||||
i64 time_ns = sys_time_ns();
|
||||
i64 time_ns = P_TimeNs();
|
||||
while (!atomic32_fetch(&G.shutdown)) {
|
||||
struct sys_window *window = G.window;
|
||||
P_Window *window = G.window;
|
||||
{
|
||||
__profn("User sleep");
|
||||
{
|
||||
@ -2096,7 +2096,7 @@ INTERNAL SYS_JOB_DEF(user_update_job, _)
|
||||
{
|
||||
__profn("Frame limiter wait");
|
||||
sys_sleep_frame(time_ns, 1000000000 / FPS_LIMIT);
|
||||
time_ns = sys_time_ns();
|
||||
time_ns = P_TimeNs();
|
||||
}
|
||||
}
|
||||
user_update(window);
|
||||
@ -2117,10 +2117,10 @@ INTERNAL SYS_JOB_DEF(user_update_job, _)
|
||||
|
||||
|
||||
|
||||
INTERNAL void generate_user_input_cmds(struct sim_client *user_input_client, u64 tick)
|
||||
INTERNAL void generate_user_input_cmds(Client *user_input_client, u64 tick)
|
||||
{
|
||||
struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick);
|
||||
struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, 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);
|
||||
/* Find / create local control cmd ent */
|
||||
struct sim_ent *control_cmd = sim_ent_find_first_match_one(user_input_ss, SEPROP_CMD);
|
||||
@ -2132,7 +2132,7 @@ INTERNAL void generate_user_input_cmds(struct sim_client *user_input_client, u64
|
||||
sim_ent_activate(control_cmd, user_input_ss->tick);
|
||||
}
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.user_sim_cmd_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.user_sim_cmd_mutex);
|
||||
/* Update control cmd */
|
||||
{
|
||||
control_cmd->cmd_control = G.user_sim_cmd_control;
|
||||
@ -2166,7 +2166,7 @@ INTERNAL void generate_user_input_cmds(struct sim_client *user_input_client, u64
|
||||
|
||||
|
||||
struct sim_ss_decode_node {
|
||||
struct sim_client *client;
|
||||
Client *client;
|
||||
u64 tick;
|
||||
u64 base_tick;
|
||||
String tmp_encoded;
|
||||
@ -2179,7 +2179,7 @@ struct sim_decode_queue {
|
||||
};
|
||||
|
||||
|
||||
INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
INTERNAL P_JobDef(local_sim_job, _)
|
||||
{
|
||||
(UNUSED)_;
|
||||
|
||||
@ -2196,7 +2196,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
N_Host *host;
|
||||
if (G.connect_address_str.len > 0) {
|
||||
host = host_alloc(0);
|
||||
struct sys_address addr = sys_address_from_string(G.connect_address_str);
|
||||
P_Address addr = P_AddressFromString(G.connect_address_str);
|
||||
host_queue_connect_to_address(host, addr);
|
||||
} else {
|
||||
host = host_alloc(12345);
|
||||
@ -2205,15 +2205,15 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
|
||||
Bitbuff msg_writer_bb = bitbuff_alloc(GIBI(64));
|
||||
Bitbuff snapshot_writer_bb = bitbuff_alloc(GIBI(64));
|
||||
struct sim_accel accel = sim_accel_alloc();
|
||||
SimAccel accel = sim_accel_alloc();
|
||||
|
||||
struct sim_client_store *store = sim_client_store_alloc();
|
||||
struct sim_client *user_input_client = sim_client_alloc(store); /* Stores snapshots containing commands to be published to local client */
|
||||
struct sim_client *local_client = sim_client_alloc(store); /* Stores snapshots produced locally */
|
||||
struct sim_client *publish_client = sim_client_alloc(store); /* Stores versions of local snapshots that will be published to remote sims */
|
||||
ClientStore *store = sim_client_store_alloc();
|
||||
Client *user_input_client = sim_client_alloc(store); /* Stores snapshots containing commands to be published to local client */
|
||||
Client *local_client = sim_client_alloc(store); /* Stores snapshots produced locally */
|
||||
Client *publish_client = sim_client_alloc(store); /* Stores versions of local snapshots that will be published to remote sims */
|
||||
|
||||
struct sim_client *master_client = sim_client_nil(); /* Stores snapshots received from master */
|
||||
struct sim_client *master_blended_client = sim_client_nil(); /* Stores interpolated master snapshots */
|
||||
Client *master_client = sim_client_nil(); /* Stores snapshots received from master */
|
||||
Client *master_blended_client = sim_client_nil(); /* Stores interpolated master snapshots */
|
||||
b32 initialized_from_master = 0;
|
||||
|
||||
|
||||
@ -2265,7 +2265,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
{
|
||||
__profn("Sim update");
|
||||
|
||||
real_dt_ns = sys_time_ns() - real_time_ns;
|
||||
real_dt_ns = P_TimeNs() - real_time_ns;
|
||||
real_time_ns += real_dt_ns;
|
||||
|
||||
N_EventList host_events = host_update_begin(scratch.arena, host);
|
||||
@ -2275,7 +2275,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
{
|
||||
for (N_Event *event = host_events.first; event; event = event->next) {
|
||||
N_ChannelId channel_id = event->channel_id;
|
||||
struct sim_client *client = sim_client_from_channel_id(store, channel_id);
|
||||
Client *client = sim_client_from_channel_id(store, channel_id);
|
||||
switch (event->kind) {
|
||||
case HOST_EVENT_KIND_CHANNEL_OPENED:
|
||||
{
|
||||
@ -2330,7 +2330,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
tmp_encoded.text = br_read_bytes_raw(&decoder_br, tmp_encoded.len);
|
||||
if (!tmp_encoded.text) tmp_encoded.len = 0;
|
||||
|
||||
struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick);
|
||||
Snapshot *base_ss = sim_snapshot_from_tick(client, base_tick);
|
||||
if (base_ss->tick == base_tick) {
|
||||
if (is_master) {
|
||||
/* Queue incoming slave client snapshot for decoding */
|
||||
@ -2392,16 +2392,16 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
|
||||
/* Decode incoming snapshots */
|
||||
for (struct sim_ss_decode_node *n = queue.first; n; n = n->next) {
|
||||
struct sim_client *client = n->client;
|
||||
Client *client = n->client;
|
||||
u64 base_tick = n->base_tick;
|
||||
u64 tick = n->tick;
|
||||
struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick);
|
||||
Snapshot *base_ss = sim_snapshot_from_tick(client, base_tick);
|
||||
if (base_ss->tick == base_tick) {
|
||||
Bitbuff bb = bitbuff_from_string(n->tmp_encoded);
|
||||
BitbuffReader br = br_from_bitbuff(&bb);
|
||||
|
||||
/* Alloc & decode snapshot */
|
||||
struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick);
|
||||
Snapshot *ss = sim_snapshot_alloc(client, base_ss, tick);
|
||||
sim_snapshot_decode(&br, ss);
|
||||
|
||||
/* Assume all incoming ents want to be sync srcs */
|
||||
@ -2440,7 +2440,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
/* Update networked clients */
|
||||
u64 oldest_client_ack = 0;
|
||||
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
|
||||
struct sim_client *client = &store->clients[i];
|
||||
Client *client = &store->clients[i];
|
||||
if (client->valid && client != local_client && client != publish_client && client != user_input_client && client != master_client) {
|
||||
client->last_rtt_ns = host_get_channel_last_rtt_ns(host, client->channel_id);
|
||||
/* Release unneeded received snapshots */
|
||||
@ -2493,14 +2493,14 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
/* Step master */
|
||||
u64 prev_tick = local_client->last_tick;
|
||||
u64 next_tick = prev_tick + 1;
|
||||
struct sim_step_ctx ctx = ZI;
|
||||
SimStepCtx ctx = ZI;
|
||||
ctx.is_master = is_master;
|
||||
ctx.sim_dt_ns = step_dt_ns;
|
||||
ctx.accel = &accel;
|
||||
ctx.user_input_client = user_input_client;
|
||||
ctx.master_client = master_client;
|
||||
ctx.publish_client = publish_client;
|
||||
struct sim_snapshot *prev_world = sim_snapshot_from_tick(local_client, prev_tick);
|
||||
Snapshot *prev_world = sim_snapshot_from_tick(local_client, prev_tick);
|
||||
ctx.world = sim_snapshot_alloc(local_client, prev_world, next_tick);
|
||||
generate_user_input_cmds(user_input_client, next_tick);
|
||||
sim_step(&ctx);
|
||||
@ -2511,7 +2511,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
|
||||
|
||||
b32 master_ss_is_blended = 0;
|
||||
struct sim_snapshot *master_ss = sim_snapshot_nil();
|
||||
Snapshot *master_ss = sim_snapshot_nil();
|
||||
{
|
||||
/* How along are we between master sim ticks (0 = start of tick, 1 = end of tick) */
|
||||
f64 tick_progress = 0;
|
||||
@ -2521,7 +2521,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
}
|
||||
|
||||
/* Predict master sim time based on average snapshot publish dt. */
|
||||
struct sim_snapshot *newest_snapshot = sim_snapshot_from_tick(master_client, master_client->last_tick);
|
||||
Snapshot *newest_snapshot = sim_snapshot_from_tick(master_client, master_client->last_tick);
|
||||
i64 master_sim_predicted_time_ns = newest_snapshot->sim_time_ns + (newest_snapshot->sim_dt_ns * tick_progress);
|
||||
|
||||
/* Determine blend time */
|
||||
@ -2539,10 +2539,10 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
|
||||
/* Get snapshot nearest to master blend time */
|
||||
/* TODO: Blend */
|
||||
struct sim_snapshot *left_snapshot = sim_snapshot_nil();
|
||||
struct sim_snapshot *right_snapshot = newest_snapshot;
|
||||
Snapshot *left_snapshot = sim_snapshot_nil();
|
||||
Snapshot *right_snapshot = newest_snapshot;
|
||||
{
|
||||
struct sim_snapshot *ss = sim_snapshot_from_tick(master_client, master_client->first_tick);
|
||||
Snapshot *ss = sim_snapshot_from_tick(master_client, master_client->first_tick);
|
||||
while (ss->valid) {
|
||||
u64 next_tick = ss->next_tick;
|
||||
i64 ss_time_ns = ss->sim_time_ns;
|
||||
@ -2665,7 +2665,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
}
|
||||
|
||||
/* Sync master with local base tick */
|
||||
struct sim_snapshot *base_ss = sim_snapshot_from_tick(local_client, step_base_tick);
|
||||
Snapshot *base_ss = sim_snapshot_from_tick(local_client, step_base_tick);
|
||||
if (mispredicted_tick) {
|
||||
if (base_ss->valid) {
|
||||
sim_snapshot_sync_ents(base_ss, master_ss, master_player->id, 0);
|
||||
@ -2680,7 +2680,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
/* Step */
|
||||
generate_user_input_cmds(user_input_client, step_end_tick);
|
||||
{
|
||||
struct sim_step_ctx ctx = ZI;
|
||||
SimStepCtx ctx = ZI;
|
||||
ctx.is_master = is_master;
|
||||
ctx.sim_dt_ns = step_dt_ns;
|
||||
ctx.accel = &accel;
|
||||
@ -2689,7 +2689,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
ctx.publish_client = publish_client;
|
||||
|
||||
u64 step_tick = step_base_tick + 1;
|
||||
struct sim_snapshot *prev_ss = base_ss;
|
||||
Snapshot *prev_ss = base_ss;
|
||||
while (step_tick <= step_end_tick) {
|
||||
ctx.world = sim_snapshot_alloc(local_client, prev_ss, step_tick);
|
||||
if (!mispredicted_tick && step_tick == step_end_tick) {
|
||||
@ -2705,15 +2705,15 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
|
||||
/* Publish snapshot to remote clients */
|
||||
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
|
||||
struct sim_client *client = &store->clients[i];
|
||||
Client *client = &store->clients[i];
|
||||
if (client->valid && client != user_input_client && client != local_client && client != publish_client) {
|
||||
BitbuffWriter msg_bw = bw_from_bitbuff(&msg_writer_bb);
|
||||
|
||||
bw_write_uv(&msg_bw, client->highest_received_tick); /* ack */
|
||||
bw_write_uv(&msg_bw, client->ack); /* double ack */
|
||||
|
||||
struct sim_snapshot *base_ss = sim_snapshot_from_tick(publish_client, client->ack);
|
||||
struct sim_snapshot *publish_ss;
|
||||
Snapshot *base_ss = sim_snapshot_from_tick(publish_client, client->ack);
|
||||
Snapshot *publish_ss;
|
||||
if (client == master_client) {
|
||||
/* If sending to master, start sending all snapshots since last ack */
|
||||
publish_ss = sim_snapshot_from_closest_tick_gte(publish_client, base_ss->tick + 1);
|
||||
@ -2747,12 +2747,12 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
|
||||
|
||||
/* Copy local snapshot to user client */
|
||||
{
|
||||
struct sim_snapshot *local_ss = sim_snapshot_from_tick(local_client, local_client->last_tick);
|
||||
Snapshot *local_ss = sim_snapshot_from_tick(local_client, local_client->last_tick);
|
||||
if (local_ss->valid) {
|
||||
/* TODO: Double buffer */
|
||||
struct snc_lock lock = snc_lock_e(&G.local_to_user_client_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.local_to_user_client_mutex);
|
||||
sim_snapshot_alloc(G.local_to_user_client, local_ss, local_ss->tick);
|
||||
i64 publish_ns = sys_time_ns();
|
||||
i64 publish_ns = P_TimeNs();
|
||||
if (last_publish_to_user_ns == 0) {
|
||||
last_publish_to_user_ns = publish_ns - G.average_local_to_user_snapshot_publish_dt_ns;
|
||||
}
|
||||
|
||||
@ -1,7 +1,3 @@
|
||||
struct sprite_startup_receipt;
|
||||
struct sound_startup_receipt;
|
||||
struct sim_startup_receipt;
|
||||
|
||||
enum user_bind_kind {
|
||||
USER_BIND_KIND_NONE,
|
||||
|
||||
@ -53,11 +49,11 @@ enum user_bind_kind {
|
||||
|
||||
struct user_startup_receipt { i32 _; };
|
||||
struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
struct sprite_startup_receipt *sprite_sr,
|
||||
S_StartupReceipt *sprite_sr,
|
||||
D_StartupReceipt *draw_sr,
|
||||
AC_StartupReceipt *asset_cache_sr,
|
||||
struct sound_startup_receipt *sound_sr,
|
||||
SND_StartupReceipt *sound_sr,
|
||||
M_StartupReceipt *mixer_sr,
|
||||
N_StartupReceipt *host_sr,
|
||||
struct sim_startup_receipt *sim_sr,
|
||||
SimStartupReceipt *sim_sr,
|
||||
String connect_address_str);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define WATCH_H
|
||||
|
||||
#include "../base/base.h"
|
||||
#include "../sys/sys.h"
|
||||
#include "../platform/platform.h"
|
||||
|
||||
#include "watch_core.h"
|
||||
|
||||
|
||||
@ -6,17 +6,17 @@ struct watch_event {
|
||||
};
|
||||
|
||||
GLOBAL struct {
|
||||
struct sys_watch *watch;
|
||||
P_Watch *watch;
|
||||
Atomic32 watch_shutdown;
|
||||
struct snc_counter watch_jobs_counter;
|
||||
P_Counter watch_jobs_counter;
|
||||
|
||||
struct snc_mutex watch_dispatcher_mutex;
|
||||
P_Mutex watch_dispatcher_mutex;
|
||||
Arena *watch_events_arena;
|
||||
struct watch_event *first_watch_event;
|
||||
struct watch_event *last_watch_event;
|
||||
struct snc_cv watch_dispatcher_cv;
|
||||
P_Cv watch_dispatcher_cv;
|
||||
|
||||
struct snc_mutex watch_callbacks_mutex;
|
||||
P_Mutex watch_callbacks_mutex;
|
||||
watch_callback *watch_callbacks[64];
|
||||
u64 num_watch_callbacks;
|
||||
} G = ZI, DEBUG_ALIAS(G, G_watch);
|
||||
@ -25,34 +25,34 @@ GLOBAL struct {
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_JOB_DEF(watch_monitor_job, _);
|
||||
INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _);
|
||||
INTERNAL SYS_EXIT_FUNC(watch_shutdown);
|
||||
INTERNAL P_JobDef(watch_monitor_job, _);
|
||||
INTERNAL P_JobDef(watch_dispatcher_job, _);
|
||||
INTERNAL P_ExitFuncDef(watch_shutdown);
|
||||
|
||||
void watch_startup(void)
|
||||
{
|
||||
G.watch = sys_watch_alloc(LIT("./"));
|
||||
G.watch = P_AllocWatch(LIT("./"));
|
||||
|
||||
G.watch_events_arena = arena_alloc(GIBI(64));
|
||||
|
||||
sys_run(1, watch_monitor_job, 0, SYS_POOL_FLOATING, SYS_PRIORITY_LOW, &G.watch_jobs_counter);
|
||||
sys_run(1, watch_dispatcher_job, 0, SYS_POOL_BACKGROUND, SYS_PRIORITY_LOW, &G.watch_jobs_counter);
|
||||
sys_on_exit(&watch_shutdown);
|
||||
P_Run(1, watch_monitor_job, 0, P_Pool_Floating, P_Priority_Low, &G.watch_jobs_counter);
|
||||
P_Run(1, watch_dispatcher_job, 0, P_Pool_Background, P_Priority_Low, &G.watch_jobs_counter);
|
||||
P_OnExit(&watch_shutdown);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Watch
|
||||
* ========================== */
|
||||
|
||||
INTERNAL SYS_EXIT_FUNC(watch_shutdown)
|
||||
INTERNAL P_ExitFuncDef(watch_shutdown)
|
||||
{
|
||||
__prof;
|
||||
atomic32_fetch_set(&G.watch_shutdown, 1);
|
||||
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
snc_cv_signal(&G.watch_dispatcher_cv, I32_MAX);
|
||||
sys_watch_wake(G.watch);
|
||||
P_WakeWatch(G.watch);
|
||||
snc_unlock(&lock);
|
||||
}
|
||||
snc_counter_wait(&G.watch_jobs_counter);
|
||||
@ -60,18 +60,18 @@ INTERNAL SYS_EXIT_FUNC(watch_shutdown)
|
||||
|
||||
void watch_register_callback(watch_callback *callback)
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.watch_callbacks_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.watch_callbacks_mutex);
|
||||
{
|
||||
if (G.num_watch_callbacks < countof(G.watch_callbacks)) {
|
||||
G.watch_callbacks[G.num_watch_callbacks++] = callback;
|
||||
} else {
|
||||
sys_panic(LIT("Max resource watch callbacks reached"));
|
||||
P_Panic(LIT("Max resource watch callbacks reached"));
|
||||
}
|
||||
}
|
||||
snc_unlock(&lock);
|
||||
}
|
||||
|
||||
INTERNAL SYS_JOB_DEF(watch_monitor_job, _)
|
||||
INTERNAL P_JobDef(watch_monitor_job, _)
|
||||
{
|
||||
(UNUSED)_;
|
||||
TempArena scratch = scratch_begin_no_conflict();
|
||||
@ -83,11 +83,11 @@ INTERNAL SYS_JOB_DEF(watch_monitor_job, _)
|
||||
|
||||
while (!atomic32_fetch(&G.watch_shutdown)) {
|
||||
TempArena temp = arena_temp_begin(scratch.arena);
|
||||
struct sys_watch_info_list info_list = sys_watch_read_wait(temp.arena, G.watch);
|
||||
P_WatchInfoList info_list = P_ReadWatchWait(temp.arena, G.watch);
|
||||
if (info_list.first && !atomic32_fetch(&G.watch_shutdown)) {
|
||||
struct snc_lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
P_Lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
{
|
||||
for (struct sys_watch_info *info = info_list.first; info; info = info->next) {
|
||||
for (P_WatchInfo *info = info_list.first; info; info = info->next) {
|
||||
String name_src = info->name;
|
||||
b32 ignore = 0;
|
||||
for (u32 i = 0; i < countof(ignored); ++i) {
|
||||
@ -129,7 +129,7 @@ struct watch_callback_job_sig {
|
||||
watch_callback **callbacks;
|
||||
};
|
||||
|
||||
INTERNAL SYS_JOB_DEF(watch_callback_job, job)
|
||||
INTERNAL P_JobDef(watch_callback_job, job)
|
||||
{
|
||||
__prof;
|
||||
struct watch_callback_job_sig *sig = job.sig;
|
||||
@ -138,7 +138,7 @@ INTERNAL SYS_JOB_DEF(watch_callback_job, job)
|
||||
callback(name);
|
||||
}
|
||||
|
||||
INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _)
|
||||
INTERNAL P_JobDef(watch_dispatcher_job, _)
|
||||
{
|
||||
(UNUSED)_;
|
||||
|
||||
@ -152,12 +152,12 @@ INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _)
|
||||
/* Delay so that duplicate events pile up */
|
||||
{
|
||||
__profn("Delay");
|
||||
sys_wait(0, 0, 0, NS_FROM_SECONDS(WATCH_DISPATCHER_DELAY_SECONDS));
|
||||
P_Wait(0, 0, 0, NS_FROM_SECONDS(WATCH_DISPATCHER_DELAY_SECONDS));
|
||||
}
|
||||
|
||||
/* Pull watch events from queue */
|
||||
{
|
||||
struct snc_lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||
P_Lock lock = snc_lock_e(&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);
|
||||
@ -177,7 +177,7 @@ INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _)
|
||||
/* Build callbacks array */
|
||||
u64 num_callbacks = 0;
|
||||
watch_callback **callbacks = 0;
|
||||
struct snc_lock callbacks_lock = snc_lock_s(&G.watch_callbacks_mutex);
|
||||
P_Lock callbacks_lock = snc_lock_s(&G.watch_callbacks_mutex);
|
||||
{
|
||||
num_callbacks = G.num_watch_callbacks;
|
||||
callbacks = arena_push_array_no_zero(scratch.arena, watch_callback *, num_callbacks);
|
||||
@ -204,8 +204,8 @@ INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _)
|
||||
struct watch_callback_job_sig sig = ZI;
|
||||
sig.name = e->name;
|
||||
sig.callbacks = callbacks;
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(num_callbacks, watch_callback_job, &sig, SYS_POOL_BACKGROUND, SYS_PRIORITY_LOW, &counter);
|
||||
P_Counter counter = ZI;
|
||||
P_Run(num_callbacks, watch_callback_job, &sig, P_Pool_Background, P_Priority_Low, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
}
|
||||
@ -215,7 +215,7 @@ INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _)
|
||||
}
|
||||
|
||||
/* Wait for event */
|
||||
struct snc_lock lock = snc_lock_s(&G.watch_dispatcher_mutex);
|
||||
P_Lock lock = snc_lock_s(&G.watch_dispatcher_mutex);
|
||||
{
|
||||
shutdown = atomic32_fetch(&G.watch_shutdown);
|
||||
while (!shutdown && !G.first_watch_event) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user