prediction progress

This commit is contained in:
jacob 2025-02-26 13:24:48 -06:00
parent 153290d57e
commit 6955da8fd1
4 changed files with 83 additions and 62 deletions

View File

@ -60,7 +60,7 @@
#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0 #define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0
/* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */ /* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */
#define BITBUFF_DEBUG 1 #define BITBUFF_DEBUG RTC
#define BITBUFF_TEST RTC #define BITBUFF_TEST RTC
/* If enabled, things like network writes & memory allocations will be tracked in a global statistics struct */ /* If enabled, things like network writes & memory allocations will be tracked in a global statistics struct */

View File

@ -88,7 +88,7 @@ struct sim_client {
/* This is the highest confirmed ack of ours that we know this client has received (this /* This is the highest confirmed ack of ours that we know this client has received (this
* can be used to determine which client ticks will no longer be delta encoded from and * can be used to determine which client ticks will no longer be delta encoded from and
* can therefore be released) */ * therefore can be released) */
u64 double_ack; u64 double_ack;
/* This is the highest tick of their's that we have received */ /* This is the highest tick of their's that we have received */

View File

@ -340,7 +340,6 @@ void sim_step(struct sim_step_ctx *ctx)
struct sim_client *user_input_client = ctx->user_input_client; struct sim_client *user_input_client = ctx->user_input_client;
struct sim_client *publish_client = ctx->publish_client; struct sim_client *publish_client = ctx->publish_client;
struct sim_client *master_client = ctx->master_client; struct sim_client *master_client = ctx->master_client;
(UNUSED)master_client;
i64 sim_dt_ns = ctx->sim_dt_ns; i64 sim_dt_ns = ctx->sim_dt_ns;
@ -357,13 +356,14 @@ void sim_step(struct sim_step_ctx *ctx)
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID); struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
/* ========================== * /* ========================== *
* Sync remote ents * Sync ents from cmd producing clients
* ========================== */ * ========================== */
{ {
/* FIXME: Ensure only cmds are synced to master client */
for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) { for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) {
struct sim_client *client = &client_store->clients[client_index]; struct sim_client *client = &client_store->clients[client_index];
if (client->valid && client != world_client && client != publish_client) { if (client->valid && client != master_client && client != world_client && client != publish_client) {
struct sim_ent *client_ent = sim_ent_from_id(world, client->ent_id); struct sim_ent *client_ent = sim_ent_from_id(world, client->ent_id);
/* Create client ent if necessary */ /* Create client ent if necessary */
@ -1259,11 +1259,9 @@ void sim_step(struct sim_step_ctx *ctx)
* Sync to publish client * Sync to publish client
* ========================== */ * ========================== */
if (publish_client->valid) { if (publish_client->valid && world->tick > publish_client->last_tick) {
struct sim_snapshot *pub_world = sim_snapshot_from_tick(publish_client, world->tick); struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
if (!pub_world->valid) { struct sim_snapshot *pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick);
struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, world->tick - 1);
pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick);
/* Sync */ /* Sync */
sim_snapshot_sync_ents(pub_world, world, world_client->ent_id); sim_snapshot_sync_ents(pub_world, world, world_client->ent_id);
pub_world->sim_dt_ns = world->sim_dt_ns; pub_world->sim_dt_ns = world->sim_dt_ns;
@ -1272,7 +1270,6 @@ void sim_step(struct sim_step_ctx *ctx)
pub_world->phys_iteration = world->phys_iteration; pub_world->phys_iteration = world->phys_iteration;
pub_world->local_client_ent = world->local_client_ent; pub_world->local_client_ent = world->local_client_ent;
} }
}
/* ========================== * /* ========================== *
* End frame * End frame

View File

@ -97,7 +97,7 @@ GLOBAL struct {
/* Rolling window of local sim -> user publish time deltas */ /* Rolling window of local sim -> user publish time deltas */
i64 last_local_to_user_snapshot_published_at_ns; i64 last_local_to_user_snapshot_published_at_ns;
i64 local_to_user_snapshot_publish_dts_ns[50]; i64 local_to_user_snapshot_publish_dts_ns[10];
i64 local_to_user_snapshot_publish_dts_index; i64 local_to_user_snapshot_publish_dts_index;
i64 average_local_to_user_snapshot_publish_dt_ns; i64 average_local_to_user_snapshot_publish_dt_ns;
@ -1943,7 +1943,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
{ {
__profscope(local_sim_sleep); __profscope(local_sim_sleep);
sleep_frame(last_tick_ns, step_dt_ns * compute_timescale); sleep_frame(last_tick_ns, step_dt_ns / compute_timescale);
last_tick_ns = sys_time_ns(); last_tick_ns = sys_time_ns();
} }
@ -2004,7 +2004,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
if (base_ss->tick == base_tick) { if (base_ss->tick == base_tick) {
if (is_master) { if (is_master) {
/* Queue incoming slave client snapshot for decoding */ /* Queue incoming slave client snapshot for decoding */
b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0; //b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0;
b32 should_decode = tick > client->highest_received_tick;
if (should_decode) { if (should_decode) {
struct sim_ss_decode_node *node = arena_push_zero(scratch.arena, struct sim_ss_decode_node); struct sim_ss_decode_node *node = arena_push_zero(scratch.arena, struct sim_ss_decode_node);
node->client = client; node->client = client;
@ -2131,44 +2132,32 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Release unneeded user input snapshots */ /* Release unneeded user input snapshots */
sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->first_tick - 1); sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->first_tick - 1);
u64 sim_base_tick = local_client->last_tick;
u64 sim_to_tick = sim_base_tick + 1;
if (master_client->valid) { if (master_client->valid) {
last_tick_from_master = master_client->last_tick; last_tick_from_master = master_client->last_tick;
last_ticks_ahead_from_master = master_client->ack - last_tick_from_master; last_ticks_ahead_from_master = master_client->ack - last_tick_from_master;
if (last_ticks_ahead_from_master > 4) { if (math_abs_i64(last_ticks_ahead_from_master) > 50) {
/* We're too far from master time, snap to last sim time */
i64 rtt_ns = master_client->rtt_ns;
f64 rtt_tick_ratio = (f64)(rtt_ns + (step_dt_ns - 1)) / (f64)step_dt_ns;
i64 num_predict_ticks = math_round_to_int64(rtt_tick_ratio) + 2;
sim_base_tick = last_tick_from_master;
sim_to_tick = last_tick_from_master + num_predict_ticks;
sim_snapshot_release_ticks_in_range(local_client, sim_base_tick + 1, U64_MAX);
sim_snapshot_release_ticks_in_range(user_input_client, sim_base_tick + 1, U64_MAX);
compute_timescale = 1.1;
} else if (last_ticks_ahead_from_master > 4) {
/* Slow down time to bring sim time closer to master time */
compute_timescale = 0.9; compute_timescale = 0.9;
} else if (last_ticks_ahead_from_master < 2) { } else if (last_ticks_ahead_from_master < 2) {
/* Speed up time to give master more inputs to work with */
compute_timescale = 1.1; compute_timescale = 1.1;
} else { } else {
compute_timescale = 1; compute_timescale = 1;
} }
} }
#if 0
/* Determine step tick */
u64 desired_step_tick = 0;
if (is_master) {
desired_step_tick = local_client->last_tick + 1;
} else {
i64 rtt_ns = master_client->rtt_ns;
f64 rtt_tick_ratio = (f64)(rtt_ns + (step_dt_ns - 1)) / (f64)step_dt_ns;
i64 num_predict_ticks = math_round_to_int64(rtt_tick_ratio);
num_predict_ticks += 2; /* Jitter buffer */
desired_step_tick = master_client->last_tick + num_predict_ticks;
}
#else
/* Snap to master sim tick if too far */
i64 num_sim_ticks = 1;
if (!is_master && math_abs_i64(last_ticks_ahead_from_master) > 50) {
i64 rtt_ns = master_client->rtt_ns;
f64 rtt_tick_ratio = (f64)(rtt_ns + (step_dt_ns - 1)) / (f64)step_dt_ns;
i64 num_predict_ticks = math_round_to_int64(rtt_tick_ratio) + 2;
i64 desired_step_tick = master_client->last_tick + num_predict_ticks;
sim_snapshot_release_ticks_in_range(local_client, desired_step_tick, U64_MAX);
sim_snapshot_release_ticks_in_range(user_input_client, desired_step_tick, U64_MAX);
num_sim_ticks = desired_step_tick - num_sim_ticks;
}
#endif
@ -2177,7 +2166,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Create user input */ /* Create user input */
{ {
struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_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, local_client->last_tick + num_sim_ticks); struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, sim_to_tick);
struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID); struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID);
/* Find / create local control cmd ent */ /* Find / create local control cmd ent */
struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL); struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL);
@ -2214,6 +2203,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Step */ /* Step */
#if 1
{ {
struct sim_step_ctx ctx = ZI; struct sim_step_ctx ctx = ZI;
ctx.is_master = is_master; ctx.is_master = is_master;
@ -2225,9 +2215,40 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
ctx.publish_client = publish_client; ctx.publish_client = publish_client;
if (is_master) { if (is_master) {
u64 prev_tick = local_client->last_tick; ASSERT(sim_to_tick == sim_base_tick + 1);
struct sim_snapshot *prev_world = sim_snapshot_from_tick(local_client, prev_tick); struct sim_snapshot *prev_world = sim_snapshot_from_tick(local_client, sim_base_tick);
ctx.world = sim_snapshot_alloc(local_client, prev_world, prev_tick + 1); ctx.world = sim_snapshot_alloc(local_client, prev_world, sim_to_tick);
sim_step(&ctx);
} else {
struct sim_snapshot *master_ss = sim_snapshot_from_tick(master_client, sim_base_tick);
if (master_ss->valid) {
local_client->ent_id = master_ss->local_client_ent;
user_input_client->ent_id = master_ss->local_client_ent;
struct sim_snapshot *prev_world = sim_snapshot_alloc(local_client, master_ss, master_ss->tick);
while (prev_world->tick < sim_to_tick) {
ctx.world = sim_snapshot_alloc(local_client, prev_world, prev_world->tick + 1);
sim_step(&ctx);
prev_world = ctx.world;
}
}
}
}
#else
{
struct sim_step_ctx 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;
if (is_master) {
struct sim_snapshot *prev_world = sim_snapshot_from_tick(local_client, sim_base_tick);
ctx.world = sim_snapshot_alloc(local_client, prev_world, sim_base_tick + 1);
sim_step(&ctx); sim_step(&ctx);
} else { } else {
struct sim_snapshot *master_ss = sim_snapshot_from_tick(master_client, master_client->last_tick); struct sim_snapshot *master_ss = sim_snapshot_from_tick(master_client, master_client->last_tick);
@ -2246,6 +2267,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
} }
} }
#endif
@ -2314,17 +2336,19 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Copy local snapshot to user client */ /* Copy local snapshot to user client */
{ {
struct sim_snapshot *local_world = sim_snapshot_from_tick(local_client, local_client->last_tick); struct sim_snapshot *local_ss = sim_snapshot_from_tick(local_client, local_client->last_tick);
if (local_ss->valid) {
/* TODO: Double buffer */ /* TODO: Double buffer */
struct sys_lock lock = sys_mutex_lock_e(&G.local_to_user_client_mutex); struct sys_lock lock = sys_mutex_lock_e(&G.local_to_user_client_mutex);
struct sim_snapshot *copy_ss = sim_snapshot_alloc(G.local_to_user_client, local_world, local_world->tick); struct sim_snapshot *copy_ss = sim_snapshot_alloc(G.local_to_user_client, local_ss, local_ss->tick);
i64 publish_ns = sys_time_ns(); i64 publish_ns = sys_time_ns();
copy_ss->publish_dt_ns = publish_ns - last_publish_ns; copy_ss->publish_dt_ns = publish_ns - last_publish_ns;
copy_ss->publish_time_ns = publish_ns; copy_ss->publish_time_ns = publish_ns;
last_publish_ns = publish_ns; last_publish_ns = publish_ns;
sim_snapshot_release_ticks_in_range(G.local_to_user_client, 0, local_world->tick - 1); sim_snapshot_release_ticks_in_range(G.local_to_user_client, 0, local_ss->tick - 1);
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
}
skip_step: skip_step: