diff --git a/src/base/base.cgh b/src/base/base.cgh index 3ff55d03..f496ec4e 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -60,6 +60,21 @@ #define IsGpu 0 #endif +//- Language +#if defined(__HLSL_VERSION) + #define IsLanguageHLSL 1 + #define IsLanguageCpp 0 + #define IsLanguageC 0 +#elif defined(__cplusplus) + #define IsLanguageHLSL 0 + #define IsLanguageCpp 1 + #define IsLanguageC 0 +#else + #define IsLanguageHLSL 0 + #define IsLanguageCpp 0 + #define IsLanguageC 1 +#endif + //- Platform #if IsGpu #define IsPlatformWindows 0 @@ -176,7 +191,7 @@ //~ Common utility macros //- Zero initialization -#if IsCpu +#if IsLanguageC #define Zi {0} #else #define Zi {} @@ -245,10 +260,10 @@ #define Stringize(x) Stringize1(x) //- Sizes -#define Kibi(n) ((n) * (1ULL << 10)) -#define Mebi(n) ((n) * (1ULL << 20)) -#define Gibi(n) ((n) * (1ULL << 30)) -#define Tebi(n) ((n) * (1ULL << 40)) +#define Kibi(n) ((n) * (1ull << 10)) +#define Mebi(n) ((n) * (1ull << 20)) +#define Gibi(n) ((n) * (1ull << 30)) +#define Tebi(n) ((n) * (1ull << 40)) //- Time #define NsFromSeconds(s) ((i64)((s) * 1000000000.0)) @@ -499,17 +514,17 @@ #define U8Max (0xFF) #define U16Max (0xFFFF) #define U32Max (0xFFFFFFFF) -#define U64Max (0xFFFFFFFFFFFFFFFFULL) +#define U64Max (0xFFFFFFFFFFFFFFFFull) #define I8Max (0x7F) #define I16Max (0x7FFF) #define I32Max (0x7FFFFFFF) -#define I64Max (0x7FFFFFFFFFFFFFFFLL) +#define I64Max (0x7FFFFFFFFFFFFFFFll) #define I8Min ((i8)-0x80) #define I16Min ((i16)0x8000) #define I32Min ((i32)0x80000000) -#define I64Min ((i64)0x8000000000000000LL) +#define I64Min ((i64)0x8000000000000000ll) //- Float infinity / nan #if IsCpu diff --git a/src/base/base_buddy.c b/src/base/base_buddy.c index 4b27128b..a57fbb13 100644 --- a/src/base/base_buddy.c +++ b/src/base/base_buddy.c @@ -156,7 +156,7 @@ void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block) BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size) { - if (size > 0x00FFFFFFFFFFFFFFULL) + if (size > 0x00FFFFFFFFFFFFFFull) { // TODO: Error Assert(0); diff --git a/src/pp/pp.c b/src/pp/pp.c index 500db2b4..e0fda190 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -12,6 +12,8 @@ Readonly P_Constraint P_NilConstraint = { }; Readonly P_Frame P_NilFrame = { + .next = &P_NilFrame, + .prev = &P_NilFrame, .first_ent = &P_NilEnt, .last_ent = &P_NilEnt, }; @@ -1948,6 +1950,11 @@ void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents) dst->created_at_ns = frame->time_ns; dst->created_at_tick = frame->tick; ++frame->ents_count; + + if (!P_tl.is_predicting) + { + dst->sim = 1; + } } } } @@ -2183,6 +2190,27 @@ void P_StepFrame(P_Frame *frame) P_Ent *local_player = P_EntFromKey(frame, P_tl.local_player); P_Ent *local_guy = P_EntFromKey(frame, local_player->guy); + ////////////////////////////// + //- Mark simulated ents + + if (is_predicting) + { + for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + P_EntKey key = ent->key; + b32 sim = 0; + if ( + P_MatchEntKey(key, local_player->key) || + P_MatchEntKey(key, local_guy->key) || + P_MatchEntKey(key, local_guy->weapon) + ) + { + sim = 1; + } + ent->sim = sim; + } + } + ////////////////////////////// //- Spawn guys @@ -2297,8 +2325,8 @@ void P_StepFrame(P_Frame *frame) weapon->is_weapon = 1; weapon->key = P_RandEntKey(); weapon->source = guy->key; - // weapon->1is_uzi = 1; - weapon->is_launcher = 1; + weapon->is_uzi = 1; + // weapon->is_launcher = 1; guy->weapon = weapon->key; } } @@ -2306,7 +2334,6 @@ void P_StepFrame(P_Frame *frame) P_SpawnEntsFromList(frame, queued_ents); } - ////////////////////////////// //- Update guy controls from player controls @@ -2377,7 +2404,7 @@ void P_StepFrame(P_Frame *frame) for (P_Ent *guy = P_FirstEnt(frame); !P_IsEntNil(guy); guy = P_NextEnt(guy)) { - if (guy->is_guy && (!is_predicting || guy == local_guy)) + if (guy->is_guy && guy->sim) { P_Control control = guy->control; @@ -2385,7 +2412,8 @@ void P_StepFrame(P_Frame *frame) { if (Vec2Len(guy->v) > 0.001) { - f32 damp_force = TweakFloat("Guy damp force", 50, 0, 100); + // f32 damp_force = TweakFloat("Guy damp force", 50, 0, 100); + f32 damp_force = TweakFloat("Guy damp force", 0, 0, 100); Vec2 damp = MulVec2(NegVec2(guy->v), damp_force * sim_dt); guy->v = AddVec2(guy->v, damp); } @@ -2575,12 +2603,12 @@ void P_StepFrame(P_Frame *frame) f32 inv_i1 = 0; // Treat statics / non-predicted ents as infinite-mass - if (!ent0->is_guy || (is_predicting && !P_MatchEntKey(ent0->key, local_guy->key))) + if (!ent0->is_guy || !ent0->sim) { inv_m0 = 0; inv_i0 = 0; } - if (!ent1->is_guy || (is_predicting && !P_MatchEntKey(ent1->key, local_guy->key))) + if (!ent1->is_guy || !ent1->sim) { inv_m1 = 0; inv_i1 = 0; @@ -2957,7 +2985,7 @@ void P_StepFrame(P_Frame *frame) for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) { - if (!ent->is_bullet && (!is_predicting || ent == local_guy)) + if (!ent->is_bullet && ent->sim) { Xform xf = ent->xf; xf.t = AddVec2(xf.t, MulVec2(ent->v, solver_dt)); @@ -2997,8 +3025,8 @@ void P_StepFrame(P_Frame *frame) for (P_Ent *firer = P_FirstEnt(frame); !P_IsEntNil(firer); firer = P_NextEnt(firer)) { P_Ent *weapon = P_EntFromKey(frame, firer->weapon); - // if (weapon->is_weapon && (firer->control.fire_held || firer->control.fire_presses)) - if (weapon->is_weapon && firer->control.fire_presses) + if (weapon->is_weapon && (firer->control.fire_held || firer->control.fire_presses)) + // if (weapon->is_weapon && firer->control.fire_presses) { f32 fire_rate = 50; f32 bullets_per_fire = 1; diff --git a/src/pp/pp.h b/src/pp/pp.h index f2d09dd8..265d302c 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -119,6 +119,7 @@ Struct(P_Ent) //- Build data f32 exists; + b32 sim; b32 is_guy; b32 is_bot; @@ -338,6 +339,7 @@ Struct(P_Frame) ////////////////////////////// //- Frame state + i64 src_tick; i64 tick; i64 time_ns; diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index bbda5ab4..65719e33 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -417,7 +417,7 @@ void S_TickForever(WaveLaneCtx *lane) //- Apply bot controls { - b32 bot_movement_enabled = TweakBool("Bot movement enabled", 0); + b32 bot_movement_enabled = TweakBool("Bot movement enabled", 1); for (P_Ent *bot = P_FirstEnt(world_frame); !P_IsEntNil(bot); bot = P_NextEnt(bot)) { if (bot->is_bot) diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 6e7c6453..f8c8cc7b 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -377,6 +377,7 @@ void V_TickForever(WaveLaneCtx *lane) // Which tick snapshots we have received and finished assembling from the server i64 ack = 0; i64 ack_mirror = 0; + i64 ack_received_at_ns = 0; f64 most_recent_rtt = 0; // i64 smoothed_rtt_ns = 0; @@ -1292,6 +1293,7 @@ void V_TickForever(WaveLaneCtx *lane) if (dst_frame->received_fragments_count >= dst_frame->fragments_count) { ack = dst_tick; + ack_received_at_ns = frame->time_ns; } } } @@ -1612,7 +1614,7 @@ void V_TickForever(WaveLaneCtx *lane) bottom_tick = MinI64(bottom_tick, first_predict_tick); bottom_tick = MinI64(bottom_tick, last_predict_tick); bottom_tick = MinI64(bottom_tick, ack); - P_ClearFrames(sim_world, I64Min, bottom_tick - 1); + // P_ClearFrames(sim_world, I64Min, bottom_tick - 1); } // P_ClearFrames(sim_world, I64Min, ack - SIM_TICKS_PER_SECOND); // P_ClearFrames(sim_world, I64Min, sim_world->last_frame->tick - 1); @@ -1633,12 +1635,14 @@ void V_TickForever(WaveLaneCtx *lane) } predict_world->seed = sim_world->seed; - P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 1, prev_frame->blend_from_tick - 1)); + // P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 1, prev_frame->blend_from_tick - 1)); + P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 2, prev_frame->blend_from_tick - 1)); predict_frame = P_PushFrame(predict_world, P_FrameFromTick(sim_world, first_predict_tick), first_predict_tick); for (i64 predict_tick = first_predict_tick + 1; predict_tick <= last_predict_tick; ++predict_tick) { predict_frame = P_PushFrame(predict_world, predict_world->last_frame, predict_tick); + predict_frame->src_tick = first_predict_tick; P_Ent *predict_player = P_EntFromKey(predict_frame, V.player_key); if (!P_IsEntNil(predict_player)) { @@ -1836,6 +1840,11 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Update local world + + + + + P_Frame *prev_local_frame = prev_frame->local_world->last_frame; P_Frame *local_frame = &P_NilFrame; { @@ -1849,6 +1858,7 @@ void V_TickForever(WaveLaneCtx *lane) P_ClearFrames(frame->local_world, I64Min, I64Max); i64 target_blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor; + // i64 target_blend_dt_ns = frame->dt_ns; i64 blend_dt_ns = frame->dt_ns; V.target_blend_time_ns += target_blend_dt_ns; @@ -1874,35 +1884,61 @@ void V_TickForever(WaveLaneCtx *lane) if (TweakBool("Interpolation enabled", 1)) { - P_Frame *left_frame = &P_NilFrame; - P_Frame *right_frame = &P_NilFrame; + P_Frame *left_predict_frame = &P_NilFrame; + P_Frame *right_predict_frame = &P_NilFrame; for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev) { if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns) { - right_frame = tmp; - left_frame = tmp->prev; + right_predict_frame = tmp; + left_predict_frame = tmp->prev; break; } } - if (P_IsFrameNil(left_frame) || P_IsFrameNil(right_frame)) + if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame)) { - right_frame = predict_world->last_frame; - left_frame = right_frame->prev; + right_predict_frame = predict_world->last_frame; + left_predict_frame = right_predict_frame->prev; } - frame->blend_from_tick = left_frame->tick; - frame->blend_to_tick = right_frame->tick; + frame->blend_from_tick = left_predict_frame->tick; + frame->blend_to_tick = right_predict_frame->tick; - local_frame = P_PushFrame(frame->local_world, left_frame, left_frame->tick); + local_frame = P_PushFrame(frame->local_world, left_predict_frame, left_predict_frame->tick); { - f64 blend_t = (f64)(V.blend_time_ns - left_frame->time_ns) / (f64)(right_frame->time_ns - left_frame->time_ns); + // P_Frame *left_sim_frame = predict_world->first_frame; + // P_Frame *right_sim_frame = left_sim_frame->next; + + // P_Frame *right_sim_frame = P_FrameFromTick(predict_world, first_predict_tick); + // P_Frame *left_sim_frame = right_sim_frame->prev; + + + // P_Frame *right_sim_frame = P_FrameFromTick(sim_world, ack - 1); + // P_Frame *left_sim_frame = right_sim_frame->prev; + + P_Frame *right_sim_frame = P_FrameFromTick(sim_world, right_predict_frame->src_tick); + P_Frame *left_sim_frame = right_sim_frame->prev; + + f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns); + + LogDebugF("blend_t: %F", FmtFloat(blend_t)); for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) { P_Ent *left = ent; - P_Ent *right = P_EntFromKey(right_frame, ent->key); + P_Ent *right = ent; + // if (ent->sim) + if (0) + { + left = ent; + right = P_EntFromKey(right_predict_frame, ent->key); + } + else + { + left = P_EntFromKey(left_sim_frame, ent->key); + right = P_EntFromKey(right_sim_frame, ent->key); + } ent->exists = LerpF32(left->exists, right->exists, blend_t); if (!P_IsEntNil(right)) @@ -1935,7 +1971,12 @@ void V_TickForever(WaveLaneCtx *lane) - // // TODO: Remove this + + + + + + // P_Frame *prev_local_frame = prev_frame->local_world->last_frame; // P_Frame *local_frame = &P_NilFrame; // { // if (frame->local_world->tiles_hash != predict_world->tiles_hash) @@ -1945,11 +1986,98 @@ void V_TickForever(WaveLaneCtx *lane) // frame->tiles_dirty = 1; // } // frame->local_world->seed = predict_world->seed; + // P_ClearFrames(frame->local_world, I64Min, I64Max); - // P_ClearFrames(frame->local_world, I64Min, frame->local_world->last_frame->tick - 1); - // local_frame = P_PushFrame(frame->local_world, predict_world->last_frame, predict_world->last_frame->tick); + // i64 target_blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor; + // i64 blend_dt_ns = frame->dt_ns; - // // LogDebugF("First frame: %F, Last frame: %F", FmtSint(frame->local_world->first_frame->tick), FmtSint(frame->local_world->last_frame->tick)); + // V.target_blend_time_ns += target_blend_dt_ns; + // V.blend_time_ns += blend_dt_ns; + + // // How many ticks back in time should the user thread blend between? + // // = * + // // E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps + // f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, 5); + // if (predict_to != prev_frame_predict_to) + // { + // i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio; + // V.target_blend_time_ns = predict_world->last_frame->time_ns - delay_ns; + // } + + // f64 blend_to_target_lerp_rate = 0.05; + // V.blend_time_ns = LerpI64(V.blend_time_ns, V.target_blend_time_ns, blend_to_target_lerp_rate); + // if (AbsI64(V.blend_time_ns - V.target_blend_time_ns) > (SIM_TICK_INTERVAL_NS * interp_ratio * 2)) + // { + // LogDebugF("Blend reset"); + // V.blend_time_ns = V.target_blend_time_ns; + // } + + // if (TweakBool("Interpolation enabled", 1)) + // { + // P_Frame *left_predict_frame = &P_NilFrame; + // P_Frame *right_predict_frame = &P_NilFrame; + // for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev) + // { + // if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns) + // { + // right_predict_frame = tmp; + // left_predict_frame = tmp->prev; + // break; + // } + // } + + // if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame)) + // { + // right_predict_frame = predict_world->last_frame; + // left_predict_frame = right_predict_frame->prev; + // } + + // frame->blend_from_tick = left_predict_frame->tick; + // frame->blend_to_tick = right_predict_frame->tick; + + // local_frame = P_PushFrame(frame->local_world, left_predict_frame, left_predict_frame->tick); + // { + // f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns); + + // // P_Frame *left_sim_frame = predict_world->first_frame; + // // P_Frame *right_sim_frame = left_sim_frame->next; + // P_Frame *right_sim_frame = P_FrameFromTick(sim_world, ack); + // P_Frame *left_sim_frame = right_sim_frame->prev; + + // for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + // { + // P_Ent *left = ent; + // P_Ent *right = ent; + // // if (ent->sim) + // if (0) + // { + // left = ent; + // right = P_EntFromKey(right_predict_frame, ent->key); + // } + // else + // { + // left = P_EntFromKey(left_sim_frame, ent->key); + // right = P_EntFromKey(right_sim_frame, ent->key); + // } + + // ent->exists = LerpF32(left->exists, right->exists, blend_t); + // if (!P_IsEntNil(right)) + // { + // ent->health = LerpF32(left->health, right->health, blend_t); + // ent->xf.t = LerpVec2(left->xf.t, right->xf.t, blend_t); + // ent->xf.r = SlerpVec2(left->xf.r, right->xf.r, blend_t); + // ent->walk_time_accum_ns = LerpI64(left->walk_time_accum_ns, right->walk_time_accum_ns, blend_t); + // ent->v = LerpVec2(left->v, right->v, blend_t); + // ent->w = LerpF32(left->w, right->w, blend_t); + // } + + // } + // } + // } + // else + // { + // local_frame = P_PushFrame(frame->local_world, predict_world->last_frame, predict_world->last_frame->tick); + // } // P_DebugDrawFrame(local_frame); @@ -1960,27 +2088,6 @@ void V_TickForever(WaveLaneCtx *lane) - // { - // i64 delay_ns = NsFromSeconds(100); - - // P_Frame *right_frame = &P_NilFrame; - // P_Frame *left_frame = &P_NilFrame; - - // for (P_Frame *tmp = - - - - - // P_Frame *right_frame = predict_world->last_frame; - // P_Frame *left_frame = predict_world->left_frame; - // } - - - - - - - ////////////////////////////// //- Query local player diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index 001e25d8..8e540f88 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -744,7 +744,7 @@ ImplComputeShader2D(V_CompositeCS) Vec4 backdrop_color = 0; { - if (!frame.is_editing) + if (!frame.is_editing || !is_in_world) { backdrop_color = backdrop.SampleLevel(bilinear_sampler, screen_uv, 0); }