From cd48dd53ffdd37931a20e5016bff9bc9181dfccf Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 17 Dec 2025 15:37:56 -0600 Subject: [PATCH] tiling progress --- src/base/base_shader.gh | 31 +++ src/config.h | 2 +- src/pp/pp_sim/pp_sim.lay | 4 + src/pp/pp_sim/pp_sim_core.c | 113 +++++++--- src/pp/pp_sim/pp_sim_core.h | 16 +- src/pp/pp_sim/pp_sim_tiles.cg | 16 ++ src/pp/pp_sim/pp_sim_tiles.cgh | 29 +++ src/pp/pp_vis/pp_vis_core.c | 347 ++++++++++++++++++++----------- src/pp/pp_vis/pp_vis_core.h | 25 ++- src/pp/pp_vis/pp_vis_shaders.cgh | 17 +- src/pp/pp_vis/pp_vis_shaders.g | 148 ++++++++----- 11 files changed, 529 insertions(+), 219 deletions(-) create mode 100644 src/pp/pp_sim/pp_sim_tiles.cg create mode 100644 src/pp/pp_sim/pp_sim_tiles.cgh diff --git a/src/base/base_shader.gh b/src/base/base_shader.gh index 73197278..b68ec5f0 100644 --- a/src/base/base_shader.gh +++ b/src/base/base_shader.gh @@ -45,6 +45,37 @@ u32 countof(T arr[N]) return N; } +//////////////////////////////////////////////////////////// +//~ Min / max + +//- Min +#define MinU8(...) min(__VA_ARGS__) +#define MinI8(...) min(__VA_ARGS__) +#define MinU32(...) min(__VA_ARGS__) +#define MinI32(...) min(__VA_ARGS__) +#define MinF32(...) min(__VA_ARGS__) +#define MinU64(...) min(__VA_ARGS__) +#define MinI64(...) min(__VA_ARGS__) +#define MinF64(...) min(__VA_ARGS__) + +//- Max +#define MaxU8(...) max(__VA_ARGS__) +#define MaxI8(...) max(__VA_ARGS__) +#define MaxU32(...) max(__VA_ARGS__) +#define MaxI32(...) max(__VA_ARGS__) +#define MaxF32(...) max(__VA_ARGS__) +#define MaxU64(...) max(__VA_ARGS__) +#define MaxI64(...) max(__VA_ARGS__) +#define MaxF64(...) max(__VA_ARGS__) + +//- Clamp +#define ClampU32(...) clamp(__VA_ARGS__) +#define ClampI32(...) clamp(__VA_ARGS__) +#define ClampF32(...) clamp(__VA_ARGS__) +#define ClampU64(...) clamp(__VA_ARGS__) +#define ClampI64(...) clamp(__VA_ARGS__) +#define ClampF64(...) clamp(__VA_ARGS__) + //////////////////////////////////////////////////////////// //~ Color helpers diff --git a/src/config.h b/src/config.h index 6329442a..97fefc3b 100644 --- a/src/config.h +++ b/src/config.h @@ -69,7 +69,7 @@ #define FLOOD_DEBUG 0 -#define GPU_DEBUG 0 +#define GPU_DEBUG 1 #define GPU_DEBUG_VALIDATION 0 #define GPU_SHADER_PRINT 1 diff --git a/src/pp/pp_sim/pp_sim.lay b/src/pp/pp_sim/pp_sim.lay index 43b3112a..08b8457f 100644 --- a/src/pp/pp_sim/pp_sim.lay +++ b/src/pp/pp_sim/pp_sim.lay @@ -8,6 +8,8 @@ ////////////////////////////// //- Api +@IncludeC pp_sim_tiles.cgh +@IncludeG pp_sim_tiles.cgh @IncludeC pp_sim_core.h @Bootstrap S_Bootstrap @@ -16,3 +18,5 @@ //- Impl @IncludeC pp_sim_core.c +@IncludeC pp_sim_tiles.cg +@IncludeG pp_sim_tiles.cg diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 8abb400f..ca8cf219 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -62,6 +62,30 @@ S_Key S_RandKey(void) return result; } +//////////////////////////////////////////////////////////// +//~ Tile helpers + +void S_UpdateTilesInPlaceFromPlacement(u8 *tiles, S_TilePlacement placement) +{ + switch (placement.placement_kind) + { + case S_TilePlacementKind_Range: + { + S_TileKind tile = placement.tile_kind; + Rng2I32 range = placement.range; + for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) + { + for (i32 tile_x = range.p0.y; tile_x < range.p1.y; ++tile_x) + { + Vec2I32 tile_pos = VEC2I32(tile_x, tile_y); + i32 tile_idx = S_TileIdxFromTilePos(tile_pos); + tiles[tile_idx] = (u8)tile; + } + } + } break; + } +} + //////////////////////////////////////////////////////////// //~ Shape helpers @@ -237,6 +261,8 @@ void S_TickForever(WaveLaneCtx *lane) Arena *frame_arena = AcquireArena(Gibi(64)); Arena *perm = PermArena(); + const i32 world_size = S_WorldSize; + //- World data Arena *ents_arena = AcquireArena(Gibi(64)); S_World *world = PushStruct(perm, S_World); @@ -244,6 +270,8 @@ void S_TickForever(WaveLaneCtx *lane) i64 first_free_ent_num = 0; i64 sim_time_ns = 0; + u8 *tiles = PushBytes(perm, world_size * world_size * 4, alignof(S_TileKind)); + ////////////////////////////// //- Sim loop @@ -280,42 +308,49 @@ void S_TickForever(WaveLaneCtx *lane) UnlockTicketMutex(&S.input_back_tm); ////////////////////////////// - //- Spawn entities + //- Process world edit commands + u64 tile_placements_count = 0; for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next) { - S_Cmd cmd = cmd_node->cmd; - if (cmd.kind == S_CmdKind_Spawn) - { - for (S_EntListNode *src_n = cmd.ents.first; src_n; src_n = src_n->next) - { - S_Ent *src = &src_n->ent; - S_Key key = src->key; - if (!S_IsKeyNil(key)) - { - S_Ent *dst = S_EntFromKey(&lookup, key); - if (S_IsEntNil(dst)) - { - if (first_free_ent_num > 0) - { - dst = &world->ents[first_free_ent_num - 1]; - first_free_ent_num = dst->next_free_ent_num; - } - else - { - dst = PushStructNoZero(ents_arena, S_Ent); - } - *dst = S_ro.nil_ent; - dst->key = key; - ++world->ents_count; - } - *dst = *src; - dst->local_shape.points_count = MaxI32(dst->local_shape.points_count, 1); + S_Cmd *cmd = &cmd_node->cmd; - dst->active = 1; + /* Spawn entity */ + if (cmd->kind == S_CmdKind_Spawn) + { + S_Ent *src = &cmd->ent; + S_Key key = src->key; + if (!S_IsKeyNil(key)) + { + S_Ent *dst = S_EntFromKey(&lookup, key); + if (S_IsEntNil(dst)) + { + if (first_free_ent_num > 0) + { + dst = &world->ents[first_free_ent_num - 1]; + first_free_ent_num = dst->next_free_ent_num; + } + else + { + dst = PushStructNoZero(ents_arena, S_Ent); + } + *dst = S_ro.nil_ent; + dst->key = key; + ++world->ents_count; } + *dst = *src; + dst->local_shape.points_count = MaxI32(dst->local_shape.points_count, 1); + + dst->active = 1; } - LogInfoF("Received spawn cmd containing %F ents. New count: %F", FmtSint(cmd.ents.count), FmtSint(world->ents_count)); + } + + /* Place tiles */ + if (cmd->kind == S_CmdKind_Tile) + { + tile_placements_count += 1; + S_TilePlacement placement = cmd->tile_placement; + S_UpdateTilesInPlaceFromPlacement(tiles, placement); } } lookup = S_LookupFromWorld(frame_arena, world); @@ -377,6 +412,24 @@ void S_TickForever(WaveLaneCtx *lane) S_Ent *dst = &snapshot->ents[ent_idx]; *dst = *src; } + + /* Forward tile placements */ + snapshot->tile_placements_count = tile_placements_count; + snapshot->tile_placements = PushStructs(output->arena, S_TilePlacement, tile_placements_count); + { + u64 tile_placement_idx = 0; + for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node && tile_placement_idx < tile_placements_count; cmd_node = cmd_node->next) + { + S_Cmd *cmd = &cmd_node->cmd; + if (cmd->kind == S_CmdKind_Tile) + { + S_TilePlacement *dst_placement = &snapshot->tile_placements[tile_placement_idx]; + *dst_placement = cmd->tile_placement; + tile_placement_idx += 1; + } + } + } + } UnlockTicketMutex(&S.output_back_tm); diff --git a/src/pp/pp_sim/pp_sim_core.h b/src/pp/pp_sim/pp_sim_core.h index b19a6380..7d5569d2 100644 --- a/src/pp/pp_sim/pp_sim_core.h +++ b/src/pp/pp_sim/pp_sim_core.h @@ -105,6 +105,7 @@ Struct(S_Lookup) Struct(S_World) { i64 tick; + S_Ent *ents; i64 ents_count; }; @@ -112,8 +113,12 @@ Struct(S_World) Struct(S_Snapshot) { i64 tick; + S_Ent *ents; i64 ents_count; + + S_TilePlacement *tile_placements; + u64 tile_placements_count; }; Struct(S_SnapshotNode) @@ -137,6 +142,7 @@ Struct(S_Iter) Enum(S_CmdKind) { S_CmdKind_Nop, + S_CmdKind_Tile, S_CmdKind_Spawn, S_CmdKind_Control, }; @@ -145,8 +151,11 @@ Struct(S_Cmd) { S_CmdKind kind; + /* Tiles */ + S_TilePlacement tile_placement; + /* Spawn */ - S_EntList ents; + S_Ent ent; /* Control */ S_Key target; @@ -226,6 +235,11 @@ b32 S_MatchKey(S_Key a, S_Key b); S_Key S_RandKey(void); +//////////////////////////////////////////////////////////// +//~ Tile helpers + +void S_UpdateTilesInPlaceFromPlacement(u8 *tiles, S_TilePlacement placement); + //////////////////////////////////////////////////////////// //~ Shape helpers diff --git a/src/pp/pp_sim/pp_sim_tiles.cg b/src/pp/pp_sim/pp_sim_tiles.cg new file mode 100644 index 00000000..f4693235 --- /dev/null +++ b/src/pp/pp_sim/pp_sim_tiles.cg @@ -0,0 +1,16 @@ +//////////////////////////////////////////////////////////// +//~ Tile helpers + +Vec2I32 S_TilePosFromWorldPos(Vec2 p) +{ + Vec2I32 result; + result.x = ClampI32((p.x + S_WorldSize / 2) * 2, 0, (S_WorldSize * 2) - 1); + result.y = ClampI32((p.y + S_WorldSize / 2) * 2, 0, (S_WorldSize * 2) - 1); + return result; +} + +i32 S_TileIdxFromTilePos(Vec2I32 p) +{ + i32 result = ClampI32(p.x + (p.y * S_WorldSize * 2), 0, S_WorldSize * S_WorldSize * 4); + return result; +} diff --git a/src/pp/pp_sim/pp_sim_tiles.cgh b/src/pp/pp_sim/pp_sim_tiles.cgh new file mode 100644 index 00000000..ad4a72d5 --- /dev/null +++ b/src/pp/pp_sim/pp_sim_tiles.cgh @@ -0,0 +1,29 @@ +//////////////////////////////////////////////////////////// +//~ Tile types + +#define S_WorldSize 128 + +Enum(S_TileKind) +{ + S_TileKind_None, + S_TileKind_Floor, + S_TileKind_Wall, +}; + +Enum(S_TilePlacementKind) +{ + S_TilePlacementKind_Range +}; + +Struct(S_TilePlacement) +{ + S_TilePlacementKind placement_kind; + S_TileKind tile_kind; + Rng2I32 range; +}; + +//////////////////////////////////////////////////////////// +//~ Tile helpers + +Vec2I32 S_TilePosFromWorldPos(Vec2 p); +i32 S_TileIdxFromTilePos(Vec2I32 p); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 42949cce..b1b04723 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -14,12 +14,37 @@ void V_Shutdown(void) YieldOnFence(&V.shutdown_complete, 1); } +//////////////////////////////////////////////////////////// +//~ Helpers + +V_Frame *V_CurrentFrame(void) +{ + return &V.frames[V.current_frame_idx]; +} + +S_Cmd *V_PushSimCmd(S_CmdKind kind) +{ + V_Frame *frame = V_CurrentFrame(); + S_CmdNode *n = PushStruct(frame->arena, S_CmdNode); + n->cmd.kind = kind; + SllQueuePush(frame->first_sim_cmd_node, frame->last_sim_cmd_node, n); + ++frame->sim_cmds_count; + return &n->cmd; +} + //////////////////////////////////////////////////////////// //~ Vis tick void V_TickForever(WaveLaneCtx *lane) { Arena *perm = PermArena(); + G_ArenaHandle gpu_perm = G_PermArena(); + + const i32 world_size = S_WorldSize; + const f32 zoom_rate = 1.50; + const f32 min_zoom = 0.03; + const f32 max_zoom = 10.0; + const f32 meters_per_draw_width = 20; ////////////////////////////// //- Init vis state @@ -28,6 +53,16 @@ void V_TickForever(WaveLaneCtx *lane) V.world = PushStruct(V.world_arena, S_World); V.player_key = S_RandKey(); + u8 *tiles = PushBytes(perm, world_size * world_size * 4, alignof(S_TileKind)); + + G_ResourceHandle gpu_tiles = G_PushTexture2D( + gpu_perm, + G_Format_R8_Uint, + VEC2I32(world_size, world_size), + G_Layout_DirectQueue_ShaderRead_ShaderReadWrite_CopyRead_CopyWrite + ); + G_Texture2DRef gpu_tiles_ref = G_PushTexture2DRef(gpu_perm, gpu_tiles); + for (u32 i = 0; i < countof(V.frames); ++i) { V_Frame *frame = &V.frames[i]; @@ -111,7 +146,7 @@ void V_TickForever(WaveLaneCtx *lane) Arena *old_arena = frame->arena; Arena *old_dverts_arena = frame->dverts_arena; Arena *old_dvert_idxs_arena = frame->dvert_idxs_arena; - G_ArenaHandle old_gpu_arena = frame->gpu_arena; + G_ArenaHandle old_gpu_arena = frame->gpu_arena; ZeroStruct(frame); frame->arena = old_arena; frame->dverts_arena = old_dverts_arena; @@ -127,7 +162,7 @@ void V_TickForever(WaveLaneCtx *lane) /* Persist state */ CopyBytes(frame->held_buttons, last_frame->held_buttons, sizeof(frame->held_buttons)); frame->commands_widget = last_frame->commands_widget; - frame->edit_mode = last_frame->edit_mode; + frame->is_editing = last_frame->is_editing; frame->ui_debug = last_frame->ui_debug; frame->show_command_palette = last_frame->show_command_palette; frame->show_console = last_frame->show_console; @@ -141,48 +176,26 @@ void V_TickForever(WaveLaneCtx *lane) frame->dt = SecondsFromNs(frame->dt_ns); S_Iter iter = Zi; - S_EntList spawn_ents = Zi; ////////////////////////////// //- Spawn test ents if (frame->tick == 1) { - S_Key child_key = S_RandKey(); - - i32 count = 1; - for (u64 i = 0; i < count; ++i) + S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Spawn); + S_Ent *ent = &cmd->ent; + ent->key = V.player_key; + ent->move_speed = 0.1; { - S_EntListNode *n = PushStruct(frame->arena, S_EntListNode); - SllQueuePush(spawn_ents.first, spawn_ents.last, n); - ++spawn_ents.count; - S_Ent *ent = &n->ent; - *ent = S_ro.nil_ent; - switch (i) - { - /* Test player */ - case 0: - { - ent->key = V.player_key; - ent->move_speed = 0.1; - { - ent->local_shape = S_ShapeFromDesc( - .mass = 10, - .count = 1, - .radius = 0.4, - ); - } - // ent->local_xf = XformFromPos(VEC2(200, 200)); - ent->xf = XformFromPos(VEC2(0, 0)); - ent->has_weapon = 1; - } break; - - default: - { - Assert(0); - } break; - } + ent->local_shape = S_ShapeFromDesc( + .mass = 10, + .count = 1, + .radius = 0.4, + ); } + // ent->local_xf = XformFromPos(VEC2(200, 200)); + ent->xf = XformFromPos(VEC2(0, 0)); + ent->has_weapon = 1; } ////////////////////////////// @@ -238,6 +251,34 @@ void V_TickForever(WaveLaneCtx *lane) } UnlockTicketMutex(&S.output_back_tm); + ////////////////////////////// + //- Update tiles from sim + + { + /* TODO: Only upload dirty rects to gpu tile map */ + b32 is_dirty = 0; + for (S_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next) + { + S_Snapshot *snapshot = &n->snapshot; + if (snapshot->tick > V.world->tick) + { + for (u64 placement_idx = 0; placement_idx < snapshot->tile_placements_count; ++placement_idx) + { + is_dirty = 1; + S_TilePlacement placement = snapshot->tile_placements[placement_idx]; + S_UpdateTilesInPlaceFromPlacement(tiles, placement); + } + } + } + if (is_dirty) + { + G_CopyCpuToBuffer(frame->cl, gpu_tiles, 0, tiles, RNGU64(0, sizeof(tiles))); + } + } + + ////////////////////////////// + //- Update world from sim + if (sim_output->last_snapshot_node && sim_output->last_snapshot_node->snapshot.tick > V.world->tick) { ResetArena(V.world_arena); @@ -291,18 +332,9 @@ void V_TickForever(WaveLaneCtx *lane) } } - ////////////////////////////// - //- Update edit mode camera position - ////////////////////////////// //- Initialize world <-> draw <-> ui transforms - f32 zoom_rate = 1.50; - f32 min_zoom = 0.03; - f32 max_zoom = 50.0; - f32 world_size = 256; - f32 meters_per_draw_width = 20; - /* World <-> ui */ frame->world_to_ui_xf = XformIdentity; frame->ui_to_world_xf = XformIdentity; @@ -310,18 +342,20 @@ void V_TickForever(WaveLaneCtx *lane) /* Determine target camera pos */ Vec2 target_camera_pos = Zi; f32 target_camera_zoom = 0; - if (frame->edit_mode) + if (frame->is_editing) { b32 pan_button = Button_M3; frame->is_panning = frame->held_buttons[pan_button] != 0; frame->edit_camera_zoom *= PowF32(zoom_rate, -last_frame->zooms); if (frame->edit_camera_zoom <= 0) { - frame->edit_camera_zoom = 1; + frame->edit_camera_pos = S_EntFromKey(&V.lookup, V.player_key)->xf.og; + frame->edit_camera_zoom = 3; } frame->edit_camera_zoom = ClampF32(frame->edit_camera_zoom, min_zoom, max_zoom); /* Offset edit camera based on cursor if panning / zooming */ - if (last_frame->edit_mode && ((last_frame->zooms != 0 && (frame->edit_camera_zoom != last_frame->edit_camera_zoom)) || (frame->is_panning && last_frame->is_panning))) + b32 is_zooming = last_frame->zooms != 0 && (frame->edit_camera_zoom != last_frame->edit_camera_zoom); + if (last_frame->is_editing && (is_zooming || (frame->is_panning && last_frame->is_panning))) { Xform last_frame_edit_to_ui_xf = Zi; Xform edit_to_ui_xf = Zi; @@ -366,7 +400,7 @@ void V_TickForever(WaveLaneCtx *lane) { lerp_ratio = 1; } - else if (frame->edit_mode) + else if (frame->is_editing) { lerp_ratio = 30.0 * frame->dt; } @@ -445,28 +479,67 @@ void V_TickForever(WaveLaneCtx *lane) if (frame->show_console) { + f32 padding = 20; + f32 rounding = 0; + Vec4 color = VEC4(0, 0, 0, 0.75); + UI_BuildSpacer(UI_GROW(1, 0), Axis_Y); + // UI_SetNext(Width, UI_SHRINK(0, 1)); + // UI_SetNext(Height, UI_SHRINK(0, 1)); + UI_SetNext(Width, UI_SHRINK(0, 1)); + UI_SetNext(Height, UI_SHRINK(0, 1)); + UI_SetNext(BackgroundColor, color); + UI_SetNext(Rounding, UI_RPIX(rounding)); UI_PushCP(UI_BuildColumn()); { + // UI_BuildSpacer(UI_PIX(10, 1), Axis_X); + // UI_Push(ChildAlignment, UI_Alignment_Center); + // UI_SetNext(Width, UI_SHRINK(0, 1)); + // UI_SetNext(Height, UI_SHRINK(0, 1)); + UI_SetNext(Width, UI_SHRINK(0, 1)); + UI_SetNext(Height, UI_SHRINK(0, 1)); + UI_PushCP(UI_BuildRow()); { + UI_BuildSpacer(UI_PIX(padding, 1), Axis_X); + UI_SetNext(Width, UI_SHRINK(0, 1)); + UI_SetNext(Height, UI_SHRINK(0, 1)); + UI_PushCP(UI_BuildColumn()); { - UI_Push(FontSize, 32); - UI_BuildLabelF("CPU:"); - UI_Pop(FontSize); + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); + Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor); + i32 tile_idx = S_TileIdxFromTilePos(tile_pos); + { + UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor)); + UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos)); + UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx)); + } + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); + { + { + UI_Push(FontSize, 32); + UI_BuildLabelF("CPU:"); + UI_Pop(FontSize); + } + UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumArenas))); + UI_BuildLabelF(" Arena memory committed: %F MiB", FmtFloat((f64)GetGstat(ArenaMemoryCommitted) / 1024 / 1024)); + UI_BuildLabelF(" Arena memory reserved: %F TiB", FmtFloat((f64)GetGstat(ArenaMemoryReserved) / 1024 / 1024 / 1024 / 1024)); + } + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); + { + { + UI_Push(FontSize, 32); + UI_BuildLabelF("GPU:"); + UI_Pop(FontSize); + } + UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumGpuArenas))); + UI_BuildLabelF(" Dedicated arena memory committed: %F MiB", FmtFloat((f64)GetGstat(DedicatedGpuArenaMemoryCommitted) / 1024 / 1024)); + UI_BuildLabelF(" Shared arena memory committed: %F MiB", FmtFloat((f64)GetGstat(SharedGpuArenaMemoryCommitted) / 1024 / 1024)); + } + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); } - UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumArenas))); - UI_BuildLabelF(" Arena memory committed: %F MiB", FmtFloat((f64)GetGstat(ArenaMemoryCommitted) / 1024 / 1024)); - UI_BuildLabelF(" Arena memory reserved: %F TiB", FmtFloat((f64)GetGstat(ArenaMemoryReserved) / 1024 / 1024 / 1024 / 1024)); - } - { - { - UI_Push(FontSize, 32); - UI_BuildLabelF("GPU:"); - UI_Pop(FontSize); - } - UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumGpuArenas))); - UI_BuildLabelF(" Dedicated arena memory committed: %F MiB", FmtFloat((f64)GetGstat(DedicatedGpuArenaMemoryCommitted) / 1024 / 1024)); - UI_BuildLabelF(" Shared arena memory committed: %F MiB", FmtFloat((f64)GetGstat(SharedGpuArenaMemoryCommitted) / 1024 / 1024)); + UI_PopCP(UI_TopCP()); + UI_BuildSpacer(UI_PIX(padding, 1), Axis_X); } + UI_PopCP(UI_TopCP()); } UI_PopCP(UI_TopCP()); } @@ -474,7 +547,7 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Build edit mode UI - if (frame->edit_mode) + if (frame->is_editing) { } @@ -509,7 +582,7 @@ void V_TickForever(WaveLaneCtx *lane) case V_CmdKind_zoom_in: { - if (frame->edit_mode) + if (frame->is_editing) { frame->zooms += 1; } @@ -517,24 +590,24 @@ void V_TickForever(WaveLaneCtx *lane) case V_CmdKind_zoom_out: { - if (frame->edit_mode) + if (frame->is_editing) { frame->zooms -= 1; } } break; - case V_CmdKind_toggle_edit_mode: + case V_CmdKind_toggle_editor: { - b32 new = !frame->edit_mode; + b32 new = !frame->is_editing; if (new) { - LogInfoF("Enabled edit mode"); + LogInfoF("Enabled editor"); } else { - LogInfoF("Disabled edit mode"); + LogInfoF("Disabled editor"); } - frame->edit_mode = new; + frame->is_editing = new; } break; case V_CmdKind_toggle_ui_debug: @@ -564,6 +637,11 @@ void V_TickForever(WaveLaneCtx *lane) case V_CmdKind_spawn: { + S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Tile); + cmd->tile_placement.placement_kind = S_TilePlacementKind_Range; + cmd->tile_placement.tile_kind = S_TileKind_Floor; + cmd->tile_placement.range.p0 = VEC2I32(100, 100); + cmd->tile_placement.range.p1 = VEC2I32(200, 200); } break; } } @@ -571,7 +649,7 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Compute movement & look - if (!frame->edit_mode) + if (!frame->is_editing) { Vec2 move = Zi; { @@ -590,53 +668,77 @@ void V_TickForever(WaveLaneCtx *lane) frame->look = look; } + /* Push control cmd */ + { + S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Control); + cmd->target = V.player_key; + cmd->move = frame->move; + cmd->look = frame->look; + } + ////////////////////////////// //- Submit sim commands LockTicketMutex(&S.input_back_tm); { S_InputState *v2s = &S.input_states[S.input_back_idx]; - - /* Submit control cmd */ + for (S_CmdNode *src = frame->first_sim_cmd_node; src; src = src->next) { - S_Cmd *cmd = 0; - { - S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); - SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); - ++v2s->cmds_count; - cmd = &cmd_node->cmd; - } - cmd->kind = S_CmdKind_Control; - cmd->target = V.player_key; - cmd->move = frame->move; - cmd->look = frame->look; - } - - /* Submit spawn cmds */ - if (spawn_ents.count > 0) - { - S_Cmd *cmd = 0; - { - S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); - SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); - ++v2s->cmds_count; - cmd = &cmd_node->cmd; - } - cmd->kind = S_CmdKind_Spawn; - S_EntList *dst = &cmd->ents; - for (S_EntListNode *src_n = spawn_ents.first; src_n; src_n = src_n->next) - { - S_EntListNode *dst_n = PushStruct(v2s->arena, S_EntListNode); - { - SllQueuePush(dst->first, dst->last, dst_n); - ++dst->count; - } - dst_n->ent = src_n->ent; - } + S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); + cmd_node->cmd = src->cmd; + SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); + ++v2s->cmds_count; } } UnlockTicketMutex(&S.input_back_tm); + // LockTicketMutex(&S.input_back_tm); + // { + // S_InputState *v2s = &S.input_states[S.input_back_idx]; + + // /* Submit control cmd */ + // { + // S_Cmd *cmd = 0; + // { + // S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); + // SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); + // ++v2s->cmds_count; + // cmd = &cmd_node->cmd; + // } + // cmd->kind = S_CmdKind_Control; + // cmd->target = V.player_key; + // cmd->move = frame->move; + // cmd->look = frame->look; + // } + + // /* Submit tile cmds */ + + + // /* Submit spawn cmds */ + // if (spawn_ents.count > 0) + // { + // S_Cmd *cmd = 0; + // { + // S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); + // SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); + // ++v2s->cmds_count; + // cmd = &cmd_node->cmd; + // } + // cmd->kind = S_CmdKind_Spawn; + // S_EntList *dst = &cmd->ents; + // for (S_EntListNode *src_n = spawn_ents.first; src_n; src_n = src_n->next) + // { + // S_EntListNode *dst_n = PushStruct(v2s->arena, S_EntListNode); + // { + // SllQueuePush(dst->first, dst->last, dst_n); + // ++dst->count; + // } + // dst_n->ent = src_n->ent; + // } + // } + // } + // UnlockTicketMutex(&S.input_back_tm); + ////////////////////////////// //- Render @@ -709,19 +811,24 @@ void V_TickForever(WaveLaneCtx *lane) params.target_size = frame->draw_dims; params.target_ro = draw_target_ro; params.target_rw = draw_target_rw; - params.shape_verts = dverts_ro; - params.target_cursor_pos = frame->draw_cursor; - - params.background_color_a = LinearFromSrgb(VEC4(0.30, 0.30, 0.30, 1)); - params.background_color_b = LinearFromSrgb(VEC4(0.15, 0.15, 0.15, 1)); - params.x_axis_color = LinearFromSrgb(VEC4(0.75, 0, 0, 1)); - params.y_axis_color = LinearFromSrgb(VEC4(0, 0.75, 0, 1)); - params.bounds_color = LinearFromSrgb(VEC4(0.75, 0.75, 0, 1)); - - params.world_size = world_size; params.world_to_draw_xf = frame->world_to_draw_xf; params.draw_to_world_xf = frame->draw_to_world_xf; + + params.target_cursor_pos = frame->draw_cursor; + params.camera_pos = frame->camera_pos; + params.camera_zoom = frame->camera_zoom; + + params.world_size = world_size; + params.tiles = gpu_tiles_ref; + params.shape_verts = dverts_ro; + + params.background_color_a = LinearFromSrgb(VEC4(0.30, 0.30, 0.30, 1)); + params.background_color_b = LinearFromSrgb(VEC4(0.15, 0.15, 0.15, 1)); + params.grid_color = LinearFromSrgb(VEC4(0, 0, 0, 1)); + params.x_axis_color = LinearFromSrgb(VEC4(0.75, 0, 0, 1)); + params.y_axis_color = LinearFromSrgb(VEC4(0, 0.75, 0, 1)); + params.bounds_color = LinearFromSrgb(VEC4(0.75, 0.75, 0, 1)); } G_ResourceHandle params_buff = G_PushBufferFromString(frame->gpu_arena, frame->cl, StringFromStruct(¶ms)); G_StructuredBufferRef params_ro = G_PushStructuredBufferRef(frame->gpu_arena, params_buff, V_DParams); diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index e955f645..c2c83ef5 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -7,7 +7,7 @@ X(toggle_command_palette, Toggle Command Palette, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_P, .ctrl = 1, .shift = 1 ), ) \ X(zoom_in, Zoom In, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelUp ), ) \ X(zoom_out, Zoom Out, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelDown ), ) \ - X(toggle_edit_mode, Toggle Edit Mode, V_CmdDescFlag_None, V_HOTKEY( Button_F1 ), ) \ + X(toggle_editor, Toggle Editor, V_CmdDescFlag_None, V_HOTKEY( Button_F1 ), ) \ X(toggle_ui_debug, Toggle UI Debug, V_CmdDescFlag_None, V_HOTKEY( Button_F5 ), ) \ X(toggle_console, Toggle Developer Console, V_CmdDescFlag_None, V_HOTKEY( Button_GraveAccent ), ) \ X(toggle_fullscreen, Toggle Fullscreen Mode, V_CmdDescFlag_None, V_HOTKEY( Button_Enter, .alt = 1 ) ) \ @@ -76,6 +76,11 @@ Global Readonly V_CmdDesc V_cmd_descs[V_CmdKind_Count] = { //////////////////////////////////////////////////////////// //~ Context types +Enum(V_EditMode) +{ + V_EditMode_Tile, +}; + Struct(V_Frame) { Arena *arena; @@ -99,12 +104,15 @@ Struct(V_Frame) Vec2I32 draw_dims; /* Modes */ - b32 edit_mode; + b32 is_editing; b32 ui_debug; b32 show_command_palette; b32 show_console; - /* Edit camera */ + /* Editor state */ + V_EditMode edit_mode; + + /* Editor */ b32 is_panning; Vec2 edit_camera_pos; f32 edit_camera_zoom; @@ -133,6 +141,11 @@ Struct(V_Frame) /* Control */ Vec2 move; Vec2 look; + + /* Sim cmds */ + u64 sim_cmds_count; + S_CmdNode *first_sim_cmd_node; + S_CmdNode *last_sim_cmd_node; }; Struct(V_Ctx) @@ -157,6 +170,12 @@ extern V_Ctx V; void V_Bootstrap(void); void V_Shutdown(void); +//////////////////////////////////////////////////////////// +//~ Helpers + +V_Frame *V_CurrentFrame(void); +S_Cmd *V_PushSimCmd(S_CmdKind kind); + //////////////////////////////////////////////////////////// //~ Vis tick diff --git a/src/pp/pp_vis/pp_vis_shaders.cgh b/src/pp/pp_vis/pp_vis_shaders.cgh index d1263d35..a01d6ef4 100644 --- a/src/pp/pp_vis/pp_vis_shaders.cgh +++ b/src/pp/pp_vis/pp_vis_shaders.cgh @@ -9,21 +9,24 @@ Struct(V_DParams) G_Texture2DRef target_ro; G_RWTexture2DRef target_rw; + Xform world_to_draw_xf; + Xform draw_to_world_xf; + + Vec2 target_cursor_pos; + Vec2 camera_pos; + f32 camera_zoom; + + f32 world_size; + G_Texture2DRef tiles; G_StructuredBufferRef quads; G_StructuredBufferRef shape_verts; - Vec2 target_cursor_pos; - Vec4 background_color_a; Vec4 background_color_b; + Vec4 grid_color; Vec4 x_axis_color; Vec4 y_axis_color; Vec4 bounds_color; - - f32 world_size; - - Xform world_to_draw_xf; - Xform draw_to_world_xf; }; //////////////////////////////////////////////////////////// diff --git a/src/pp/pp_vis/pp_vis_shaders.g b/src/pp/pp_vis/pp_vis_shaders.g index 09ca60e6..6416da81 100644 --- a/src/pp/pp_vis/pp_vis_shaders.g +++ b/src/pp/pp_vis/pp_vis_shaders.g @@ -5,75 +5,109 @@ ComputeShader2D(V_BackdropCS, 8, 8) { V_DParams params = G_Dereference(V_ShaderConst_Params)[0]; RWTexture2D target = G_Dereference(params.target_rw); + Texture2D tiles = G_Dereference(params.tiles); Vec2U32 target_pos = SV_DispatchThreadID; Vec2I32 target_size = params.target_size; if (target_pos.x < target_size.x && target_pos.y < target_size.y) { - Vec4 result = 0; + Vec4 result = Vec4(0.025, 0.025, 0.025, 1); + Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(target_pos, 1)); + Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos); - /* Checkered square color */ + f32 half_thickness = 1; + f32 half_bounds_size = params.world_size * 0.5; + Vec2 bounds_screen_p0 = mul(params.world_to_draw_xf, Vec3(-half_bounds_size, -half_bounds_size, 1)); + Vec2 bounds_screen_p1 = mul(params.world_to_draw_xf, Vec3(half_bounds_size, half_bounds_size, 1)); + b32 is_in_bounds = target_pos.x > (bounds_screen_p0.x - half_thickness) && + target_pos.y > (bounds_screen_p0.y - half_thickness) && + target_pos.x < (bounds_screen_p1.x + half_thickness) && + target_pos.y < (bounds_screen_p1.y + half_thickness); + if (is_in_bounds) { - i32 color_idx = 0; - Vec4 colors[2] = { - params.background_color_a, - params.background_color_b - }; - Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(target_pos, 1)); - Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(2, 2)); - if (world_pos_modded.x < 1) + /* Grid checker */ { - color_idx = !color_idx; - } - if (world_pos_modded.y < 1) - { - color_idx = !color_idx; - } - if (world_pos.x < 0) - { - color_idx = !color_idx; - } - if (world_pos.y < 0) - { - color_idx = !color_idx; - } - result = colors[color_idx]; - } - - { - f32 half_thickness = 1; - f32 half_bounds_size = params.world_size * 0.5; - Vec2 bounds_screen_p0 = mul(params.world_to_draw_xf, Vec3(-half_bounds_size, -half_bounds_size, 1)); - Vec2 bounds_screen_p1 = mul(params.world_to_draw_xf, Vec3(half_bounds_size, half_bounds_size, 1)); - if (target_pos.x > (bounds_screen_p0.x - half_thickness) && target_pos.y > (bounds_screen_p0.y - half_thickness) && - target_pos.x < (bounds_screen_p1.x + half_thickness) && target_pos.y < (bounds_screen_p1.y + half_thickness)) - { - /* Axis color */ + i32 color_idx = 0; + Vec4 colors[2] = { + params.background_color_a, + params.background_color_b + }; + Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(1.0, 1.0)); + if (world_pos_modded.x < 0.5) { - f32 half_thickness = 1; - Vec2 zero_screen = mul(params.world_to_draw_xf, Vec3(0, 0, 1)); - f32 x_dist = abs(target_pos.x - zero_screen.x); - f32 y_dist = abs(target_pos.y - zero_screen.y); - if (y_dist <= half_thickness) - { - result = params.x_axis_color; - } - else if (x_dist <= half_thickness) - { - result = params.y_axis_color; - } + color_idx = !color_idx; } - /* World bounds color */ + if (world_pos_modded.y < 0.5) { - f32 bounds_dist = 100000; - bounds_dist = min(bounds_dist, abs(target_pos.x - bounds_screen_p0.x)); - bounds_dist = min(bounds_dist, abs(target_pos.x - bounds_screen_p1.x)); - bounds_dist = min(bounds_dist, abs(target_pos.y - bounds_screen_p0.y)); - bounds_dist = min(bounds_dist, abs(target_pos.y - bounds_screen_p1.y)); - if (bounds_dist <= half_thickness) + color_idx = !color_idx; + } + if (world_pos.x < 0) + { + color_idx = !color_idx; + } + if (world_pos.y < 0) + { + color_idx = !color_idx; + } + result = colors[color_idx]; + } + /* Grid outline */ + { + Vec2 grid_screen_p0 = mul(params.world_to_draw_xf, Vec3(floor(world_pos), 1)); + Vec2 grid_screen_p1 = mul(params.world_to_draw_xf, Vec3(ceil(world_pos), 1)); + f32 grid_dist = 100000; + grid_dist = min(grid_dist, abs(target_pos.x - grid_screen_p0.x)); + grid_dist = min(grid_dist, abs(target_pos.x - grid_screen_p1.x)); + grid_dist = min(grid_dist, abs(target_pos.y - grid_screen_p0.y)); + grid_dist = min(grid_dist, abs(target_pos.y - grid_screen_p1.y)); + if (grid_dist <= half_thickness) + { + result = params.grid_color; + } + } + /* Tile */ + { + S_TileKind tile = (S_TileKind)tiles.Load(Vec3I32(tile_pos, 0)); + switch (tile) + { + default: break; + + case S_TileKind_Floor: { - result = params.bounds_color; - } + result = Color_Blue; + } break; + + case S_TileKind_Wall: + { + result = Color_Red; + } break; + } + } + /* Axis */ + { + f32 half_thickness = 1; + Vec2 zero_screen = mul(params.world_to_draw_xf, Vec3(0, 0, 1)); + f32 x_dist = abs(target_pos.x - zero_screen.x); + f32 y_dist = abs(target_pos.y - zero_screen.y); + if (y_dist <= half_thickness) + { + result = params.x_axis_color; + } + else if (x_dist <= half_thickness) + { + result = params.y_axis_color; + } + } + /* World bounds */ + { + f32 bounds_dist = 100000; + bounds_dist = min(bounds_dist, abs(target_pos.x - bounds_screen_p0.x)); + bounds_dist = min(bounds_dist, abs(target_pos.x - bounds_screen_p1.x)); + bounds_dist = min(bounds_dist, abs(target_pos.y - bounds_screen_p0.y)); + bounds_dist = min(bounds_dist, abs(target_pos.y - bounds_screen_p1.y)); + if (bounds_dist <= half_thickness) + { + result = params.bounds_color; } } }