convert sys_timestamp_t to struct

This commit is contained in:
jacob 2025-01-29 10:22:00 -06:00
parent fef1d98c26
commit 4eef91dd63
11 changed files with 100 additions and 60 deletions

View File

@ -102,7 +102,7 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams)
struct asset *asset = params->asset; struct asset *asset = params->asset;
logf_info("Loading font \"%F\" (point size %F)", FMT_STR(path), FMT_FLOAT((f64)point_size)); logf_info("Loading font \"%F\" (point size %F)", FMT_STR(path), FMT_FLOAT((f64)point_size));
sys_timestamp_t start_ts = sys_timestamp(); struct sys_timestamp start_ts = sys_timestamp_prog();
ASSERT(string_ends_with(path, STR(".ttf"))); ASSERT(string_ends_with(path, STR(".ttf")));
if (!resource_exists(path)) { if (!resource_exists(path)) {
@ -157,7 +157,8 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams)
font_task_params_release(params); font_task_params_release(params);
logf_info("Finished loading font \"%F\" (point size %F) in %F seconds", FMT_STR(path), FMT_FLOAT((f64)point_size), FMT_FLOAT(sys_timestamp_seconds(sys_timestamp() - start_ts))); f64 elapsed = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), start_ts));
logf_info("Finished loading font \"%F\" (point size %F) in %F seconds", FMT_STR(path), FMT_FLOAT((f64)point_size), FMT_FLOAT(elapsed));
asset_cache_mark_ready(asset, font); asset_cache_mark_ready(asset, font);
scratch_end(scratch); scratch_end(scratch);

View File

@ -504,7 +504,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
* ========================== */ * ========================== */
++G.tick.tick_id; ++G.tick.tick_id;
G.tick.tick_ts = sys_timestamp(); G.tick.tick_ts = sys_timestamp_prog();
G.tick.dt = max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale); G.tick.dt = max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale);
G.tick.time += G.tick.dt; G.tick.time += G.tick.dt;
@ -1347,13 +1347,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
(UNUSED)arg; (UNUSED)arg;
sys_timestamp_t last_frame_ts = 0; struct sys_timestamp last_frame_ts = ZI;
f64 target_dt = GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0; f64 target_dt = GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0;
while (!atomic_i32_eval(&G.game_thread_shutdown)) { while (!atomic_i32_eval(&G.game_thread_shutdown)) {
__profscope(game_update_w_sleep); __profscope(game_update_w_sleep);
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
sleep_frame(last_frame_ts, target_dt); sleep_frame(last_frame_ts, target_dt);
last_frame_ts = sys_timestamp(); last_frame_ts = sys_timestamp_prog();
{ {
struct game_cmd_array game_cmds = pop_cmds(temp.arena); struct game_cmd_array game_cmds = pop_cmds(temp.arena);
if (!G.paused) { if (!G.paused) {

View File

@ -7,6 +7,10 @@ struct sprite_startup_receipt;
struct sound_startup_receipt; struct sound_startup_receipt;
struct phys_startup_receipt; struct phys_startup_receipt;
/* ========================== *
* Game cmd
* ========================== */
enum game_cmd_state { enum game_cmd_state {
GAME_CMD_STATE_STOP = -1, GAME_CMD_STATE_STOP = -1,
GAME_CMD_STATE_NO_CHANGE = 0, GAME_CMD_STATE_NO_CHANGE = 0,
@ -30,16 +34,6 @@ enum game_cmd_kind {
GAME_CMD_KIND_COUNT GAME_CMD_KIND_COUNT
}; };
/* Absolute layers */
#define GAME_LAYER_FLOOR_DECALS -300
#define GAME_LAYER_BULLETS -200
#define GAME_LAYER_TRACERS -100
#define GAME_LAYER_SHOULDERS 0
/* Relative layers */
#define GAME_LAYER_RELATIVE_DEFAULT 0
#define GAME_LAYER_RELATIVE_WEAPON 1
struct game_cmd { struct game_cmd {
enum game_cmd_kind kind; enum game_cmd_kind kind;
enum game_cmd_state state; enum game_cmd_state state;
@ -61,6 +55,16 @@ struct game_cmd_array {
u64 count; u64 count;
}; };
/* Absolute layers */
#define GAME_LAYER_FLOOR_DECALS -300
#define GAME_LAYER_BULLETS -200
#define GAME_LAYER_TRACERS -100
#define GAME_LAYER_SHOULDERS 0
/* Relative layers */
#define GAME_LAYER_RELATIVE_DEFAULT 0
#define GAME_LAYER_RELATIVE_WEAPON 1
struct game_startup_receipt { i32 _; }; struct game_startup_receipt { i32 _; };
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr, struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
struct sprite_startup_receipt *sheet_sr, struct sprite_startup_receipt *sheet_sr,

View File

@ -115,7 +115,7 @@ INLINE void ix_pause(void)
_mm_pause(); _mm_pause();
} }
INLINE u64 ix_clock(void) INLINE i64 ix_clock(void)
{ {
return __rdtsc(); return __rdtsc();
} }

View File

@ -91,7 +91,7 @@ INTERNAL WORK_TASK_FUNC_DEF(sound_load_asset_task, vparams)
u32 flags = params->flags; u32 flags = params->flags;
logf_info("Loading sound \"%F\"", FMT_STR(path)); logf_info("Loading sound \"%F\"", FMT_STR(path));
sys_timestamp_t start_ts = sys_timestamp(); struct sys_timestamp start_ts = sys_timestamp_prog();
b32 success = true; b32 success = true;
struct string error_msg = STR("Unknown error"); struct string error_msg = STR("Unknown error");
@ -132,9 +132,8 @@ INTERNAL WORK_TASK_FUNC_DEF(sound_load_asset_task, vparams)
}; };
MEMCPY(sound->pcm.samples, decoded.pcm.samples, decoded.pcm.count * sizeof(*decoded.pcm.samples)); MEMCPY(sound->pcm.samples, decoded.pcm.samples, decoded.pcm.count * sizeof(*decoded.pcm.samples));
logf_info("Finished loading sound \"%F\" in %F seconds", f64 elapsed = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), start_ts));
FMT_STR(path), logf_info("Finished loading sound \"%F\" in %F seconds", FMT_STR(path), FMT_FLOAT(elapsed));
FMT_FLOAT(sys_timestamp_seconds(sys_timestamp() - start_ts)));
asset_cache_mark_ready(asset, sound); asset_cache_mark_ready(asset, sound);
} else { } else {

View File

@ -342,7 +342,7 @@ INTERNAL void cache_node_load_texture(struct cache_node *n, struct sprite_tag ta
struct string path = tag.path; struct string path = tag.path;
logf_info("Loading sprite texture \"%F\"", FMT_STR(path)); logf_info("Loading sprite texture \"%F\"", FMT_STR(path));
sys_timestamp_t start_ts = sys_timestamp(); struct sys_timestamp start_ts = sys_timestamp_prog();
ASSERT(string_ends_with(path, STR(".ase"))); ASSERT(string_ends_with(path, STR(".ase")));
ASSERT(n->kind == CACHE_NODE_KIND_TEXTURE); ASSERT(n->kind == CACHE_NODE_KIND_TEXTURE);
@ -383,9 +383,10 @@ INTERNAL void cache_node_load_texture(struct cache_node *n, struct sprite_tag ta
n->memory_usage = n->arena.committed + memory_size; n->memory_usage = n->arena.committed + memory_size;
atomic_u64_eval_add(&G.cache.memory_usage, n->memory_usage); atomic_u64_eval_add(&G.cache.memory_usage, n->memory_usage);
f64 elapsed = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), start_ts));
logf_info("Finished loading sprite texture \"%F\" in %F seconds (cache size: %F bytes).", logf_info("Finished loading sprite texture \"%F\" in %F seconds (cache size: %F bytes).",
FMT_STR(path), FMT_STR(path),
FMT_FLOAT(sys_timestamp_seconds(sys_timestamp() - start_ts)), FMT_FLOAT(elapsed),
FMT_UINT(n->memory_usage)); FMT_UINT(n->memory_usage));
atomic_u32_eval_exchange(&n->state, CACHE_NODE_STATE_LOADED); atomic_u32_eval_exchange(&n->state, CACHE_NODE_STATE_LOADED);
@ -647,7 +648,7 @@ INTERNAL void cache_node_load_sheet(struct cache_node *n, struct sprite_tag tag)
struct string path = tag.path; struct string path = tag.path;
logf_info("Loading sprite sheet \"%F\"", FMT_STR(path)); logf_info("Loading sprite sheet \"%F\"", FMT_STR(path));
sys_timestamp_t start_ts = sys_timestamp(); struct sys_timestamp start_ts = sys_timestamp_prog();
//ASSERT(string_ends_with(path, STR(".ase"))); //ASSERT(string_ends_with(path, STR(".ase")));
ASSERT(n->kind == CACHE_NODE_KIND_SHEET); ASSERT(n->kind == CACHE_NODE_KIND_SHEET);
@ -682,9 +683,10 @@ INTERNAL void cache_node_load_sheet(struct cache_node *n, struct sprite_tag tag)
n->memory_usage = n->arena.committed; n->memory_usage = n->arena.committed;
atomic_u64_eval_add(&G.cache.memory_usage, n->memory_usage); atomic_u64_eval_add(&G.cache.memory_usage, n->memory_usage);
f64 elapsed = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), start_ts));
logf_info("Finished loading sprite sheet \"%F\" in %F seconds (cache size: %F bytes).", logf_info("Finished loading sprite sheet \"%F\" in %F seconds (cache size: %F bytes).",
FMT_STR(path), FMT_STR(path),
FMT_FLOAT(sys_timestamp_seconds(sys_timestamp() - start_ts)), FMT_FLOAT(elapsed),
FMT_UINT(n->memory_usage)); FMT_UINT(n->memory_usage));

View File

@ -174,25 +174,50 @@ void sys_memory_set_committed_readonly(void *address, u64 size);
void sys_memory_set_committed_readwrite(void *address, u64 size); void sys_memory_set_committed_readwrite(void *address, u64 size);
/* ========================== * /* ========================== *
* Time * Timestamp
* ========================== */
struct sys_timestamp {
u64 v;
};
/* Returns timestamp representing time since program start */
struct sys_timestamp sys_timestamp_prog(void);
/* NOTE: Conversion between timestamp & seconds should only happen with small
* timestamp values (like relative timestamps) to avoid precision loss */
struct sys_timestamp sys_timestamp_from_seconds(f64 s);
f64 sys_timestamp_to_seconds(struct sys_timestamp ts);
INLINE struct sys_timestamp sys_timestamp_add(struct sys_timestamp a, struct sys_timestamp b)
{
struct sys_timestamp res;
res.v = a.v + b.v;
return res;
}
INLINE struct sys_timestamp sys_timestamp_sub(struct sys_timestamp a, struct sys_timestamp b)
{
struct sys_timestamp res;
res.v = a.v - b.v;
return res;
}
/* ========================== *
* Datetime
* ========================== */ * ========================== */
struct sys_datetime { struct sys_datetime {
u32 year; u32 year;
u32 month; u32 month;
u32 day_of_week; u32 day_of_week;
u32 day; u32 day;
u32 hour; u32 hour;
u32 minute; u32 minute;
u32 second; u32 second;
u32 milliseconds; u32 milliseconds;
}; };
typedef u64 sys_timestamp_t;
sys_timestamp_t sys_timestamp(void);
f64 sys_timestamp_seconds(sys_timestamp_t ts);
struct sys_datetime sys_local_time(void); struct sys_datetime sys_local_time(void);
/* ========================== * /* ========================== *

View File

@ -244,16 +244,25 @@ INTERNAL i64 _win32_i64_muldiv(i64 value, i64 numer, i64 denom) {
return q * numer + r * numer / denom; return q * numer + r * numer / denom;
} }
sys_timestamp_t sys_timestamp(void) struct sys_timestamp sys_timestamp_prog(void)
{ {
struct sys_timestamp ts;
LARGE_INTEGER time; LARGE_INTEGER time;
QueryPerformanceCounter(&time); QueryPerformanceCounter(&time);
return (u64)_win32_i64_muldiv(time.QuadPart - G.timer_start.QuadPart, 1000000000, G.timer_frequency.QuadPart); ts.v = (u64)_win32_i64_muldiv(time.QuadPart - G.timer_start.QuadPart, 1000000000, G.timer_frequency.QuadPart);
return ts;
} }
f64 sys_timestamp_seconds(sys_timestamp_t ts) struct sys_timestamp sys_timestamp_from_seconds(f64 s)
{ {
return (f64)ts / 1000000000.0; struct sys_timestamp ts;
ts.v = (u64)(s * 1000000000.0);
return ts;
}
f64 sys_timestamp_to_seconds(struct sys_timestamp ts)
{
return (f64)(ts.v) / 1000000000.0;
} }
struct sys_datetime sys_local_time(void) struct sys_datetime sys_local_time(void)

View File

@ -291,13 +291,13 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
from_tick = oldest_tick; from_tick = oldest_tick;
to_tick = newest_tick; to_tick = newest_tick;
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) { for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
f64 bt_time = sys_timestamp_seconds(bt->world.tick_ts); f64 bt_time = sys_timestamp_to_seconds(bt->world.tick_ts);
if (bt_time < blend_time && bt_time > sys_timestamp_seconds(from_tick->tick_ts)) { if (bt_time < blend_time && bt_time > sys_timestamp_to_seconds(from_tick->tick_ts)) {
from_tick = &bt->world; from_tick = &bt->world;
} }
if (bt_time > blend_time && bt_time < sys_timestamp_seconds(to_tick->tick_ts)) { if (bt_time > blend_time && bt_time < sys_timestamp_to_seconds(to_tick->tick_ts)) {
to_tick = &bt->world; to_tick = &bt->world;
} }
} }
@ -309,8 +309,8 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
u64 bts_to_free_count = 0; u64 bts_to_free_count = 0;
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) { for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
f64 bt_time = sys_timestamp_seconds(bt->world.tick_ts); f64 bt_time = sys_timestamp_to_seconds(bt->world.tick_ts);
if (bt_time < sys_timestamp_seconds(from_tick->tick_ts)) { if (bt_time < sys_timestamp_to_seconds(from_tick->tick_ts)) {
*arena_push(scratch.arena, struct blend_tick *) = bt; *arena_push(scratch.arena, struct blend_tick *) = bt;
++bts_to_free_count; ++bts_to_free_count;
} }
@ -490,7 +490,7 @@ INTERNAL void user_update(void)
* Begin frame * Begin frame
* ========================== */ * ========================== */
f64 cur_time = sys_timestamp_seconds(sys_timestamp()); f64 cur_time = sys_timestamp_to_seconds(sys_timestamp_prog());
G.dt = max_f64(0.0, cur_time - G.time); G.dt = max_f64(0.0, cur_time - G.time);
G.time += G.dt; G.time += G.dt;
G.screen_size = sys_window_get_size(G.window); G.screen_size = sys_window_get_size(G.window);
@ -500,11 +500,11 @@ INTERNAL void user_update(void)
struct game_cmd_list cmd_list = ZI; struct game_cmd_list cmd_list = ZI;
/* ========================== * /* ========================== *
* Produce interpolated tick * Interpolate between game ticks
* ========================== */ * ========================== */
{ {
__profscope(produce_interpolated_tick); __profscope(interpolate_ticks);
#if USER_INTERP_ENABLED #if USER_INTERP_ENABLED
/* TODO: Use actual fps of game thread (will differ from GAME_FPS if game thread is lagging) to hide lag with slow-motion? */ /* TODO: Use actual fps of game thread (will differ from GAME_FPS if game thread is lagging) to hide lag with slow-motion? */
@ -518,8 +518,8 @@ INTERNAL void user_update(void)
f32 tick_blend = 0; f32 tick_blend = 0;
{ {
f64 t0_time = sys_timestamp_seconds(t0->tick_ts); f64 t0_time = sys_timestamp_to_seconds(t0->tick_ts);
f64 t1_time = sys_timestamp_seconds(t1->tick_ts); f64 t1_time = sys_timestamp_to_seconds(t1->tick_ts);
if (t1_time > t0_time) { if (t1_time > t0_time) {
tick_blend = (f32)((blend_time - t0_time) / (t1_time - t0_time)); tick_blend = (f32)((blend_time - t0_time) / (t1_time - t0_time));
} }
@ -1717,13 +1717,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_thread_entry_point, arg)
{ {
(UNUSED)arg; (UNUSED)arg;
sys_timestamp_t last_frame_ts = 0; struct sys_timestamp last_frame_ts = ZI;
f64 target_dt = USER_FRAME_LIMIT > (0) ? (1.0 / USER_FRAME_LIMIT) : 0; f64 target_dt = USER_FRAME_LIMIT > (0) ? (1.0 / USER_FRAME_LIMIT) : 0;
while (!atomic_i32_eval(&G.user_thread_shutdown)) { while (!atomic_i32_eval(&G.user_thread_shutdown)) {
__profscope(user_update_w_sleep); __profscope(user_update_w_sleep);
sleep_frame(last_frame_ts, target_dt); sleep_frame(last_frame_ts, target_dt);
last_frame_ts = sys_timestamp(); last_frame_ts = sys_timestamp_prog();
user_update(); user_update();
} }
} }

View File

@ -239,11 +239,11 @@ INLINE void sync_flag_wait(struct sync_flag *sf)
* Sleep frame * Sleep frame
* ========================== */ * ========================== */
INLINE void sleep_frame(sys_timestamp_t last_frame_time, f64 target_dt) INLINE void sleep_frame(struct sys_timestamp last_frame_time, f64 target_dt)
{ {
__prof; __prof;
if (last_frame_time != 0 && target_dt > 0) { if (last_frame_time.v != 0 && target_dt > 0) {
f64 last_frame_dt = sys_timestamp_seconds(sys_timestamp() - last_frame_time); f64 last_frame_dt = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), last_frame_time));
f64 sleep_time = target_dt - last_frame_dt; f64 sleep_time = target_dt - last_frame_dt;
if (sleep_time > 0) { if (sleep_time > 0) {
sys_sleep_precise(sleep_time); sys_sleep_precise(sleep_time);

View File

@ -4,9 +4,9 @@
#include "entity.h" #include "entity.h"
struct world { struct world {
u64 continuity_gen; /* Starts at 1 */ u64 continuity_gen; /* Starts at 1 */
u64 tick_id; /* Starts at 1 */ u64 tick_id; /* Starts at 1 */
u64 tick_ts; /* When was this tick simulated in program time */ struct sys_timestamp tick_ts; /* When was this tick simulated in program time */
/* World time */ /* World time */
f64 timescale; f64 timescale;