prediction progress
This commit is contained in:
parent
153290d57e
commit
6955da8fd1
@ -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 */
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
98
src/user.c
98
src/user.c
@ -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:
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user