refactor progress

This commit is contained in:
jacob 2025-07-29 00:06:43 -05:00
parent 8f96d89f35
commit 1a33021a52
64 changed files with 3104 additions and 2954 deletions

View File

@ -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));

View 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"

View File

@ -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");

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -54,7 +54,7 @@ String _incbin_get(_IncbinRcResource *inc)
EnumResourceNamesW(0, RT_RCDATA, &enum_func, (LONG_PTR)&params);
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;

View File

@ -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);
}

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -2,7 +2,7 @@
#define NET_H
#include "../base/base.h"
#include "../sys/sys.h"
#include "../platform/platform.h"
#include "net_core.h"

View File

@ -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 */

View File

@ -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
View 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
View 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

View 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);

View File

@ -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");

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}
}

View 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

View 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;

View File

@ -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"

View File

@ -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)_;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"))) {

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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)) {

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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;
}

View File

@ -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);

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -1,6 +0,0 @@
#include "sys.h"
#include "sys_snc.c"
#include "sys_sleep.c"
#include "sys_core.c"
#include "sys_log.c"

View File

@ -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

View File

@ -1,5 +0,0 @@
#if PLATFORM_WINDOWS
# include "sys_core_win32.c"
#else
# error System core layer not implemented
#endif

View File

@ -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);

View File

@ -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);

View File

@ -2,7 +2,7 @@
#define TAR_H
#include "../base/base.h"
#include "../sys/sys.h"
#include "../platform/platform.h"
#include "tar_core.h"

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -2,7 +2,7 @@
#define WATCH_H
#include "../base/base.h"
#include "../sys/sys.h"
#include "../platform/platform.h"
#include "watch_core.h"

View File

@ -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) {