diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 55f37e94..95455264 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -890,13 +890,15 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_CommandListHandle G_D12_Resource *resource = 0; b32 is_buffer = desc.kind == G_ResourceKind_Buffer; - b32 is_texture = desc.kind == G_ResourceKind_Texture1D || - desc.kind == G_ResourceKind_Texture2D || - desc.kind == G_ResourceKind_Texture3D; + b32 is_texture= + desc.kind == G_ResourceKind_Texture1D || + desc.kind == G_ResourceKind_Texture2D || + desc.kind == G_ResourceKind_Texture3D; b32 is_sampler = desc.kind == G_ResourceKind_Sampler; - G_ResourceFlag flags = is_buffer ? desc.buffer.flags : - is_texture ? desc.texture.flags : - desc.sampler.flags; + G_ResourceFlag flags = + is_buffer ? desc.buffer.flags : + is_texture ? desc.texture.flags : + desc.sampler.flags; ////////////////////////////// //- Initialize heap info diff --git a/src/pp/pp.c b/src/pp/pp.c index 98809ab1..ad52eecd 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -7,7 +7,8 @@ Readonly P_Ent P_NilEnt = { }; Readonly P_Frame P_NilFrame = { - 0 + .first_ent = &P_NilEnt, + .last_ent = &P_NilEnt, }; //////////////////////////////////////////////////////////// @@ -1056,7 +1057,7 @@ P_Ent *P_EntFromKey(P_Frame *frame, P_Key key) P_Ent *P_FirstEnt(P_Frame *frame) { P_Ent *result = &P_NilEnt; - if (frame->first_ent) + if (!P_IsEntNil(frame->first_ent)) { result = frame->first_ent; } @@ -1066,7 +1067,7 @@ P_Ent *P_FirstEnt(P_Frame *frame) P_Ent *P_NextEnt(P_Ent *e) { P_Ent *result = &P_NilEnt; - if (e && e->next) + if (!P_IsEntNil(e) && !P_IsEntNil(e->next)) { result = e->next; } @@ -1164,7 +1165,7 @@ P_World *P_AcquireWorld(void) world->first_frame = &P_NilFrame; world->last_frame = &P_NilFrame; - world->frame_bins_count = Kibi(1); + world->frame_bins_count = Kibi(16); world->frame_bins = PushStructs(world->arena, P_FrameBin, world->frame_bins_count); // TODO @@ -1189,83 +1190,80 @@ void P_UpdateWorldFromSnapshots(P_World *world, P_SnapshotList snapshots) world->seed = snapshot->world_seed; frame->time_ns = snapshot->time_ns; - if (frame->ents_count == 0) + for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) { - for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) + P_Delta *delta = &dn->delta; + // FIXME: Bounds check tile deltas + if (0) { - P_Delta *delta = &dn->delta; - // FIXME: Bounds check tile deltas - if (0) - { - } - //- Reset - else if (delta->kind == P_DeltaKind_Reset) - { - // FIXME: Free list entities - frame->ents_count = 0; - frame->first_ent = 0; - frame->last_ent = 0; - ZeroStructs(world->tiles, P_TilesCount); - ZeroStructs(frame->ent_bins, frame->ent_bins_count); - tiles_dirty = 1; - } - //- Raw ent - else if (delta->kind == P_DeltaKind_RawEnt) - { - P_Ent tmp_ent = delta->ent; - P_EntListNode tmp_ent_node = Zi; - tmp_ent_node.ent = tmp_ent; - P_EntList ent_list = Zi; - ent_list.first = &tmp_ent_node; - ent_list.last = &tmp_ent_node; - P_SpawnEntsFromList(frame, ent_list); - } - //- Raw tiles - else if (delta->kind == P_DeltaKind_RawTiles) - { - Rng2I32 range = delta->tile_range; - for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) - { - i32 src_tile_y = tile_y - range.p0.y; - for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) - { - i32 src_tile_x = tile_x - range.p0.x; - Vec2 src_tile_pos = VEC2(src_tile_x, src_tile_y); - i32 src_tile_idx = P_TileIdxFromTilePos(src_tile_pos); - u8 src_tile = delta->raw_tiles[src_tile_idx]; - - Vec2 tile_pos = VEC2(tile_x, tile_y); - i32 tile_idx = P_TileIdxFromTilePos(tile_pos); - world->tiles[tile_idx] = src_tile; - } - } - tiles_dirty = 1; - } - //- Tile range - else if (delta->kind == P_DeltaKind_Tile) - { - P_TileKind tile = delta->tile_kind; - Rng2I32 range = delta->tile_range; - for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) - { - for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) - { - Vec2 tile_pos = VEC2(tile_x, tile_y); - i32 tile_idx = P_TileIdxFromTilePos(tile_pos); - world->tiles[tile_idx] = (u8)tile; - } - } - tiles_dirty = 1; - } } - - - // FIXME: Real prune - // for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + //- Reset + // else if (delta->kind == P_DeltaKind_Reset) // { - // ent->exists = 0; + // // FIXME: Freelist entities + // frame->ents_count = 0; + // frame->first_ent = 0; + // frame->last_ent = 0; + // ZeroStructs(world->tiles, P_TilesCount); + // ZeroStructs(frame->ent_bins, frame->ent_bins_count); + // tiles_dirty = 1; + // } + //- Raw ent + else if (delta->kind == P_DeltaKind_RawEnt) + { + P_Ent tmp_ent = delta->ent; + P_EntListNode tmp_ent_node = Zi; + tmp_ent_node.ent = tmp_ent; + P_EntList ent_list = Zi; + ent_list.first = &tmp_ent_node; + ent_list.last = &tmp_ent_node; + P_SpawnEntsFromList(frame, ent_list); + } + //- Raw tiles + else if (delta->kind == P_DeltaKind_RawTiles) + { + Rng2I32 range = delta->tile_range; + for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) + { + i32 src_tile_y = tile_y - range.p0.y; + for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) + { + i32 src_tile_x = tile_x - range.p0.x; + Vec2 src_tile_pos = VEC2(src_tile_x, src_tile_y); + i32 src_tile_idx = P_TileIdxFromTilePos(src_tile_pos); + u8 src_tile = delta->raw_tiles[src_tile_idx]; + + Vec2 tile_pos = VEC2(tile_x, tile_y); + i32 tile_idx = P_TileIdxFromTilePos(tile_pos); + world->tiles[tile_idx] = src_tile; + } + } + tiles_dirty = 1; + } + //- Tile range + // else if (delta->kind == P_DeltaKind_Tile) + // { + // P_TileKind tile = delta->tile_kind; + // Rng2I32 range = delta->tiles_range; + // for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) + // { + // for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) + // { + // Vec2 tile_pos = VEC2(tile_x, tile_y); + // i32 tile_idx = P_TileIdxFromTilePos(tile_pos); + // world->tiles[tile_idx] = (u8)tile; + // } + // } + // tiles_dirty = 1; // } } + + + // FIXME: Real prune + // for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + // { + // ent->exists = 0; + // } } } @@ -1295,9 +1293,16 @@ void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents) } if (!dst) { - // FIXME: Use free list - dst = PushStructNoZero(world->arena, P_Ent); - DllQueuePush(frame->first_ent, frame->last_ent, dst); + dst = world->first_free_ent; + if (dst) + { + SllStackPop(world->first_free_ent); + } + else + { + dst = PushStructNoZero(world->frames_arena, P_Ent); + } + DllQueuePushNPZ(&P_NilEnt, frame->first_ent, frame->last_ent, dst, next, prev); DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin); } P_Ent *old_next = dst->next; @@ -1345,14 +1350,18 @@ void P_ClearFrames(P_World *world, i64 tick_min, i64 tick_max) P_Frame *next_frame = frame->next; if (frame->tick >= tick_min && frame->tick <= tick_max) { - // FIXME: Freelist ents - - // FIXME: Freelist frame + if (!P_IsEntNil(frame->first_ent)) + { + frame->last_ent->next = world->first_free_ent; + world->first_free_ent = frame->first_ent; + } u64 hash = MixU64(frame->tick); P_FrameBin *bin = &world->frame_bins[hash % world->frame_bins_count]; DllQueueRemoveNPZ(&P_NilFrame, world->first_frame, world->last_frame, frame, next, prev); DllQueueRemoveNPZ(0, bin->first, bin->last, frame, next_in_bin, prev_in_bin); + + SllStackPush(world->first_free_frame, frame); } else { @@ -1367,16 +1376,34 @@ P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick) Assert(!(src_frame->world == world && tick <= src_frame->tick)); // Can't read from tick that is being overwritten by new tick P_ClearFrames(world, tick, I64Max); - P_Frame *frame = PushStruct(world->frames_arena, P_Frame); + P_Frame *frame = world->first_free_frame; + if (frame) { - // FIXME: Pull from freelist + SllStackPop(world->first_free_frame); + i64 old_ent_bins_count = frame->ent_bins_count; + P_EntBin *old_ent_bins = frame->ent_bins; + ZeroStruct(frame); + frame->ent_bins_count = old_ent_bins_count; + frame->ent_bins = old_ent_bins; + ZeroStructs(frame->ent_bins, frame->ent_bins_count); + } + else + { + frame = PushStruct(world->frames_arena, P_Frame); + } + { frame->world = world; frame->tick = tick; frame->time_ns = src_frame->time_ns; - frame->ent_bins_count = Kibi(16); - frame->ent_bins = PushStructs(world->frames_arena, P_EntBin, frame->ent_bins_count); + frame->first_ent = &P_NilEnt; + frame->last_ent = &P_NilEnt; + if (frame->ent_bins_count == 0) + { + frame->ent_bins_count = Kibi(16); + frame->ent_bins = PushStructs(world->frames_arena, P_EntBin, frame->ent_bins_count); + } u64 hash = MixU64(tick); P_FrameBin *bin = &world->frame_bins[hash % world->frame_bins_count]; @@ -1388,10 +1415,18 @@ P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick) for (P_Ent *src = P_FirstEnt(src_frame); !P_IsEntNil(src); src = P_NextEnt(src)) { // FIXME: Pull from freelist - P_Ent *dst = PushStruct(world->frames_arena, P_Ent); + P_Ent *dst = world->first_free_ent; + if (dst) + { + SllStackPop(world->first_free_ent); + } + else + { + dst = PushStructNoZero(world->frames_arena, P_Ent); + } *dst = *src; P_EntBin *bin = &frame->ent_bins[src->key.v % frame->ent_bins_count]; - DllQueuePush(frame->first_ent, frame->last_ent, dst); + DllQueuePushNPZ(&P_NilEnt, frame->first_ent, frame->last_ent, dst, next, prev); DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin); ++frame->ents_count; } diff --git a/src/pp/pp.h b/src/pp/pp.h index 11446cd7..1d540a1b 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -151,13 +151,14 @@ Struct(P_World) Arena *statics_arena; u64 seed; - // P_Ent *first_free_ent; + + P_Ent *first_free_ent; P_Frame *first_frame; P_Frame *last_frame; i64 frame_bins_count; P_FrameBin *frame_bins; - // P_Frame *first_free_frame; + P_Frame *first_free_frame; u8 *tiles; }; @@ -167,18 +168,14 @@ Enum(P_DeltaKind) P_DeltaKind_Reset, P_DeltaKind_RawEnt, P_DeltaKind_RawTiles, - P_DeltaKind_Tile, }; Struct(P_Delta) { P_DeltaKind kind; - P_Ent ent; - - u8 *raw_tiles; - P_TileKind tile_kind; Rng2I32 tile_range; + u8 *raw_tiles; }; Struct(P_DeltaNode) @@ -342,8 +339,10 @@ Struct(P_DebugDrawNode) Enum(P_CmdKind) { P_CmdKind_Nop, - P_CmdKind_Save, - P_CmdKind_Delta, + P_CmdKind_SaveWorld, + P_CmdKind_ResetWorld, + P_CmdKind_TileEdit, + P_CmdKind_EntEdit, P_CmdKind_Control, }; @@ -352,8 +351,12 @@ Struct(P_Cmd) i64 tick; P_CmdKind kind; - // Delta - P_Delta delta; + // Tile edit + P_TileKind tile_kind; + Rng2I32 tile_range; + + // Ent edit + P_Ent ent; // Control P_Key target; @@ -366,6 +369,7 @@ Struct(P_Cmd) Struct(P_CmdNode) { P_CmdNode *next; + P_CmdNode *prev; P_Cmd cmd; }; diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 7bb6cbda..5e8073ea 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -29,6 +29,27 @@ void S_TickForever(WaveLaneCtx *lane) // TODO: Real per-client deltas b32 has_sent_initial_tick = 0; + + + + + + // FIXME: Header + + Rng user_cmd_tick_range = RNG(0, SIM_TICKS_PER_SECOND * 0.5); + P_CmdList queued_user_cmds = Zi; + P_CmdNode *first_free_user_cmd_node = 0; + + + + + + + + + + + ////////////////////////////// //- Sim loop @@ -91,7 +112,8 @@ void S_TickForever(WaveLaneCtx *lane) P_Frame *prev_world_frame = world->last_frame; P_Frame *world_frame = P_PushFrame(world, prev_world_frame, prev_world_frame->tick + 1); - // FIXME: Copy frame + // TDOO: Remove this + P_ClearFrames(world, I64Min, prev_world_frame->tick - 1); i64 frame_begin_ns = TimeNs(); @@ -113,6 +135,66 @@ void S_TickForever(WaveLaneCtx *lane) } UnlockTicketMutex(&P.sim_input_back_tm); + P_CmdList user_cmds = Zi; + { + i64 user_cmds_min_tick = world_frame->tick - user_cmd_tick_range.min; + i64 user_cmds_max_tick = world_frame->tick + user_cmd_tick_range.max; + // Prune user cmds + { + for (P_CmdNode *cmd_node = queued_user_cmds.first; cmd_node;) + { + P_CmdNode *next = cmd_node->next; + b32 prune = 0; + if (cmd_node->cmd.tick < user_cmds_min_tick || cmd_node->cmd.tick > user_cmds_max_tick) + { + prune = 1; + } + if (prune) + { + DllQueueRemove(queued_user_cmds.first, queued_user_cmds.last, cmd_node); + SllStackPush(first_free_user_cmd_node, cmd_node); + --queued_user_cmds.count; + } + cmd_node = next; + } + } + // Push user cmds to queue + { + for (P_CmdNode *src_cmd_node = input->cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) + { + if (src_cmd_node->cmd.tick >= user_cmds_min_tick && src_cmd_node->cmd.tick <= user_cmds_max_tick) + { + P_CmdNode *dst_cmd_node = first_free_user_cmd_node; + if (dst_cmd_node) + { + SllStackPop(first_free_user_cmd_node); + ZeroStruct(dst_cmd_node); + } + else + { + dst_cmd_node = PushStruct(perm, P_CmdNode); + } + dst_cmd_node->cmd = src_cmd_node->cmd; + DllQueuePush(queued_user_cmds.first, queued_user_cmds.last, dst_cmd_node); + ++queued_user_cmds.count; + } + } + } + // Copy queued commands for current tick + { + for (P_CmdNode *src_cmd_node = queued_user_cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) + { + if (src_cmd_node->cmd.tick == world_frame->tick) + { + P_CmdNode *dst_cmd_node = PushStruct(frame_arena, P_CmdNode); + dst_cmd_node->cmd = src_cmd_node->cmd; + DllQueuePush(user_cmds.first, user_cmds.last, dst_cmd_node); + ++user_cmds.count; + } + } + } + } + ////////////////////////////// //- Update double-buffered entity data @@ -126,21 +208,21 @@ void S_TickForever(WaveLaneCtx *lane) // FIXME: Only accept save command from local user - b32 should_save = 0; - for (P_CmdNode *cmd_node = input->cmds.first; cmd_node; cmd_node = cmd_node->next) - { - P_Cmd *cmd = &cmd_node->cmd; - if (cmd->kind == P_CmdKind_Save) - { - should_save = 1; - break; - } - } - if (should_save) - { - String path = Lit("HAH"); - LogInfoF("Saving world to %F", FmtString(path)); - } + // b32 should_save = 0; + // for (P_CmdNode *cmd_node = user_cmds.first; cmd_node; cmd_node = cmd_node->next) + // { + // P_Cmd *cmd = &cmd_node->cmd; + // if (cmd->kind == P_CmdKind_SaveWorld) + // { + // should_save = 1; + // break; + // } + // } + // if (should_save) + // { + // String path = Lit("..."); + // LogInfoF("Saving world to %F", FmtString(path)); + // } ////////////////////////////// //- Process user world delta commands @@ -149,53 +231,44 @@ void S_TickForever(WaveLaneCtx *lane) // FIXME: Only apply relevant cmds based on tick - i64 applied_user_deltas_count = 0; - P_Delta **applied_user_deltas = PushStructsNoZero(frame_arena, P_Delta *, input->cmds.count); - for (P_CmdNode *cmd_node = input->cmds.first; cmd_node; cmd_node = cmd_node->next) + { - P_Cmd *cmd = &cmd_node->cmd; - if (cmd->kind == P_CmdKind_Delta) + b32 tiles_dirty = 0; + for (P_CmdNode *cmd_node = user_cmds.first; cmd_node; cmd_node = cmd_node->next) { - P_Delta *delta = &cmd->delta; + P_Cmd *cmd = &cmd_node->cmd; b32 allow = 0; - b32 forward = 0; - if (delta->kind == P_DeltaKind_Reset) + if (cmd->kind == P_CmdKind_ResetWorld) { - allow = 1; - forward = 1; + // TODO } - if (delta->kind == P_DeltaKind_RawEnt) + if (cmd->kind == P_CmdKind_EntEdit) { - allow = 1; + P_EntList ents = Zi; + P_Ent *dst = P_PushTempEnt(frame_arena, &ents); + *dst = cmd->ent; + P_SpawnEntsFromList(world_frame, ents); } - if (delta->kind == P_DeltaKind_Tile) + if (cmd->kind == P_CmdKind_TileEdit) { - allow = 1; - forward = 1; - } - if (forward) - { - applied_user_deltas[applied_user_deltas_count] = delta; - applied_user_deltas_count += 1; - } - if (allow) - { - P_DeltaNode tmp_delta_node = Zi; - tmp_delta_node.delta = *delta; - - P_SnapshotNode tmp_snapshot_node = Zi; - tmp_snapshot_node.snapshot.deltas_count = 1; - tmp_snapshot_node.snapshot.first_delta_node = &tmp_delta_node; - tmp_snapshot_node.snapshot.last_delta_node = &tmp_delta_node; - - P_SnapshotList tmp_snapshot_list = Zi; - tmp_snapshot_list.count = 1; - tmp_snapshot_list.first = &tmp_snapshot_node; - tmp_snapshot_list.last = &tmp_snapshot_node; - - P_UpdateWorldFromSnapshots(world, tmp_snapshot_list); + P_TileKind tile = cmd->tile_kind; + Rng2I32 range = cmd->tile_range; + for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) + { + for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) + { + Vec2 tile_pos = VEC2(tile_x, tile_y); + i32 tile_idx = P_TileIdxFromTilePos(tile_pos); + world->tiles[tile_idx] = (u8)tile; + } + } } } + + // TODO: Hash tiles here + // if (tiles_dirty) + // { + // } } ////////////////////////////// @@ -208,7 +281,7 @@ void S_TickForever(WaveLaneCtx *lane) ent->fire_presses = 0; } - for (P_CmdNode *cmd_node = input->cmds.first; cmd_node; cmd_node = cmd_node->next) + for (P_CmdNode *cmd_node = user_cmds.first; cmd_node; cmd_node = cmd_node->next) { P_Cmd cmd = cmd_node->cmd; if (cmd.kind == P_CmdKind_Control) @@ -1237,20 +1310,6 @@ void S_TickForever(WaveLaneCtx *lane) snapshot->tick = world_frame->tick; snapshot->time_ns = world_frame->time_ns; - // Forward user edit deltas - for (i64 applied_user_delta_idx = 0; applied_user_delta_idx < applied_user_deltas_count; ++applied_user_delta_idx) - { - P_Delta *delta = 0; - { - P_DeltaNode *dn = PushStruct(output->arena, P_DeltaNode); - snapshot->deltas_count += 1; - SllQueuePush(snapshot->first_delta_node, snapshot->last_delta_node, dn); - delta = &dn->delta; - } - P_Delta *src = applied_user_deltas[applied_user_delta_idx]; - *delta = *src; - } - // Push full tile delta if (!has_sent_initial_tick) { @@ -1320,13 +1379,13 @@ void S_TickForever(WaveLaneCtx *lane) for (i64 prune_idx = 0; prune_idx < ents_to_prune_count; ++prune_idx) { - // FIXME: Add to freelist // FIXME: Ensure sure prunes are received by user P_Ent *ent = ents_to_prune[prune_idx]; P_EntBin *bin = &world_frame->ent_bins[ent->key.v % world_frame->ent_bins_count]; DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin); - DllQueueRemove(world_frame->first_ent, world_frame->last_ent, ent); + DllQueueRemoveNPZ(&P_NilEnt, world_frame->first_ent, world_frame->last_ent, ent, next, prev); world_frame->ents_count -= 1; + SllStackPush(world->first_free_ent, ent); } } diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 313ac0fe..2d93e043 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -37,17 +37,25 @@ V_Cmd *V_PushVisCmd(String name) cmd->name = name; } ++frame->cmds_count; - SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, cmd_node); + DllQueuePush(frame->first_cmd_node, frame->last_cmd_node, cmd_node); return cmd; } P_Cmd *V_PushSimCmd(P_CmdKind kind) { - // FIXME: Free list Arena *perm = PermArena(); - P_CmdNode *n = PushStruct(perm, P_CmdNode); + P_CmdNode *n = V.first_free_sim_cmd_node; + if (n) + { + SllStackPop(V.first_free_sim_cmd_node); + ZeroStruct(n); + } + else + { + n = PushStruct(perm, P_CmdNode); + } n->cmd.kind = kind; - SllQueuePush(V.sim_cmds.first, V.sim_cmds.last, n); + DllQueuePush(V.sim_cmds.first, V.sim_cmds.last, n); ++V.sim_cmds.count; return &n->cmd; } @@ -1002,7 +1010,7 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Place tiles - // TODO: Push vis cmd + // TODO: Push vis cmd instead if (frame->is_editing && prev_frame->is_selecting && !frame->is_selecting) { @@ -1013,10 +1021,9 @@ void V_TickForever(WaveLaneCtx *lane) tile_range.p0 = Vec2I32FromVec(FloorVec2(MulXformV2(frame->xf.world_to_tile, prev_frame->world_selection.p0))); tile_range.p1 = Vec2I32FromVec(CeilVec2(MulXformV2(frame->xf.world_to_tile, prev_frame->world_selection.p1))); - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta); - cmd->delta.kind = P_DeltaKind_Tile; - cmd->delta.tile_kind = prev_frame->equipped_tile; - cmd->delta.tile_range = tile_range; + P_Cmd *cmd = V_PushSimCmd(P_CmdKind_TileEdit); + cmd->tile_kind = prev_frame->equipped_tile; + cmd->tile_range = tile_range; } } @@ -2234,12 +2241,20 @@ void V_TickForever(WaveLaneCtx *lane) { UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); { - UI_BuildLabelF("World seed: 0x%F", FmtHex(blend_world->seed)); - UI_BuildLabelF("Entities count: %F", FmtSint(blend_world->last_frame->ents_count)); + UI_BuildLabelF("Sim world seed: 0x%F", FmtHex(sim_world->seed)); + UI_BuildLabelF("Sim world tick: %F", FmtSint(sim_world->last_frame->tick)); + UI_BuildLabelF("Sim world entities: %F", FmtSint(sim_world->last_frame->ents_count)); + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); + UI_BuildLabelF("Predict world seed: 0x%F", FmtHex(predict_world->seed)); + UI_BuildLabelF("Predict world tick: %F", FmtSint(predict_world->last_frame->tick)); + UI_BuildLabelF("Predict world entities: %F", FmtSint(predict_world->last_frame->ents_count)); + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); + UI_BuildLabelF("Blend world seed: 0x%F", FmtHex(blend_world->seed)); + UI_BuildLabelF("Blend world tick: %F", FmtSint(blend_world->last_frame->tick)); + UI_BuildLabelF("Blend world entities: %F", FmtSint(blend_world->last_frame->ents_count)); } UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); { - UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); Vec2 tile_pos = MulXformV2(frame->xf.world_to_tile, frame->world_cursor); Vec2 cell_pos = MulXformV2(frame->xf.world_to_cell, frame->world_cursor); i32 tile_idx = P_TileIdxFromTilePos(tile_pos); @@ -2521,8 +2536,7 @@ void V_TickForever(WaveLaneCtx *lane) Vec2 player_pos = VEC2(5, 0); if (kind == V_CmdKind_reset_world) { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta); - cmd->delta.kind = P_DeltaKind_Reset; + P_Cmd *cmd = V_PushSimCmd(P_CmdKind_ResetWorld); } else { @@ -2530,9 +2544,8 @@ void V_TickForever(WaveLaneCtx *lane) } // Spawn player { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta); - cmd->delta.kind = P_DeltaKind_RawEnt; - P_Ent *ent = &cmd->delta.ent; + P_Cmd *cmd = V_PushSimCmd(P_CmdKind_EntEdit); + P_Ent *ent = &cmd->ent; *ent = P_NilEnt; ent->key = V.player_key; ent->xf = XformFromPos(player_pos); @@ -2544,9 +2557,8 @@ void V_TickForever(WaveLaneCtx *lane) case V_CmdKind_spawn_dummy: { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta); - cmd->delta.kind = P_DeltaKind_RawEnt; - P_Ent *ent = &cmd->delta.ent; + P_Cmd *cmd = V_PushSimCmd(P_CmdKind_EntEdit); + P_Ent *ent = &cmd->ent; *ent = P_NilEnt; ent->key = P_RandKey(); ent->xf = XformFromPos(frame->world_cursor); @@ -2559,9 +2571,8 @@ void V_TickForever(WaveLaneCtx *lane) { if (!P_IsEntNil(hovered_ent)) { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta); - cmd->delta.kind = P_DeltaKind_RawEnt; - P_Ent *ent = &cmd->delta.ent; + P_Cmd *cmd = V_PushSimCmd(P_CmdKind_EntEdit); + P_Ent *ent = &cmd->ent; ent->key = hovered_ent->key; ent->exists = 0; } @@ -2571,7 +2582,7 @@ void V_TickForever(WaveLaneCtx *lane) { if (frame->is_editing) { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Save); + P_Cmd *cmd = V_PushSimCmd(P_CmdKind_SaveWorld); } } break; @@ -2617,16 +2628,6 @@ void V_TickForever(WaveLaneCtx *lane) } } - // Push control cmd - { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Control); - cmd->target = V.player_key; - cmd->move = frame->move; - cmd->look = frame->look; - cmd->fire_held = frame->fire_held; - cmd->fire_presses = frame->fire_presses; - } - @@ -2646,9 +2647,6 @@ void V_TickForever(WaveLaneCtx *lane) } UnlockTicketMutex(&P.sim_output_back_tm); - - - ////////////////////////////// //- Apply sim snapshots @@ -2699,6 +2697,10 @@ void V_TickForever(WaveLaneCtx *lane) P_UpdateWorldFromSnapshots(sim_world, sim_snapshots); } + // TODO: Remove this + P_ClearFrames(sim_world, I64Min, sim_world->last_frame->tick - 1); + P_Frame *sim_frame = sim_world->last_frame; + @@ -2708,21 +2710,46 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Submit sim commands - i64 predict_to = sim_world->last_frame->tick + 10; - - LockTicketMutex(&P.sim_input_back_tm); + frame->predict_to = sim_world->last_frame->tick + 1; + if (frame->predict_to != prev_frame->predict_to) { - P_InputState *v2s = &P.sim_input_states[P.sim_input_back_idx]; - for (P_CmdNode *src = V.sim_cmds.first; src; src = src->next) + // Push control cmd { - P_CmdNode *cmd_node = PushStruct(v2s->arena, P_CmdNode); - cmd_node->cmd = src->cmd; - cmd_node->cmd.tick = predict_to; - SllQueuePush(v2s->cmds.first, v2s->cmds.last, cmd_node); - ++v2s->cmds.count; + P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Control); + cmd->target = V.player_key; + cmd->move = frame->move; + cmd->look = frame->look; + cmd->fire_held = frame->fire_held; + cmd->fire_presses = frame->fire_presses; } + + LockTicketMutex(&P.sim_input_back_tm); + { + P_InputState *v2s = &P.sim_input_states[P.sim_input_back_idx]; + for (P_CmdNode *src_cmd_node = V.sim_cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) + { + if (src_cmd_node->cmd.kind == P_CmdKind_EntEdit) + { + DEBUGBREAKABLE; + } + + P_CmdNode *dst_cmd_node = PushStruct(v2s->arena, P_CmdNode); + dst_cmd_node->cmd = src_cmd_node->cmd; + dst_cmd_node->cmd.tick = frame->predict_to; + DllQueuePush(v2s->cmds.first, v2s->cmds.last, dst_cmd_node); + ++v2s->cmds.count; + } + } + UnlockTicketMutex(&P.sim_input_back_tm); + if (V.sim_cmds.first) + { + V.sim_cmds.last->next = V.first_free_sim_cmd_node; + V.first_free_sim_cmd_node = V.sim_cmds.first; + } + V.sim_cmds.first = 0; + V.sim_cmds.last = 0; + V.sim_cmds.count = 0; } - UnlockTicketMutex(&P.sim_input_back_tm); ////////////////////////////// @@ -2750,7 +2777,7 @@ void V_TickForever(WaveLaneCtx *lane) // { // P_CmdNode *n = PushStructNoZero(frame->arena, P_CmdNode); // *n = *src; - // SllQueuePush(step_cmds.first, step_cmds.last, n); + // DllQueuePush(step_cmds.first, step_cmds.last, n); // ++step_cmds.count; // } @@ -2775,9 +2802,8 @@ void V_TickForever(WaveLaneCtx *lane) // TODO: Remove this P_Frame *blend_frame = 0; { - // P_ResetWorldFromFrame(blended_world, predict_world->last_frame); - // P_Frame *blend_frame = blended_world->last_frame; - blend_frame = predict_frame; + P_ClearFrames(blend_world, I64Min, I64Max); + blend_frame = P_PushFrame(blend_world, sim_world->last_frame, sim_world->last_frame->tick); } @@ -3206,85 +3232,85 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Debug draw - // { - // // Copy debug draw data from sim - // if (received_unseen_tick) - // { - // ResetArena(sim_debug_arena); - // first_sim_debug_draw_node = 0; - // last_sim_debug_draw_node = 0; - // { - // i64 dst_idx = 0; - // P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, sim_output->debug_draw_nodes_count); - // for (P_DebugDrawNode *src = sim_output->first_debug_draw_node; src; src = src->next) - // { - // P_DebugDrawNode *dst = &dst_nodes[dst_idx]; - // *dst = *src; - // dst_idx += 1; - // SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst); - // } - // } - // } + { + // Copy debug draw data from sim + // if (received_unseen_tick) + { + ResetArena(sim_debug_arena); + first_sim_debug_draw_node = 0; + last_sim_debug_draw_node = 0; + { + i64 dst_idx = 0; + P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, sim_output->debug_draw_nodes_count); + for (P_DebugDrawNode *src = sim_output->first_debug_draw_node; src; src = src->next) + { + P_DebugDrawNode *dst = &dst_nodes[dst_idx]; + *dst = *src; + dst_idx += 1; + SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst); + } + } + } - // // Merge vis debug draws with sim debug draws - // P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node; - // P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node; - // if (P_tl.first_debug_draw_node) - // { - // if (last_debug_draw_node) - // { - // last_debug_draw_node->next = P_tl.first_debug_draw_node; - // } - // else - // { - // first_debug_draw_node = P_tl.first_debug_draw_node; - // } - // last_debug_draw_node = P_tl.last_debug_draw_node; - // } + // Merge vis debug draws with sim debug draws + P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node; + P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node; + if (P_tl.first_debug_draw_node) + { + if (last_debug_draw_node) + { + last_debug_draw_node->next = P_tl.first_debug_draw_node; + } + else + { + first_debug_draw_node = P_tl.first_debug_draw_node; + } + last_debug_draw_node = P_tl.last_debug_draw_node; + } - // // Push draws - // for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next) - // { - // Vec4 color = Vec4FromU32(n->srgb32); - // i32 detail = 24; - // f32 radius = 5; - // switch(n->kind) - // { - // case P_DebugDrawKind_Point: - // { - // Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p); - // V_DrawPoint(ui_p, color); - // } break; + // Push draws + for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next) + { + Vec4 color = Vec4FromU32(n->srgb32); + i32 detail = 24; + f32 radius = 5; + switch(n->kind) + { + case P_DebugDrawKind_Point: + { + Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p); + V_DrawPoint(ui_p, color); + } break; - // case P_DebugDrawKind_Line: - // { - // Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0); - // Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1); - // V_DrawLine(ui_p0, ui_p1, color); - // } break; + case P_DebugDrawKind_Line: + { + Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0); + Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1); + V_DrawLine(ui_p0, ui_p1, color); + } break; - // case P_DebugDrawKind_Rect: - // { - // Rng2 ui_rect = Zi; - // ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0); - // ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1); - // V_DrawRect(ui_rect, color, V_DrawFlag_Line); - // } break; + case P_DebugDrawKind_Rect: + { + Rng2 ui_rect = Zi; + ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0); + ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1); + V_DrawRect(ui_rect, color, V_DrawFlag_Line); + } break; - // case P_DebugDrawKind_Shape: - // { - // P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape); - // V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line); - // } break; - // } - // } + case P_DebugDrawKind_Shape: + { + P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape); + V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line); + } break; + } + } - // // Reset vis debug draws - // ResetArena(P_tl.debug_arena); - // P_tl.first_debug_draw_node = 0; - // P_tl.last_debug_draw_node = 0; - // P_tl.debug_draw_nodes_count = 0; - // } + // Reset vis debug draws + ResetArena(P_tl.debug_arena); + P_tl.first_debug_draw_node = 0; + P_tl.last_debug_draw_node = 0; + P_tl.debug_draw_nodes_count = 0; + } ////////////////////////////// @@ -3560,29 +3586,28 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Prune ents - // { - // i64 ents_to_prune_count = 0; - // P_Ent **ents_to_prune = PushStructsNoZero(frame->arena, P_Ent *, world->ents_count); - // for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent)) - // { - // if (ent->exists <= 0) - // { - // ents_to_prune[ents_to_prune_count] = ent; - // ents_to_prune_count += 1; - // } - // } - - // for (i64 prune_idx = 0; prune_idx < ents_to_prune_count; ++prune_idx) - // { - // // FIXME: Add to free list - // P_Ent *ent = ents_to_prune[prune_idx]; - // P_EntBin *bin = &world->ent_bins[ent->key.v % world->ent_bins_count]; - // DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin); - // DllQueueRemove(world->first_ent, world->last_ent, ent); - // world->ents_count -= 1; - // } - // } + { + i64 ents_to_prune_count = 0; + P_Ent **ents_to_prune = PushStructsNoZero(frame->arena, P_Ent *, sim_frame->ents_count); + for (P_Ent *ent = P_FirstEnt(sim_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + if (ent->exists <= 0) + { + ents_to_prune[ents_to_prune_count] = ent; + ents_to_prune_count += 1; + } + } + for (i64 prune_idx = 0; prune_idx < ents_to_prune_count; ++prune_idx) + { + P_Ent *ent = ents_to_prune[prune_idx]; + P_EntBin *bin = &sim_frame->ent_bins[ent->key.v % sim_frame->ent_bins_count]; + DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin); + DllQueueRemoveNPZ(&P_NilEnt, sim_frame->first_ent, sim_frame->last_ent, ent, next, prev); + sim_frame->ents_count -= 1; + SllStackPush(sim_world->first_free_ent, ent); + } + } ////////////////////////////// //- End frame diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index dc621cb0..f780a8a0 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -123,6 +123,7 @@ Struct(V_Cmd) Struct(V_CmdNode) { V_CmdNode *next; + V_CmdNode *prev; V_Cmd cmd; }; @@ -265,6 +266,8 @@ Struct(V_Frame) V_CmdNode *first_cmd_node; V_CmdNode *last_cmd_node; + i64 predict_to; + // Control Vec2 move; Vec2 look; @@ -288,6 +291,7 @@ Struct(V_Ctx) // Sim commands P_CmdList sim_cmds; + P_CmdNode *first_free_sim_cmd_node; // Atomic monotonically increasing allocation counter sequence for GPU particle ring buffer u32 particle_seq;