remove sys_timestamp, refactor into generalized i64 holding nanoseconds
This commit is contained in:
parent
a20e8eced5
commit
f0a25248c3
@ -231,6 +231,10 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
|||||||
#define GIGABYTE(n) (n*MEGABYTE(1024ULL))
|
#define GIGABYTE(n) (n*MEGABYTE(1024ULL))
|
||||||
#define TERABYTE(n) (n*GIGABYTE(1024ULL))
|
#define TERABYTE(n) (n*GIGABYTE(1024ULL))
|
||||||
|
|
||||||
|
/* Time */
|
||||||
|
#define NS_FROM_SECONDS(s) ((i64)((s) * 1000000000.0))
|
||||||
|
#define SECONDS_FROM_NS(ns) ((f64)(ns) / 1000000000.0)
|
||||||
|
|
||||||
/* typeof */
|
/* typeof */
|
||||||
#if COMPILER_MSVC
|
#if COMPILER_MSVC
|
||||||
/* Typeof not supported in MSVC */
|
/* Typeof not supported in MSVC */
|
||||||
|
|||||||
@ -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));
|
||||||
struct sys_timestamp start_ts = sys_timestamp_prog();
|
i64 start_ns = sys_time_ns();
|
||||||
|
|
||||||
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,7 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams)
|
|||||||
|
|
||||||
font_task_params_release(params);
|
font_task_params_release(params);
|
||||||
|
|
||||||
f64 elapsed = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), start_ts));
|
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||||
logf_info("Finished loading font \"%F\" (point size %F) in %F seconds", FMT_STR(path), FMT_FLOAT((f64)point_size), FMT_FLOAT(elapsed));
|
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);
|
||||||
|
|
||||||
|
|||||||
21
src/game.c
21
src/game.c
@ -504,12 +504,13 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
++G.tick.tick_id;
|
++G.tick.tick_id;
|
||||||
G.tick.tick_ts = sys_timestamp_prog();
|
G.tick.simtime_ns = sys_time_ns();
|
||||||
G.tick.dt = max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale);
|
|
||||||
G.tick.time += G.tick.dt;
|
|
||||||
|
|
||||||
f64 dt = G.tick.dt;
|
G.tick.dt_ns = NS_FROM_SECONDS(max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale));
|
||||||
f64 time = G.tick.time;
|
G.tick.time_ns += G.tick.dt_ns;
|
||||||
|
|
||||||
|
f64 dt = SECONDS_FROM_NS(G.tick.dt_ns);
|
||||||
|
f64 time = SECONDS_FROM_NS(G.tick.time_ns);
|
||||||
G.sprite_frame_scope = sprite_scope_begin();
|
G.sprite_frame_scope = sprite_scope_begin();
|
||||||
G.root = entity_from_handle(G.tick.entity_store, G.tick.entity_store->root);
|
G.root = entity_from_handle(G.tick.entity_store, G.tick.entity_store->root);
|
||||||
|
|
||||||
@ -1218,7 +1219,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
|
|
||||||
/* Lerp camera */
|
/* Lerp camera */
|
||||||
if (ent->camera_applied_lerp_continuity_gen_plus_one == ent->camera_lerp_continuity_gen + 1) {
|
if (ent->camera_applied_lerp_continuity_gen_plus_one == ent->camera_lerp_continuity_gen + 1) {
|
||||||
f32 t = 1 - math_pow(2.f, -20.f * (f32)G.tick.dt);
|
f32 t = 1 - math_pow(2.f, -20.f * (f32)dt);
|
||||||
xf = xform_lerp(xf, ent->camera_xform_target, t);
|
xf = xform_lerp(xf, ent->camera_xform_target, t);
|
||||||
} else {
|
} else {
|
||||||
/* Skip lerp */
|
/* Skip lerp */
|
||||||
@ -1347,13 +1348,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;
|
||||||
struct sys_timestamp last_frame_ts = ZI;
|
i64 last_frame_ns = 0;
|
||||||
f64 target_dt = GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0;
|
i64 target_dt_ns = NS_FROM_SECONDS(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_ns, target_dt_ns);
|
||||||
last_frame_ts = sys_timestamp_prog();
|
last_frame_ns = sys_time_ns();
|
||||||
{
|
{
|
||||||
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) {
|
||||||
|
|||||||
18
src/math.h
18
src/math.h
@ -590,16 +590,26 @@ INLINE f32 math_unwind_angle(f32 a)
|
|||||||
* Lerp
|
* Lerp
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE f32 math_lerp(f32 val0, f32 val1, f32 t)
|
INLINE f32 math_lerp_f32(f32 val0, f32 val1, f32 t)
|
||||||
{
|
{
|
||||||
return val0 + ((val1 - val0) * t);
|
return val0 + ((val1 - val0) * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f64 math_lerp64(f64 val0, f64 val1, f64 t)
|
INLINE f64 math_lerp_f64(f64 val0, f64 val1, f64 t)
|
||||||
{
|
{
|
||||||
return val0 + ((val1 - val0) * t);
|
return val0 + ((val1 - val0) * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE i32 math_lerp_i32(i32 val0, i32 val1, f32 t)
|
||||||
|
{
|
||||||
|
return val0 + math_round_to_int(((f32)(val1 - val0) * t));
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE i64 math_lerp_i64(i64 val0, i64 val1, f64 t)
|
||||||
|
{
|
||||||
|
return val0 + math_round_to_int64(((f64)(val1 - val0) * t));
|
||||||
|
}
|
||||||
|
|
||||||
INLINE f32 math_lerp_angle(f32 a, f32 b, f32 t) {
|
INLINE f32 math_lerp_angle(f32 a, f32 b, f32 t) {
|
||||||
f32 diff = math_unwind_angle(b - a);
|
f32 diff = math_unwind_angle(b - a);
|
||||||
return a + diff * t;
|
return a + diff * t;
|
||||||
@ -795,14 +805,14 @@ INLINE struct v2 v2_closest_point_ray(struct v2 ray_pos, struct v2 ray_dir_norm,
|
|||||||
/* Interpolate position vectors */
|
/* Interpolate position vectors */
|
||||||
INLINE struct v2 v2_lerp(struct v2 val0, struct v2 val1, f32 t)
|
INLINE struct v2 v2_lerp(struct v2 val0, struct v2 val1, f32 t)
|
||||||
{
|
{
|
||||||
return V2(math_lerp(val0.x, val1.x, t), math_lerp(val0.y, val1.y, t));
|
return V2(math_lerp_f32(val0.x, val1.x, t), math_lerp_f32(val0.y, val1.y, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interpolate direction vectors (spherical lerp) */
|
/* Interpolate direction vectors (spherical lerp) */
|
||||||
INLINE struct v2 v2_slerp(struct v2 val0, struct v2 val1, f32 t)
|
INLINE struct v2 v2_slerp(struct v2 val0, struct v2 val1, f32 t)
|
||||||
{
|
{
|
||||||
f32 rot = math_lerp_angle(v2_angle(val0), v2_angle(val1), t);
|
f32 rot = math_lerp_angle(v2_angle(val0), v2_angle(val1), t);
|
||||||
f32 len = math_lerp(v2_len(val0), v2_len(val1), t);
|
f32 len = math_lerp_f32(v2_len(val0), v2_len(val1), t);
|
||||||
return v2_mul(v2_from_angle(rot), len);
|
return v2_mul(v2_from_angle(rot), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
src/mixer.c
10
src/mixer.c
@ -376,8 +376,8 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
|
|
||||||
/* Lerp */
|
/* Lerp */
|
||||||
f32 t = in_frame_pos_exact - (f32)in_frame_pos_prev;
|
f32 t = in_frame_pos_exact - (f32)in_frame_pos_prev;
|
||||||
f32 sample1 = math_lerp(sample1_prev, sample1_next, t);
|
f32 sample1 = math_lerp_f32(sample1_prev, sample1_next, t);
|
||||||
f32 sample2 = math_lerp(sample2_prev, sample2_next, t);
|
f32 sample2 = math_lerp_f32(sample2_prev, sample2_next, t);
|
||||||
|
|
||||||
out_samples[(out_frame_pos * 2) + 0] += sample1;
|
out_samples[(out_frame_pos * 2) + 0] += sample1;
|
||||||
out_samples[(out_frame_pos * 2) + 1] += sample2;
|
out_samples[(out_frame_pos * 2) + 1] += sample2;
|
||||||
@ -395,7 +395,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
|
|
||||||
/* Lerp */
|
/* Lerp */
|
||||||
f32 t = (f32)in_frame_pos_exact - in_frame_pos_prev;
|
f32 t = (f32)in_frame_pos_exact - in_frame_pos_prev;
|
||||||
f32 sample = math_lerp(sample_prev, sample_next, t);
|
f32 sample = math_lerp_f32(sample_prev, sample_next, t);
|
||||||
|
|
||||||
out_samples[(out_frame_pos * 2) + 0] += sample;
|
out_samples[(out_frame_pos * 2) + 0] += sample;
|
||||||
out_samples[(out_frame_pos * 2) + 1] += sample;
|
out_samples[(out_frame_pos * 2) + 1] += sample;
|
||||||
@ -446,8 +446,8 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
/* Spatialize samples */
|
/* Spatialize samples */
|
||||||
for (u64 frame_pos = 0; frame_pos < frame_count; ++frame_pos) {
|
for (u64 frame_pos = 0; frame_pos < frame_count; ++frame_pos) {
|
||||||
f32 t = (f32)frame_pos / (f32)(frame_count - 1);
|
f32 t = (f32)frame_pos / (f32)(frame_count - 1);
|
||||||
f32 volume = math_lerp(volume_start, volume_end, t);
|
f32 volume = math_lerp_f32(volume_start, volume_end, t);
|
||||||
f32 pan = math_lerp(pan_start, pan_end, t);
|
f32 pan = math_lerp_f32(pan_start, pan_end, t);
|
||||||
|
|
||||||
u64 sample1_index = frame_pos * 2;
|
u64 sample1_index = frame_pos * 2;
|
||||||
u64 sample2_index = sample1_index + 1;
|
u64 sample2_index = sample1_index + 1;
|
||||||
|
|||||||
@ -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));
|
||||||
struct sys_timestamp start_ts = sys_timestamp_prog();
|
i64 start_ns = sys_time_ns();
|
||||||
|
|
||||||
b32 success = true;
|
b32 success = true;
|
||||||
struct string error_msg = STR("Unknown error");
|
struct string error_msg = STR("Unknown error");
|
||||||
@ -132,7 +132,7 @@ 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));
|
||||||
|
|
||||||
f64 elapsed = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), start_ts));
|
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||||
logf_info("Finished loading sound \"%F\" in %F seconds", FMT_STR(path), FMT_FLOAT(elapsed));
|
logf_info("Finished loading sound \"%F\" in %F seconds", FMT_STR(path), FMT_FLOAT(elapsed));
|
||||||
|
|
||||||
asset_cache_mark_ready(asset, sound);
|
asset_cache_mark_ready(asset, sound);
|
||||||
|
|||||||
@ -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));
|
||||||
struct sys_timestamp start_ts = sys_timestamp_prog();
|
i64 start_ns = sys_time_ns();
|
||||||
|
|
||||||
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,7 +383,7 @@ 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));
|
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||||
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(elapsed),
|
FMT_FLOAT(elapsed),
|
||||||
@ -648,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));
|
||||||
struct sys_timestamp start_ts = sys_timestamp_prog();
|
i64 start_ns = sys_time_ns();
|
||||||
|
|
||||||
//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);
|
||||||
@ -683,7 +683,7 @@ 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));
|
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||||
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(elapsed),
|
FMT_FLOAT(elapsed),
|
||||||
|
|||||||
34
src/sys.h
34
src/sys.h
@ -174,37 +174,7 @@ 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);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Timestamp
|
* Time
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
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 {
|
||||||
@ -220,6 +190,8 @@ struct sys_datetime {
|
|||||||
|
|
||||||
struct sys_datetime sys_local_time(void);
|
struct sys_datetime sys_local_time(void);
|
||||||
|
|
||||||
|
i64 sys_time_ns(void);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* File system
|
* File system
|
||||||
*
|
*
|
||||||
|
|||||||
@ -224,7 +224,8 @@ void sys_memory_set_committed_readwrite(void *address, u64 size)
|
|||||||
|
|
||||||
INTERNAL struct sys_datetime win32_time_to_sys_time(SYSTEMTIME st)
|
INTERNAL struct sys_datetime win32_time_to_sys_time(SYSTEMTIME st)
|
||||||
{
|
{
|
||||||
return (struct sys_datetime) {
|
return (struct sys_datetime)
|
||||||
|
{
|
||||||
.year = st.wYear,
|
.year = st.wYear,
|
||||||
.month = st.wMonth,
|
.month = st.wMonth,
|
||||||
.day_of_week = st.wDayOfWeek,
|
.day_of_week = st.wDayOfWeek,
|
||||||
@ -236,27 +237,6 @@ INTERNAL struct sys_datetime win32_time_to_sys_time(SYSTEMTIME st)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_timestamp sys_timestamp_prog(void)
|
|
||||||
{
|
|
||||||
struct sys_timestamp ts;
|
|
||||||
LARGE_INTEGER qpc;
|
|
||||||
QueryPerformanceCounter(&qpc);
|
|
||||||
ts.v = (qpc.QuadPart * G.timer_frequency_ns) - G.timer_start_ns;
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sys_timestamp sys_timestamp_from_seconds(f64 s)
|
|
||||||
{
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
SYSTEMTIME lt;
|
SYSTEMTIME lt;
|
||||||
@ -264,6 +244,14 @@ struct sys_datetime sys_local_time(void)
|
|||||||
return win32_time_to_sys_time(lt);
|
return win32_time_to_sys_time(lt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i64 sys_time_ns(void)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER qpc;
|
||||||
|
QueryPerformanceCounter(&qpc);
|
||||||
|
i64 res = (qpc.QuadPart * G.timer_frequency_ns) - G.timer_start_ns;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* File system
|
* File system
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|||||||
75
src/user.c
75
src/user.c
@ -71,8 +71,8 @@ GLOBAL struct {
|
|||||||
struct arena sys_events_arena;
|
struct arena sys_events_arena;
|
||||||
|
|
||||||
/* Per-frame */
|
/* Per-frame */
|
||||||
f64 time;
|
i64 time_ns;
|
||||||
f64 dt;
|
i64 dt_ns;
|
||||||
struct v2 screen_size;
|
struct v2 screen_size;
|
||||||
struct v2 screen_cursor;
|
struct v2 screen_cursor;
|
||||||
struct v2 ui_screen_offset;
|
struct v2 ui_screen_offset;
|
||||||
@ -257,7 +257,7 @@ struct interp_ticks {
|
|||||||
struct world *to_tick;
|
struct world *to_tick;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
|
INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -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_to_seconds(bt->world.tick_ts);
|
i64 bt_time_ns = bt->world.simtime_ns;
|
||||||
|
|
||||||
if (bt_time < blend_time && bt_time > sys_timestamp_to_seconds(from_tick->tick_ts)) {
|
if (bt_time_ns < blend_time_ns && bt_time_ns > from_tick->simtime_ns) {
|
||||||
from_tick = &bt->world;
|
from_tick = &bt->world;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_time > blend_time && bt_time < sys_timestamp_to_seconds(to_tick->tick_ts)) {
|
if (bt_time_ns > blend_time_ns && bt_time_ns < to_tick->simtime_ns) {
|
||||||
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_to_seconds(bt->world.tick_ts);
|
i64 bt_time_ns = bt->world.simtime_ns;
|
||||||
if (bt_time < sys_timestamp_to_seconds(from_tick->tick_ts)) {
|
if (bt_time_ns < from_tick->simtime_ns) {
|
||||||
*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,9 +490,9 @@ INTERNAL void user_update(void)
|
|||||||
* Begin frame
|
* Begin frame
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
f64 cur_time = sys_timestamp_to_seconds(sys_timestamp_prog());
|
i64 now_ns = sys_time_ns();
|
||||||
G.dt = max_f64(0.0, cur_time - G.time);
|
G.dt_ns = max_f64(0.0, now_ns - G.time_ns);
|
||||||
G.time += G.dt;
|
G.time_ns += G.dt_ns;
|
||||||
G.screen_size = sys_window_get_size(G.window);
|
G.screen_size = sys_window_get_size(G.window);
|
||||||
|
|
||||||
struct entity_store *store = G.world.entity_store;
|
struct entity_store *store = G.world.entity_store;
|
||||||
@ -508,20 +508,22 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
#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? */
|
||||||
f64 blend_time_offset = (1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO;
|
i64 blend_time_offset_ns = NS_FROM_SECONDS((1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO);
|
||||||
f64 blend_time = G.time > blend_time_offset ? G.time - blend_time_offset : 0;
|
i64 blend_time_ns = G.time_ns > blend_time_offset_ns ? G.time_ns - blend_time_offset_ns : 0;
|
||||||
|
|
||||||
/* Pull ticks */
|
/* Pull ticks */
|
||||||
struct interp_ticks interp_ticks = pull_ticks(blend_time);
|
struct interp_ticks interp_ticks = pull_ticks(blend_time_ns);
|
||||||
struct world *t0 = interp_ticks.from_tick;
|
struct world *t0 = interp_ticks.from_tick;
|
||||||
struct world *t1 = interp_ticks.to_tick;
|
struct world *t1 = interp_ticks.to_tick;
|
||||||
|
|
||||||
f32 tick_blend = 0;
|
f32 tick_blend = 0;
|
||||||
{
|
{
|
||||||
f64 t0_time = sys_timestamp_to_seconds(t0->tick_ts);
|
i64 t0_time_ns = t0->simtime_ns;
|
||||||
f64 t1_time = sys_timestamp_to_seconds(t1->tick_ts);
|
i64 t1_time_ns = t1->simtime_ns;
|
||||||
if (t1_time > t0_time) {
|
if (t1_time_ns > t0_time_ns) {
|
||||||
tick_blend = (f32)((blend_time - t0_time) / (t1_time - t0_time));
|
f64 t0_t1_elapsed = SECONDS_FROM_NS(t1_time_ns - t0_time_ns);
|
||||||
|
f64 t0_blend_elapsed = SECONDS_FROM_NS(blend_time_ns - t0_time_ns);
|
||||||
|
tick_blend = t0_blend_elapsed / t0_t1_elapsed;
|
||||||
}
|
}
|
||||||
tick_blend = clamp_f32(tick_blend, 0.0f, 1.0f);
|
tick_blend = clamp_f32(tick_blend, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
@ -529,8 +531,8 @@ INTERNAL void user_update(void)
|
|||||||
world_copy_replace(&G.world, t0);
|
world_copy_replace(&G.world, t0);
|
||||||
|
|
||||||
/* Blend world globals */
|
/* Blend world globals */
|
||||||
G.world.time = math_lerp64(t0->time, t1->time, (f64)tick_blend);
|
G.world.time_ns = math_lerp_i64(t0->time_ns, t1->time_ns, (f64)tick_blend);
|
||||||
G.world.dt = math_lerp64(t0->dt, t1->dt, (f64)tick_blend);
|
G.world.dt_ns = math_lerp_i64(t0->dt_ns, t1->dt_ns, (f64)tick_blend);
|
||||||
|
|
||||||
/* Blend entities */
|
/* Blend entities */
|
||||||
u64 num_entities = min_u64(t0->entity_store->reserved, t1->entity_store->reserved);
|
u64 num_entities = min_u64(t0->entity_store->reserved, t1->entity_store->reserved);
|
||||||
@ -554,8 +556,8 @@ INTERNAL void user_update(void)
|
|||||||
entity_set_xform(e, xform_lerp(e0_xf, e1_xf, tick_blend));
|
entity_set_xform(e, xform_lerp(e0_xf, e1_xf, tick_blend));
|
||||||
}
|
}
|
||||||
|
|
||||||
e->control_force = math_lerp(e0->control_force, e1->control_force, tick_blend);
|
e->control_force = math_lerp_f32(e0->control_force, e1->control_force, tick_blend);
|
||||||
e->control_torque = math_lerp(e0->control_torque, e1->control_torque, tick_blend);
|
e->control_torque = math_lerp_f32(e0->control_torque, e1->control_torque, tick_blend);
|
||||||
|
|
||||||
e->linear_velocity = v2_lerp(e0->linear_velocity, e1->linear_velocity, tick_blend);
|
e->linear_velocity = v2_lerp(e0->linear_velocity, e1->linear_velocity, tick_blend);
|
||||||
e->angular_velocity = math_lerp_angle(e0->angular_velocity, e1->angular_velocity, tick_blend);
|
e->angular_velocity = math_lerp_angle(e0->angular_velocity, e1->angular_velocity, tick_blend);
|
||||||
@ -564,12 +566,12 @@ INTERNAL void user_update(void)
|
|||||||
e->control.focus = v2_lerp(e0->control.focus, e1->control.focus, tick_blend);
|
e->control.focus = v2_lerp(e0->control.focus, e1->control.focus, tick_blend);
|
||||||
|
|
||||||
e->sprite_local_xform = xform_lerp(e0->sprite_local_xform, e1->sprite_local_xform, tick_blend);
|
e->sprite_local_xform = xform_lerp(e0->sprite_local_xform, e1->sprite_local_xform, tick_blend);
|
||||||
e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
|
e->animation_time_in_frame = math_lerp_f64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
|
||||||
e->animation_frame = (u32)math_round_to_int(math_lerp(e0->animation_frame, e1->animation_frame, tick_blend));
|
e->animation_frame = (u32)math_round_to_int(math_lerp_f32(e0->animation_frame, e1->animation_frame, tick_blend));
|
||||||
|
|
||||||
e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend);
|
e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend);
|
||||||
e->camera_xform_target = xform_lerp(e0->camera_xform_target, e1->camera_xform_target, tick_blend);
|
e->camera_xform_target = xform_lerp(e0->camera_xform_target, e1->camera_xform_target, tick_blend);
|
||||||
e->shake = math_lerp(e0->shake, e1->shake, tick_blend);
|
e->shake = math_lerp_f32(e0->shake, e1->shake, tick_blend);
|
||||||
|
|
||||||
e->tracer_gradient_start = v2_lerp(e0->tracer_gradient_start, e1->tracer_gradient_start, tick_blend);
|
e->tracer_gradient_start = v2_lerp(e0->tracer_gradient_start, e1->tracer_gradient_start, tick_blend);
|
||||||
e->tracer_gradient_end = v2_lerp(e0->tracer_gradient_end, e1->tracer_gradient_end, tick_blend);
|
e->tracer_gradient_end = v2_lerp(e0->tracer_gradient_end, e1->tracer_gradient_end, tick_blend);
|
||||||
@ -735,12 +737,12 @@ INTERNAL void user_update(void)
|
|||||||
if (!entity_is_valid_and_active(ent)) continue;
|
if (!entity_is_valid_and_active(ent)) continue;
|
||||||
|
|
||||||
/* How much time between camera shakes */
|
/* How much time between camera shakes */
|
||||||
const f32 frequency = 0.01f;
|
i64 frequency_ns = NS_FROM_SECONDS(0.01f);
|
||||||
f32 shake = ent->shake;
|
f32 shake = ent->shake;
|
||||||
if (shake > 0) {
|
if (shake > 0) {
|
||||||
u64 basis = hash_fnv64(HASH_FNV64_BASIS, BUFFER_FROM_STRUCT(&ent->handle));
|
u64 basis = hash_fnv64(HASH_FNV64_BASIS, BUFFER_FROM_STRUCT(&ent->handle));
|
||||||
u32 angle_seed0 = basis + (u64)(G.world.time / frequency);
|
u64 angle_seed0 = basis + (u64)(G.world.time_ns / frequency_ns);
|
||||||
u32 angle_seed1 = angle_seed0 + 1;
|
u64 angle_seed1 = angle_seed0 + 1;
|
||||||
f32 angle0 = rng_noise_f32(angle_seed0, 0, TAU);
|
f32 angle0 = rng_noise_f32(angle_seed0, 0, TAU);
|
||||||
f32 angle1 = rng_noise_f32(angle_seed1, 0, TAU);
|
f32 angle1 = rng_noise_f32(angle_seed1, 0, TAU);
|
||||||
|
|
||||||
@ -749,7 +751,7 @@ INTERNAL void user_update(void)
|
|||||||
struct v2 vec1 = v2_with_len(v2_from_angle(angle1), shake);
|
struct v2 vec1 = v2_with_len(v2_from_angle(angle1), shake);
|
||||||
|
|
||||||
/* TODO: Cubic interp? */
|
/* TODO: Cubic interp? */
|
||||||
f32 blend = math_fmod64(G.world.time, frequency) / frequency;
|
f32 blend = (f32)(G.world.time_ns % frequency_ns) / (f32)frequency_ns;
|
||||||
struct v2 vec = v2_lerp(vec0, vec1, blend);
|
struct v2 vec = v2_lerp(vec0, vec1, blend);
|
||||||
|
|
||||||
struct xform xf = entity_get_xform(ent);
|
struct xform xf = entity_get_xform(ent);
|
||||||
@ -1534,15 +1536,12 @@ INTERNAL void user_update(void)
|
|||||||
if (font) {
|
if (font) {
|
||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, STR("time: %F"), FMT_FLOAT((f64)G.time)));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, STR("time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.time_ns))));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, STR("world time: %F"), FMT_FLOAT((f64)G.world.time)));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, STR("world time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.world.time_ns))));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
//draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, STR("time - world time: %F"), FMT_FLOAT((f64)G.time - (f64)G.world.time)));
|
|
||||||
//pos.y += spacing;
|
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, STR("entities: %F/%F"), FMT_UINT(G.world.entity_store->allocated), FMT_UINT(G.world.entity_store->reserved)));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, STR("entities: %F/%F"), FMT_UINT(G.world.entity_store->allocated), FMT_UINT(G.world.entity_store->reserved)));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
@ -1717,13 +1716,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_thread_entry_point, arg)
|
|||||||
{
|
{
|
||||||
(UNUSED)arg;
|
(UNUSED)arg;
|
||||||
|
|
||||||
struct sys_timestamp last_frame_ts = ZI;
|
i64 last_frame_ns = 0;
|
||||||
f64 target_dt = USER_FRAME_LIMIT > (0) ? (1.0 / USER_FRAME_LIMIT) : 0;
|
i64 target_dt_ns = NS_FROM_SECONDS(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_ns, target_dt_ns);
|
||||||
last_frame_ts = sys_timestamp_prog();
|
last_frame_ns = sys_time_ns();
|
||||||
user_update();
|
user_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/util.h
13
src/util.h
@ -239,14 +239,15 @@ INLINE void sync_flag_wait(struct sync_flag *sf)
|
|||||||
* Sleep frame
|
* Sleep frame
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE void sleep_frame(struct sys_timestamp last_frame_time, f64 target_dt)
|
INLINE void sleep_frame(i64 last_frame_time_ns, i64 target_dt_ns)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
if (last_frame_time.v != 0 && target_dt > 0) {
|
if (last_frame_time_ns != 0 && target_dt_ns > 0) {
|
||||||
f64 last_frame_dt = sys_timestamp_to_seconds(sys_timestamp_sub(sys_timestamp_prog(), last_frame_time));
|
i64 now_ns = sys_time_ns();
|
||||||
f64 sleep_time = target_dt - last_frame_dt;
|
i64 last_frame_dt_ns = now_ns - last_frame_time_ns;
|
||||||
if (sleep_time > 0) {
|
i64 sleep_time_ns = target_dt_ns - last_frame_dt_ns;
|
||||||
sys_sleep_precise(sleep_time);
|
if (sleep_time_ns > 0) {
|
||||||
|
sys_sleep_precise(SECONDS_FROM_NS(sleep_time_ns));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
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 */
|
||||||
struct sys_timestamp tick_ts; /* When was this tick simulated in program time */
|
i64 simtime_ns; /* When was this tick simulated in program time */
|
||||||
|
|
||||||
/* World time */
|
/* World time */
|
||||||
f64 timescale;
|
f64 timescale;
|
||||||
f64 dt;
|
i64 dt_ns;
|
||||||
f64 time;
|
i64 time_ns;
|
||||||
|
|
||||||
struct entity_store *entity_store;
|
struct entity_store *entity_store;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user