feat: smaller cells (10x10px) for higher detail
Cells reduced from 16x16 to 10x10 pixels. Same window size now shows more of the world — finer detail, more cells visible. Adaptive viewport recalculates grid_w/grid_h from new cell size. 109 tests, 0 failures
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
{"0": "Vulkan Core Setup", "1": "Terminal Renderer & Game Loop", "2": "Graphics Vulkan Renderer", "3": "AI Pipe Protocol", "4": "AI Game Session", "5": "CLI Entry & GPU Mode", "6": "AI State Export", "7": "Terminal Input Handler", "8": "Entity System", "9": "Cellular Automaton", "10": "Replay System", "11": "Edge Case Tests", "12": "AI Actions & Grid", "13": "Material Physics Tests", "14": "Player Controller", "15": "Cell & Material Types", "16": "Material Interaction Tests", "17": "Player Control Tests", "18": "AI Agent Roadmap", "19": "Verlet Physics Solver", "20": "Render & Phase Roadmap", "21": "Collision Robustness Tests", "22": "Render Mode & UI Roadmap", "23": "Window Input (winit)", "24": "Determinism Tests", "25": "Ragdoll Death Tests", "26": "Grid Collision Resolver", "27": "Material Registry", "28": "Entity Types & Game Loop", "29": "Adaptive Viewport", "30": "Headless Dump & Combat Plan", "31": "Entity Damage Tests", "32": "Entity Movement Tests", "33": "Lava Physics Tests", "34": "Sand Physics Tests", "35": "Acid Physics Tests", "36": "Water Physics Tests", "37": "Ragdoll Physics Plan", "38": "Integration Tests", "39": "Per-Cell Color Plan", "40": "Game Run & Input", "41": "Slope Stepping", "42": "Renderer Trait", "43": "AI Module Root", "44": "Physics Module Root", "45": "Library Root", "46": "World Module Root"}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/home/emil/.local/share/uv/tools/graphifyy/bin/python
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/home/emil/Desktop/Verbatim
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
# Graph Report - . (2026-06-21)
|
||||||
|
|
||||||
|
## Corpus Check
|
||||||
|
- Corpus is ~33,231 words - fits in a single context window. You may not need a graph.
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
- 690 nodes · 1218 edges · 47 communities (44 shown, 3 thin omitted)
|
||||||
|
- Extraction: 97% EXTRACTED · 3% INFERRED · 0% AMBIGUOUS · INFERRED: 32 edges (avg confidence: 0.86)
|
||||||
|
- Token cost: 0 input · 0 output
|
||||||
|
|
||||||
|
## Community Hubs (Navigation)
|
||||||
|
- [[_COMMUNITY_Vulkan Core Setup|Vulkan Core Setup]]
|
||||||
|
- [[_COMMUNITY_Terminal Renderer & Game Loop|Terminal Renderer & Game Loop]]
|
||||||
|
- [[_COMMUNITY_Graphics Vulkan Renderer|Graphics Vulkan Renderer]]
|
||||||
|
- [[_COMMUNITY_AI Pipe Protocol|AI Pipe Protocol]]
|
||||||
|
- [[_COMMUNITY_AI Game Session|AI Game Session]]
|
||||||
|
- [[_COMMUNITY_CLI Entry & GPU Mode|CLI Entry & GPU Mode]]
|
||||||
|
- [[_COMMUNITY_AI State Export|AI State Export]]
|
||||||
|
- [[_COMMUNITY_Terminal Input Handler|Terminal Input Handler]]
|
||||||
|
- [[_COMMUNITY_Entity System|Entity System]]
|
||||||
|
- [[_COMMUNITY_Cellular Automaton|Cellular Automaton]]
|
||||||
|
- [[_COMMUNITY_Replay System|Replay System]]
|
||||||
|
- [[_COMMUNITY_Edge Case Tests|Edge Case Tests]]
|
||||||
|
- [[_COMMUNITY_AI Actions & Grid|AI Actions & Grid]]
|
||||||
|
- [[_COMMUNITY_Material Physics Tests|Material Physics Tests]]
|
||||||
|
- [[_COMMUNITY_Player Controller|Player Controller]]
|
||||||
|
- [[_COMMUNITY_Cell & Material Types|Cell & Material Types]]
|
||||||
|
- [[_COMMUNITY_Material Interaction Tests|Material Interaction Tests]]
|
||||||
|
- [[_COMMUNITY_Player Control Tests|Player Control Tests]]
|
||||||
|
- [[_COMMUNITY_AI Agent Roadmap|AI Agent Roadmap]]
|
||||||
|
- [[_COMMUNITY_Verlet Physics Solver|Verlet Physics Solver]]
|
||||||
|
- [[_COMMUNITY_Render & Phase Roadmap|Render & Phase Roadmap]]
|
||||||
|
- [[_COMMUNITY_Collision Robustness Tests|Collision Robustness Tests]]
|
||||||
|
- [[_COMMUNITY_Render Mode & UI Roadmap|Render Mode & UI Roadmap]]
|
||||||
|
- [[_COMMUNITY_Window Input (winit)|Window Input (winit)]]
|
||||||
|
- [[_COMMUNITY_Determinism Tests|Determinism Tests]]
|
||||||
|
- [[_COMMUNITY_Ragdoll Death Tests|Ragdoll Death Tests]]
|
||||||
|
- [[_COMMUNITY_Grid Collision Resolver|Grid Collision Resolver]]
|
||||||
|
- [[_COMMUNITY_Material Registry|Material Registry]]
|
||||||
|
- [[_COMMUNITY_Entity Types & Game Loop|Entity Types & Game Loop]]
|
||||||
|
- [[_COMMUNITY_Adaptive Viewport|Adaptive Viewport]]
|
||||||
|
- [[_COMMUNITY_Headless Dump & Combat Plan|Headless Dump & Combat Plan]]
|
||||||
|
- [[_COMMUNITY_Entity Damage Tests|Entity Damage Tests]]
|
||||||
|
- [[_COMMUNITY_Entity Movement Tests|Entity Movement Tests]]
|
||||||
|
- [[_COMMUNITY_Lava Physics Tests|Lava Physics Tests]]
|
||||||
|
- [[_COMMUNITY_Sand Physics Tests|Sand Physics Tests]]
|
||||||
|
- [[_COMMUNITY_Acid Physics Tests|Acid Physics Tests]]
|
||||||
|
- [[_COMMUNITY_Water Physics Tests|Water Physics Tests]]
|
||||||
|
- [[_COMMUNITY_Ragdoll Physics Plan|Ragdoll Physics Plan]]
|
||||||
|
- [[_COMMUNITY_Per-Cell Color Plan|Per-Cell Color Plan]]
|
||||||
|
- [[_COMMUNITY_Game Run & Input|Game Run & Input]]
|
||||||
|
- [[_COMMUNITY_Slope Stepping|Slope Stepping]]
|
||||||
|
- [[_COMMUNITY_Renderer Trait|Renderer Trait]]
|
||||||
|
|
||||||
|
## God Nodes (most connected - your core abstractions)
|
||||||
|
1. `VulkanRenderer` - 37 edges
|
||||||
|
2. `GraphicsRenderer` - 31 edges
|
||||||
|
3. `GameSession` - 26 edges
|
||||||
|
4. `Game` - 24 edges
|
||||||
|
5. `Entity` - 20 edges
|
||||||
|
6. `CellularAutomaton` - 19 edges
|
||||||
|
7. `InputHandler` - 18 edges
|
||||||
|
8. `Result` - 17 edges
|
||||||
|
9. `String` - 17 edges
|
||||||
|
10. `setup()` - 17 edges
|
||||||
|
|
||||||
|
## Surprising Connections (you probably didn't know these)
|
||||||
|
- `pipe render mode` --semantically_similar_to--> `AI pipe protocol (JSON stdin/stdout)` [INFERRED] [semantically similar]
|
||||||
|
AGENTS.md → PLAN.md
|
||||||
|
- `Game::fixed_update()` --semantically_similar_to--> `Fixed 60Hz timestep` [INFERRED] [semantically similar]
|
||||||
|
AGENTS.md → PLAN.md
|
||||||
|
- `Player` --semantically_similar_to--> `Player entity (headless dump)` [INFERRED] [semantically similar]
|
||||||
|
AGENTS.md → headless_dump.txt
|
||||||
|
- `rigid entity type` --semantically_similar_to--> `Rigid entities (AABB + slope stepping)` [INFERRED] [semantically similar]
|
||||||
|
AGENTS.md → PLAN.md
|
||||||
|
- `ragdoll entity type` --semantically_similar_to--> `Ragdoll corpses (Verlet)` [INFERRED] [semantically similar]
|
||||||
|
AGENTS.md → PLAN.md
|
||||||
|
|
||||||
|
## Import Cycles
|
||||||
|
- 1-file cycle: `src/ai/action.rs -> src/ai/action.rs`
|
||||||
|
- 1-file cycle: `src/world/grid.rs -> src/world/grid.rs`
|
||||||
|
- 1-file cycle: `src/ai/protocol.rs -> src/ai/protocol.rs`
|
||||||
|
- 1-file cycle: `src/ai/replay.rs -> src/ai/replay.rs`
|
||||||
|
- 1-file cycle: `src/ai/scenario.rs -> src/ai/scenario.rs`
|
||||||
|
- 1-file cycle: `src/ai/session.rs -> src/ai/session.rs`
|
||||||
|
- 1-file cycle: `src/ai/state.rs -> src/ai/state.rs`
|
||||||
|
- 1-file cycle: `src/game.rs -> src/game.rs`
|
||||||
|
- 1-file cycle: `src/entity/player.rs -> src/entity/player.rs`
|
||||||
|
- 1-file cycle: `src/render/terminal.rs -> src/render/terminal.rs`
|
||||||
|
- 1-file cycle: `src/input.rs -> src/input.rs`
|
||||||
|
- 1-file cycle: `src/main.rs -> src/main.rs`
|
||||||
|
- 1-file cycle: `src/physics/collision.rs -> src/physics/collision.rs`
|
||||||
|
- 1-file cycle: `src/physics/verlet.rs -> src/physics/verlet.rs`
|
||||||
|
- 1-file cycle: `src/render/graphics.rs -> src/render/graphics.rs`
|
||||||
|
- 1-file cycle: `src/render/vulkan.rs -> src/render/vulkan.rs`
|
||||||
|
- 1-file cycle: `src/render/window_input.rs -> src/render/window_input.rs`
|
||||||
|
- 1-file cycle: `src/world/cellular.rs -> src/world/cellular.rs`
|
||||||
|
- 1-file cycle: `src/world/material.rs -> src/world/material.rs`
|
||||||
|
- 1-file cycle: `tests/collision_robust.rs -> tests/collision_robust.rs`
|
||||||
|
|
||||||
|
## Hyperedges (group relationships)
|
||||||
|
- **Game loop fixed_update pipeline: CA step → rigid update → ragdoll update → damage** — [INFERRED]
|
||||||
|
- **Three render modes read the same Grid + EntityManager (single source of truth)** — [INFERRED]
|
||||||
|
- **GpuRenderer trait unifies VulkanRenderer + GraphicsRenderer behind run_gpu_mode<R>() with identical event loops** — [INFERRED]
|
||||||
|
|
||||||
|
## Communities (47 total, 3 thin omitted)
|
||||||
|
|
||||||
|
### Community 0 - "Vulkan Core Setup"
|
||||||
|
Cohesion: 0.10
|
||||||
|
Nodes (61): BufferUsageFlags, c_char, DescriptorPool, DescriptorSet, DescriptorSetLayout, Format, Image, MemoryPropertyFlags (+53 more)
|
||||||
|
|
||||||
|
### Community 1 - "Terminal Renderer & Game Loop"
|
||||||
|
Cohesion: 0.07
|
||||||
|
Nodes (19): CellularAutomaton, Duration, InputHandler, Player, R, TerminalRenderer, Renderer, Game (+11 more)
|
||||||
|
|
||||||
|
### Community 2 - "Graphics Vulkan Renderer"
|
||||||
|
Cohesion: 0.07
|
||||||
|
Nodes (31): ColorInstance, GraphicsRenderer, PushConstants, Arc, Buffer, CommandBuffer, CommandPool, Device (+23 more)
|
||||||
|
|
||||||
|
### Community 3 - "AI Pipe Protocol"
|
||||||
|
Cohesion: 0.12
|
||||||
|
Nodes (31): Command, handle_command(), Response, run_pipe_protocol(), Assertion, AssertionResult, check_assertion(), format_results() (+23 more)
|
||||||
|
|
||||||
|
### Community 4 - "AI Game Session"
|
||||||
|
Cohesion: 0.09
|
||||||
|
Nodes (13): GameSession, Default, ReplayRecorder, AiAction, CellInfo, EntityInfo, Game, GameState (+5 more)
|
||||||
|
|
||||||
|
### Community 5 - "CLI Entry & GPU Mode"
|
||||||
|
Cohesion: 0.15
|
||||||
|
Nodes (20): Cli, dump_view(), GpuRenderer, main(), player_info(), Arc, EntityManager, Game (+12 more)
|
||||||
|
|
||||||
|
### Community 6 - "AI State Export"
|
||||||
|
Cohesion: 0.13
|
||||||
|
Nodes (23): build_game_state(), CellInfo, entity_info(), entity_kind_name(), EntityInfo, GameState, material_from_name(), parse_entity_kind() (+15 more)
|
||||||
|
|
||||||
|
### Community 7 - "Terminal Input Handler"
|
||||||
|
Cohesion: 0.13
|
||||||
|
Nodes (15): Event, JoinHandle, Receiver, Action, HeldKey, HeldState, InputHandler, MaterialBrush (+7 more)
|
||||||
|
|
||||||
|
### Community 8 - "Entity System"
|
||||||
|
Cohesion: 0.15
|
||||||
|
Nodes (9): Constraint, Entity, EntityKind, EntityManager, EntityId, Option, Self, SubBody (+1 more)
|
||||||
|
|
||||||
|
### Community 9 - "Cellular Automaton"
|
||||||
|
Cohesion: 0.29
|
||||||
|
Nodes (4): Grid, MaterialId, Self, CellularAutomaton
|
||||||
|
|
||||||
|
### Community 10 - "Replay System"
|
||||||
|
Cohesion: 0.13
|
||||||
|
Nodes (11): ReplayEvent, ReplayPlayer, ReplayRecorder, ReplayRecording, ReplayEvent, AiAction, GameSession, Result (+3 more)
|
||||||
|
|
||||||
|
### Community 11 - "Edge Case Tests"
|
||||||
|
Cohesion: 0.16
|
||||||
|
Nodes (17): center_camera_on_player(), clear_region_removes_all_materials(), entity_at_right_boundary(), entity_at_world_boundary_stays_in_bounds(), fill_rect_creates_correct_material_count(), find_material_locates_existing(), find_material_returns_none_for_absent(), goblin_has_correct_max_health() (+9 more)
|
||||||
|
|
||||||
|
### Community 12 - "AI Actions & Grid"
|
||||||
|
Cohesion: 0.18
|
||||||
|
Nodes (7): AiAction, Cell, Game, MaterialId, Self, Vec, Grid
|
||||||
|
|
||||||
|
### Community 13 - "Material Physics Tests"
|
||||||
|
Cohesion: 0.22
|
||||||
|
Nodes (17): bone_is_static(), dirt_is_solid(), fire_dies_over_time(), fire_ignites_flesh(), fire_ignites_grass(), fire_ignites_wood(), grass_is_solid(), lava_initial_temp_is_high() (+9 more)
|
||||||
|
|
||||||
|
### Community 14 - "Player Controller"
|
||||||
|
Cohesion: 0.21
|
||||||
|
Nodes (6): Player, Entity, EntityId, EntityManager, Option, Self
|
||||||
|
|
||||||
|
### Community 15 - "Cell & Material Types"
|
||||||
|
Cohesion: 0.17
|
||||||
|
Nodes (4): Self, Cell, MaterialId, rand_u8()
|
||||||
|
|
||||||
|
### Community 16 - "Material Interaction Tests"
|
||||||
|
Cohesion: 0.26
|
||||||
|
Nodes (14): acid_dissolves_dirt(), acid_dissolves_grass(), acid_does_not_dissolve_empty(), fire_does_not_ignite_stone(), fire_does_not_ignite_water(), fire_spreads_through_wood_line(), lava_and_water_produce_both_steam_and_stone(), lava_cools_to_stone_eventually() (+6 more)
|
||||||
|
|
||||||
|
### Community 17 - "Player Control Tests"
|
||||||
|
Cohesion: 0.26
|
||||||
|
Nodes (14): continuous_movement_does_not_fall_through_floor(), jump_goes_up_then_falls_back(), jump_while_airborne_does_nothing(), move_left_changes_x_position(), move_left_then_right_cancels(), move_right_changes_x_position(), player_health_stays_full_without_damage(), player_not_on_ground_while_jumping() (+6 more)
|
||||||
|
|
||||||
|
### Community 18 - "AI Agent Roadmap"
|
||||||
|
Cohesion: 0.18
|
||||||
|
Nodes (14): AiAction, GameSession, pipe render mode, AI pipe protocol (JSON stdin/stdout), Seeded RNG determinism, LLM agent (Ollama/Llama/Qwen), Phase 7: AI Agent Integration, Phase 8: Web Arena & Training Pipeline (+6 more)
|
||||||
|
|
||||||
|
### Community 19 - "Verlet Physics Solver"
|
||||||
|
Cohesion: 0.22
|
||||||
|
Nodes (5): Constraint, SubBody, VerletSolver, MaterialId, Self
|
||||||
|
|
||||||
|
### Community 20 - "Render & Phase Roadmap"
|
||||||
|
Cohesion: 0.15
|
||||||
|
Nodes (11): Chunk system (64x64), Cross-platform support (Win/Linux/macOS), Multi-layer world architecture, Phase 2: World & Exploration, Phase 3: RPG Layer, Phase 4: Render Modes, Phase 4b: Graphics layers (lighting/particles/textures), Phase 5: Content & Polish (+3 more)
|
||||||
|
|
||||||
|
### Community 21 - "Collision Robustness Tests"
|
||||||
|
Cohesion: 0.27
|
||||||
|
Nodes (10): entity_collision_with_dirt_wall(), player_blocked_by_ceiling(), player_blocked_by_left_wall(), player_blocked_by_right_wall(), player_blocked_by_two_walls_both_sides(), player_does_not_stick_to_wall(), player_slides_along_wall(), player_squeezes_through_gap() (+2 more)
|
||||||
|
|
||||||
|
### Community 22 - "Render Mode & UI Roadmap"
|
||||||
|
Cohesion: 0.22
|
||||||
|
Nodes (11): EntityManager, Grid (250x250) source of truth, ascii render mode, graphics render mode, terminal render mode, ASCII renderer (Vulkan glyph atlas), Graphics renderer (Vulkan colored cells), Phase 1.5: UI Layer (+3 more)
|
||||||
|
|
||||||
|
### Community 23 - "Window Input (winit)"
|
||||||
|
Cohesion: 0.20
|
||||||
|
Nodes (7): ElementState, HashSet, PhysicalKey, WindowInput, KeyCode, Option, Self
|
||||||
|
|
||||||
|
### Community 24 - "Determinism Tests"
|
||||||
|
Cohesion: 0.22
|
||||||
|
Nodes (3): determinism_with_spawn_and_damage(), GameSession, setup()
|
||||||
|
|
||||||
|
### Community 25 - "Ragdoll Death Tests"
|
||||||
|
Cohesion: 0.38
|
||||||
|
Nodes (9): corpse_exists_in_world(), damage_reduces_health_progressively(), death_transitions_rigid_to_ragdoll(), player_death_becomes_corpse(), ragdoll_bodies_stay_near_each_other(), ragdoll_falls_after_death(), GameSession, setup() (+1 more)
|
||||||
|
|
||||||
|
### Community 26 - "Grid Collision Resolver"
|
||||||
|
Cohesion: 0.46
|
||||||
|
Nodes (6): apply_liquid_drag(), CollisionResult, resolve_grid_collision(), Grid, Self, SubBody
|
||||||
|
|
||||||
|
### Community 27 - "Material Registry"
|
||||||
|
Cohesion: 0.43
|
||||||
|
Nodes (4): MaterialId, Self, Material, MaterialRegistry
|
||||||
|
|
||||||
|
### Community 28 - "Entity Types & Game Loop"
|
||||||
|
Cohesion: 0.29
|
||||||
|
Nodes (7): cellular entity type, CellularAutomaton, Game::fixed_update(), rigid entity type, Fixed 60Hz timestep, 14 CA Materials, Rigid entities (AABB + slope stepping)
|
||||||
|
|
||||||
|
### Community 29 - "Adaptive Viewport"
|
||||||
|
Cohesion: 0.33
|
||||||
|
Nodes (7): check_resize(), GpuRenderer trait, GraphicsRenderer, run_gpu_mode<R>(), VulkanRenderer, WindowInput, Adaptive viewport
|
||||||
|
|
||||||
|
### Community 30 - "Headless Dump & Combat Plan"
|
||||||
|
Cohesion: 0.33
|
||||||
|
Nodes (6): Player, vector movement convention, Goblin entity (headless dump), Grid ASCII rendering (headless dump), Player entity (headless dump), Phase 1: Combat & Interaction
|
||||||
|
|
||||||
|
### Community 31 - "Entity Damage Tests"
|
||||||
|
Cohesion: 0.52
|
||||||
|
Nodes (6): entity_blocked_by_stone(), entity_dies_becomes_corpse(), entity_on_fire_takes_damage_over_time(), entity_takes_lava_damage(), GameSession, setup_empty()
|
||||||
|
|
||||||
|
### Community 32 - "Entity Movement Tests"
|
||||||
|
Cohesion: 0.48
|
||||||
|
Nodes (5): player_blocked_by_stone_wall(), player_can_move_right(), player_survives_fall(), GameSession, setup_empty()
|
||||||
|
|
||||||
|
### Community 33 - "Lava Physics Tests"
|
||||||
|
Cohesion: 0.52
|
||||||
|
Nodes (6): lava_flows_down(), lava_ignites_grass(), lava_ignites_wood(), lava_plus_water_makes_steam(), GameSession, setup_empty()
|
||||||
|
|
||||||
|
### Community 34 - "Sand Physics Tests"
|
||||||
|
Cohesion: 0.52
|
||||||
|
Nodes (6): GameSession, sand_displaces_water(), sand_does_not_fall_through_stone(), sand_falls_down(), sand_piles_on_stone(), setup_empty()
|
||||||
|
|
||||||
|
### Community 35 - "Acid Physics Tests"
|
||||||
|
Cohesion: 0.60
|
||||||
|
Nodes (5): acid_dissolves_wood(), acid_does_not_dissolve_stone(), acid_flows_down(), GameSession, setup_empty()
|
||||||
|
|
||||||
|
### Community 36 - "Water Physics Tests"
|
||||||
|
Cohesion: 0.60
|
||||||
|
Nodes (5): GameSession, setup_empty(), water_does_not_pass_through_stone_wall(), water_flows_down(), water_spreads_sideways()
|
||||||
|
|
||||||
|
### Community 37 - "Ragdoll Physics Plan"
|
||||||
|
Cohesion: 0.50
|
||||||
|
Nodes (5): Constraint, ragdoll entity type, SubBody, VerletSolver, Ragdoll corpses (Verlet)
|
||||||
|
|
||||||
|
### Community 39 - "Per-Cell Color Plan"
|
||||||
|
Cohesion: 0.67
|
||||||
|
Nodes (4): Cell struct, inline cell colors convention, MaterialRegistry, Per-cell color (reality layer)
|
||||||
|
|
||||||
|
## Knowledge Gaps
|
||||||
|
- **106 isolated node(s):** `String`, `CellInfo`, `Vec`, `EntityInfo`, `ScenarioResult` (+101 more)
|
||||||
|
These have ≤1 connection - possible missing edges or undocumented components.
|
||||||
|
- **3 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||||
|
|
||||||
|
## Suggested Questions
|
||||||
|
_Questions this graph is uniquely positioned to answer:_
|
||||||
|
|
||||||
|
- **Why does `Cell` connect `AI Actions & Grid` to `Cellular Automaton`?**
|
||||||
|
_High betweenness centrality (0.011) - this node is a cross-community bridge._
|
||||||
|
- **Why does `GameSession` connect `AI Game Session` to `AI State Export`?**
|
||||||
|
_High betweenness centrality (0.011) - this node is a cross-community bridge._
|
||||||
|
- **What connects `String`, `CellInfo`, `Vec` to the rest of the system?**
|
||||||
|
_108 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||||
|
- **Should `Vulkan Core Setup` be split into smaller, more focused modules?**
|
||||||
|
_Cohesion score 0.09525899912203688 - nodes in this community are weakly interconnected._
|
||||||
|
- **Should `Terminal Renderer & Game Loop` be split into smaller, more focused modules?**
|
||||||
|
_Cohesion score 0.06956521739130435 - nodes in this community are weakly interconnected._
|
||||||
|
- **Should `Graphics Vulkan Renderer` be split into smaller, more focused modules?**
|
||||||
|
_Cohesion score 0.06543385490753911 - nodes in this community are weakly interconnected._
|
||||||
|
- **Should `AI Pipe Protocol` be split into smaller, more focused modules?**
|
||||||
|
_Cohesion score 0.12063492063492064 - nodes in this community are weakly interconnected._
|
||||||
graphify-out/cache/ast/v0.8.44/045dbbc45414b6bfea5270ecf0f88a68c4897e915a118c9e6a66cde0ddd604a5.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/0a393136c1e69636880e294cb529ffd5d2c446bf946ef8903f5606f48ca821d7.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/0c037c2066a7b634e22f62a3283d517d6e347bbe29e65a0547b252f76acd6349.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/0d9560f4a5114e6db7b2b410045dece5d402cfd2ca22788278b16924ca7f94dc.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/1004493b75aba57ba52f6b4b9a7008cf895520b66cc97ffb107c46eacf290b20.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/1383016c27aed86139990e1c5b1e82145f27689850971634070664b951773b22.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/1e4a9dcbc6242e19c4e3fad6956d1f78459422a65d747eb6d61dbc9d27d8a0ee.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/21ab58c3d4cb7ff279b6de6c4e6547e1cf4759d554e54daa099abdd887512a30.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/2c1b9a0f2b19b554c0d6c91cca6e29346922726c248642443a786c888a0eb84a.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_entity_mod_rs", "label": "mod.rs", "file_type": "code", "source_file": "src/entity/mod.rs", "source_location": "L1"}], "edges": [{"source": "home_emil_desktop_verbatim_src_entity_mod_rs", "target": "entity", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/entity/mod.rs", "source_location": "L4", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_entity_mod_rs", "target": "player", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/entity/mod.rs", "source_location": "L5", "weight": 1.0, "context": "import"}], "raw_calls": []}
|
||||||
graphify-out/cache/ast/v0.8.44/2f2aaec4165990d2bc541fb7299281b706f99e3cbbad27d0ccfaaec7492c5b1d.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/32a7af8ee35b97f6802369b6486fd8e754ce770654c62b777d7a2249d212fae1.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_lib_rs", "label": "lib.rs", "file_type": "code", "source_file": "src/lib.rs", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||||
graphify-out/cache/ast/v0.8.44/33c894de63e7ad6cfec4f4a1d0fc12bc186e222a4d11de24340102459c02f744.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_physics_mod_rs", "label": "mod.rs", "file_type": "code", "source_file": "src/physics/mod.rs", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||||
graphify-out/cache/ast/v0.8.44/33f6f97b825a0495f24606999865a1aee5076417870699500ea54ee3ce40ac1e.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/3524d0a008a9cff9804a055d9c3d3f9c34eab27dabcff76701af9fdeaa8ec43a.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/36112d79800455d9de55dcf66bf6b44f512673c1ece8031e0f9bc51ba522bc98.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/3bb250cfbe2035e04cef321f430809b6a65211d0558e3a422b553cc779fd05cd.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/3e9a58069b81f3c8343b26641d6f8de2c3c15b3a005d072e07251d62e35f0a8e.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/4860cc9adda85a11b339216077e9ab43e270eea741057ee35e9a98ddd4662c2e.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/5070d8053c5bdb1e52d1c877a900f00aef501d6ca02f287b02db551c28a17937.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/544aa8832e4ccd323e2d9e6dc945bf3c6d2d2f27336cd0f887d5a4209a9eaba2.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/5aa277f50d8b55c0a61281f765565496743221d8610897933ab9e6ba74ce1b6a.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/5b6237c87418b65102d3ccf7b48b95bbf17023ebccc95a1dd49949874637b1ef.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/5edac12b81a4be7fbe495d1fd694358f0f2c0fad5a09276a9cb99a014e6f4d84.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/6ea5cbecf29a17fc28e84d2d55250632972b47963eddb90e43cb7a488e64e07b.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/725a669732f71f9cde36a8a52f1011ab6f870e44f1edce16d17899776dd6f737.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/755f912dd9db0bb7ffabc2a3c29b044359b99720f964a1b5c4123ca2fff35361.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/78f62b1306b79536f56e94738682314d676d2eff69e15665f516a98bfbdcefcd.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/7ec222b87142c70e7a1d44a25a2e154ef67533d9a14cba768e126888e42cfbad.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/83ff90991fbc3e9044aef06d4ce98f1783aee5086a8cf5782e09986a72f7e12d.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_world_material_rs", "label": "material.rs", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L1"}, {"id": "world_material_material", "label": "Material", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L4"}, {"id": "materialid", "label": "MaterialId", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L5"}, {"id": "world_material_materialregistry", "label": "MaterialRegistry", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L24"}, {"id": "world_material_materialregistry_new", "label": ".new()", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L29"}, {"id": "self", "label": "Self", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L29"}, {"id": "world_material_materialregistry_get", "label": ".get()", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L260"}, {"id": "world_material_materialregistry_instance", "label": ".instance()", "file_type": "code", "source_file": "src/world/material.rs", "source_location": "L264"}], "edges": [{"source": "home_emil_desktop_verbatim_src_world_material_rs", "target": "materialid", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L1", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_world_material_rs", "target": "world_material_material", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L4", "weight": 1.0}, {"source": "world_material_material", "target": "materialid", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L5", "weight": 1.0, "context": "field"}, {"source": "home_emil_desktop_verbatim_src_world_material_rs", "target": "world_material_materialregistry", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L24", "weight": 1.0}, {"source": "world_material_materialregistry", "target": "world_material_material", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L25", "weight": 1.0, "context": "field"}, {"source": "world_material_materialregistry", "target": "world_material_materialregistry_new", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L29", "weight": 1.0}, {"source": "world_material_materialregistry_new", "target": "self", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L29", "weight": 1.0, "context": "return_type"}, {"source": "world_material_materialregistry", "target": "world_material_materialregistry_get", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L260", "weight": 1.0}, {"source": "world_material_materialregistry_get", "target": "materialid", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L260", "weight": 1.0, "context": "parameter_type"}, {"source": "world_material_materialregistry_get", "target": "world_material_material", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L260", "weight": 1.0, "context": "return_type"}, {"source": "world_material_materialregistry", "target": "world_material_materialregistry_instance", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L264", "weight": 1.0}, {"source": "world_material_materialregistry_instance", "target": "world_material_materialregistry", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L264", "weight": 1.0, "context": "return_type"}, {"source": "world_material_materialregistry_instance", "target": "world_material_materialregistry_new", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "src/world/material.rs", "source_location": "L265", "weight": 1.0}], "raw_calls": [{"caller_nid": "world_material_materialregistry_instance", "callee": "get_or_init", "is_member_call": true, "source_file": "/home/emil/Desktop/Verbatim/src/world/material.rs", "source_location": "L266"}]}
|
||||||
graphify-out/cache/ast/v0.8.44/840bf75ab1b85c2a9352db0ab9466930a1720b02d7af484dddba41b725ea27e7.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/85ba814ce36483d2fc8843f18634b1f59e6b85a8e1862fa0bbfa4db969dc64c9.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/8a4cd674b1e1a549c6b0a4c0e2dfeb00320b5b1d0dcbc08f0c32de6d913c3b5f.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/8a8549a6a5bb485faf650d6adc5fff11e7d102cb9f930ea213531f1e42383c8f.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/8d2d0703840a1a61356a1d3ddc9d6bb0fab9ab3cca56f9b83646e8a093f4107d.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/8e99bda8e2164a9f13944f1df8fed3a42e5005adf6a165d8cf665a6ee052e70d.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/92b06e1e743fa3df4fd5bbfba47aae08c8cd59250fd629a89b9df21b3b75bda0.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/a18f80fe6d27240a60cfd56d1063355b4a1e59115c5788af430d8f81992e0c8b.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/a6ab3244b2e4f733dd66a34b6f091a977eb4a94e24d86fb540a34f1030845e62.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/b243d2d7b4b78794c20e7a790acaaa73ca949868894f25f719dfcad6749a6e33.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/b7a5381e3eb2270e501b281c97df2e7561e166e1e279e4f07472965696361b72.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/b89001186fb568d71ad057ff976c3c83e8294e7c621921b7aa9ac098d96240eb.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_world_mod_rs", "label": "mod.rs", "file_type": "code", "source_file": "src/world/mod.rs", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||||
graphify-out/cache/ast/v0.8.44/b8aa33177db42b285835535f2d401d1de12f1620c5531112d4cc013896cbd7f3.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/bbd2d8dbbbbbd080d6e2555d1e2ae948e73a3ca8c26d41b5575de3c5dcc0a8ee.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/be65af46393cd999c96ae634106a87270c742987b3f4503eaa8bbc3d1aa65528.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_render_window_input_rs", "label": "window_input.rs", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L1"}, {"id": "render_window_input_windowinput", "label": "WindowInput", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L4"}, {"id": "option", "label": "Option", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L13"}, {"id": "hashset", "label": "HashSet", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L15"}, {"id": "keycode", "label": "KeyCode", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L15"}, {"id": "render_window_input_windowinput_new", "label": ".new()", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L19"}, {"id": "self", "label": "Self", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L19"}, {"id": "render_window_input_windowinput_on_key_event", "label": ".on_key_event()", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L29"}, {"id": "physicalkey", "label": "PhysicalKey", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L29"}, {"id": "elementstate", "label": "ElementState", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L29"}, {"id": "render_window_input_windowinput_update", "label": ".update()", "file_type": "code", "source_file": "src/render/window_input.rs", "source_location": "L45"}], "edges": [{"source": "home_emil_desktop_verbatim_src_render_window_input_rs", "target": "hashset", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L1", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_render_window_input_rs", "target": "keyboard", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L2", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_render_window_input_rs", "target": "render_window_input_windowinput", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L4", "weight": 1.0}, {"source": "render_window_input_windowinput", "target": "option", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L13", "weight": 1.0, "context": "field"}, {"source": "render_window_input_windowinput", "target": "hashset", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L15", "weight": 1.0, "context": "field"}, {"source": "render_window_input_windowinput", "target": "keycode", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L15", "weight": 1.0, "context": "generic_arg"}, {"source": "render_window_input_windowinput", "target": "render_window_input_windowinput_new", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L19", "weight": 1.0}, {"source": "render_window_input_windowinput_new", "target": "self", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L19", "weight": 1.0, "context": "return_type"}, {"source": "render_window_input_windowinput", "target": "render_window_input_windowinput_on_key_event", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L29", "weight": 1.0}, {"source": "render_window_input_windowinput_on_key_event", "target": "physicalkey", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L29", "weight": 1.0, "context": "parameter_type"}, {"source": "render_window_input_windowinput_on_key_event", "target": "elementstate", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L29", "weight": 1.0, "context": "parameter_type"}, {"source": "render_window_input_windowinput", "target": "render_window_input_windowinput_update", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/render/window_input.rs", "source_location": "L45", "weight": 1.0}], "raw_calls": []}
|
||||||
graphify-out/cache/ast/v0.8.44/c3273d42f58f9db0a34d2000c572d2c4f18ce38d3f1a2e355e2f71d035f0380c.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/cbbffb0643983e1e760be640e637268ea20d13a04a2240021afc946957e32776.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/d17d3eb2784633ddd404ec8460f64aeb0d7504c6cbd7020de5b496473f0465c1.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/d21f06eaa154cf8920dac06ac565a4c17ac9e78fcc9580bde92e17eb45e8af92.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/db93c1950666d4b33b9fc8e8c52aca39d35493ae61c5e3ac1854d0d5bc3b704b.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
graphify-out/cache/ast/v0.8.44/e695c318e894a8c99e79400b65bb513336bb3e979eb9a819d9870d9dae4ece0d.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/e78cb479a3dba268e610d0f6e4c12e9a9626893ac0c7888a0d6cd64f7bd76a73.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/ecc068c28276959a40628e1a4240204185086de14630739e2536f47b9b2d212f.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_render_mod_rs", "label": "mod.rs", "file_type": "code", "source_file": "src/render/mod.rs", "source_location": "L1"}, {"id": "render_mod_renderer", "label": "Renderer", "file_type": "code", "source_file": "src/render/mod.rs", "source_location": "L9"}], "edges": [{"source": "home_emil_desktop_verbatim_src_render_mod_rs", "target": "entitymanager", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/render/mod.rs", "source_location": "L6", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_render_mod_rs", "target": "grid", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/render/mod.rs", "source_location": "L7", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_render_mod_rs", "target": "render_mod_renderer", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/render/mod.rs", "source_location": "L9", "weight": 1.0}], "raw_calls": []}
|
||||||
graphify-out/cache/ast/v0.8.44/f22ba9e1d92577eee87d4e8454f243ca22e8b718a666344f437ac59b6d03d7c2.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/f3b1806cd23c230ecffce623b96718eba63a57ab7ca50d833d2a767776914a91.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_emil_desktop_verbatim_src_ai_mod_rs", "label": "mod.rs", "file_type": "code", "source_file": "src/ai/mod.rs", "source_location": "L1"}], "edges": [{"source": "home_emil_desktop_verbatim_src_ai_mod_rs", "target": "state", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/ai/mod.rs", "source_location": "L8", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_ai_mod_rs", "target": "aiaction", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/ai/mod.rs", "source_location": "L9", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_ai_mod_rs", "target": "gamesession", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/ai/mod.rs", "source_location": "L10", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_ai_mod_rs", "target": "replay", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/ai/mod.rs", "source_location": "L11", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_ai_mod_rs", "target": "scenario", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/ai/mod.rs", "source_location": "L12", "weight": 1.0, "context": "import"}, {"source": "home_emil_desktop_verbatim_src_ai_mod_rs", "target": "run_pipe_protocol", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "src/ai/mod.rs", "source_location": "L13", "weight": 1.0, "context": "import"}], "raw_calls": []}
|
||||||
graphify-out/cache/ast/v0.8.44/f7ea3b715c5e63353dadd9a81af8a9ba0648d68c701ccadc4abbaab9ca9548d6.json
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [], "edges": [], "skipped": "data json (not a config/manifest)"}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "headless_dump_headless_dump", "label": "headless_dump.txt", "file_type": "document", "source_file": "headless_dump.txt", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "headless_dump_player", "label": "Player entity (headless dump)", "file_type": "concept", "source_file": "headless_dump.txt", "source_location": "line 33", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "headless_dump_goblin", "label": "Goblin entity (headless dump)", "file_type": "concept", "source_file": "headless_dump.txt", "source_location": "line 184", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "headless_dump_grid_render", "label": "Grid ASCII rendering (headless dump)", "file_type": "concept", "source_file": "headless_dump.txt", "source_location": "line 7", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "headless_dump_headless_dump", "target": "headless_dump_player", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "headless_dump.txt", "source_location": "line 33", "weight": 1.0}, {"source": "headless_dump_headless_dump", "target": "headless_dump_goblin", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "headless_dump.txt", "source_location": "line 184", "weight": 1.0}, {"source": "headless_dump_headless_dump", "target": "headless_dump_grid_render", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "headless_dump.txt", "source_location": "line 7", "weight": 1.0}, {"source": "headless_dump_player", "target": "headless_dump_goblin", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "headless_dump.txt", "source_location": "line 184", "weight": 1.0}, {"source": "headless_dump_grid_render", "target": "agents_render_terminal", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "headless_dump.txt", "source_location": "line 7", "weight": 1.0}, {"source": "headless_dump_goblin", "target": "plan_phase1_combat", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "headless_dump.txt", "source_location": "line 184", "weight": 1.0}], "hyperedges": []}
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"date": "2026-06-21T06:52:56.684475+00:00",
|
||||||
|
"input_tokens": 0,
|
||||||
|
"output_tokens": 0,
|
||||||
|
"files": 58
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_input_tokens": 0,
|
||||||
|
"total_output_tokens": 0
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
+20137
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,292 @@
|
|||||||
|
{
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/acid_dissolves_wood.json": {
|
||||||
|
"mtime": 1781970764.6442819,
|
||||||
|
"ast_hash": "8d56cc1848be6548decbe1e329491b4e",
|
||||||
|
"semantic_hash": "8d56cc1848be6548decbe1e329491b4e"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/acid_eats_through_wall.json": {
|
||||||
|
"mtime": 1781984503.8460147,
|
||||||
|
"ast_hash": "2beb1ff35d7487a83fab52c75904d73e",
|
||||||
|
"semantic_hash": "2beb1ff35d7487a83fab52c75904d73e"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/entity_burns_in_lava.json": {
|
||||||
|
"mtime": 1781970726.5528774,
|
||||||
|
"ast_hash": "75f62c9cf20a5c144f6f389d7b1d5f5a",
|
||||||
|
"semantic_hash": "75f62c9cf20a5c144f6f389d7b1d5f5a"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/entity_survives_fall.json": {
|
||||||
|
"mtime": 1781983490.8671792,
|
||||||
|
"ast_hash": "4cc7a6f511896c0c5a1ab614d899fa2d",
|
||||||
|
"semantic_hash": "4cc7a6f511896c0c5a1ab614d899fa2d"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/fire_chain_wood.json": {
|
||||||
|
"mtime": 1781983468.9059443,
|
||||||
|
"ast_hash": "14b91384dff483d49dddc9d99b5041a4",
|
||||||
|
"semantic_hash": "14b91384dff483d49dddc9d99b5041a4"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/fire_spreads_through_grass.json": {
|
||||||
|
"mtime": 1781970725.561867,
|
||||||
|
"ast_hash": "a6f1b65d9a660266fd81ab4c0570fa15",
|
||||||
|
"semantic_hash": "a6f1b65d9a660266fd81ab4c0570fa15"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/lava_ignites_wood.json": {
|
||||||
|
"mtime": 1781970722.357833,
|
||||||
|
"ast_hash": "3c3975c955f54dc092000d2b8cbab980",
|
||||||
|
"semantic_hash": "3c3975c955f54dc092000d2b8cbab980"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/lava_plus_water_makes_steam.json": {
|
||||||
|
"mtime": 1781984425.8851807,
|
||||||
|
"ast_hash": "9deb9ec56c2d0f581874aa9d51be1438",
|
||||||
|
"semantic_hash": "9deb9ec56c2d0f581874aa9d51be1438"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/lava_pool_interaction.json": {
|
||||||
|
"mtime": 1781984476.6377237,
|
||||||
|
"ast_hash": "cab0da83d6903a07ae1054e710f9d108",
|
||||||
|
"semantic_hash": "cab0da83d6903a07ae1054e710f9d108"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/player_falls_and_lands.json": {
|
||||||
|
"mtime": 1781970725.561867,
|
||||||
|
"ast_hash": "c4264a79dea6301828ba05a892ea513e",
|
||||||
|
"semantic_hash": "c4264a79dea6301828ba05a892ea513e"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/sand_buries_wood.json": {
|
||||||
|
"mtime": 1781983484.682113,
|
||||||
|
"ast_hash": "1220b84d088ec7a35777416ffcb7ad16",
|
||||||
|
"semantic_hash": "1220b84d088ec7a35777416ffcb7ad16"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/sand_falls_down.json": {
|
||||||
|
"mtime": 1781970712.2597258,
|
||||||
|
"ast_hash": "30baf2c5ef87bc287a16e99eb6bad98f",
|
||||||
|
"semantic_hash": "30baf2c5ef87bc287a16e99eb6bad98f"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/steam_condenses.json": {
|
||||||
|
"mtime": 1781983498.8702648,
|
||||||
|
"ast_hash": "e59d6d0f5c9688bc0fcf88b63882d7f0",
|
||||||
|
"semantic_hash": "e59d6d0f5c9688bc0fcf88b63882d7f0"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/scenarios/water_flows_sideways.json": {
|
||||||
|
"mtime": 1781970716.227768,
|
||||||
|
"ast_hash": "2aed38e5196f3331f69f7b2c8272fe9d",
|
||||||
|
"semantic_hash": "2aed38e5196f3331f69f7b2c8272fe9d"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/ai/action.rs": {
|
||||||
|
"mtime": 1781982011.0213413,
|
||||||
|
"ast_hash": "c514af97d56e023db3e14776cebd742b",
|
||||||
|
"semantic_hash": "c514af97d56e023db3e14776cebd742b"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/ai/mod.rs": {
|
||||||
|
"mtime": 1781970069.3378994,
|
||||||
|
"ast_hash": "37cfd173334195bb77ce77032e734475",
|
||||||
|
"semantic_hash": "37cfd173334195bb77ce77032e734475"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/ai/protocol.rs": {
|
||||||
|
"mtime": 1781982011.0213413,
|
||||||
|
"ast_hash": "35c87a0bc8eea05d7973c0646723f26e",
|
||||||
|
"semantic_hash": "35c87a0bc8eea05d7973c0646723f26e"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/ai/replay.rs": {
|
||||||
|
"mtime": 1781994698.517593,
|
||||||
|
"ast_hash": "bb610684494750685093b6745cbd3c95",
|
||||||
|
"semantic_hash": "bb610684494750685093b6745cbd3c95"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/ai/scenario.rs": {
|
||||||
|
"mtime": 1781982011.0213413,
|
||||||
|
"ast_hash": "1ed4faf1ab6157642642e77372821df2",
|
||||||
|
"semantic_hash": "1ed4faf1ab6157642642e77372821df2"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/ai/session.rs": {
|
||||||
|
"mtime": 1781994682.1954203,
|
||||||
|
"ast_hash": "299982f384ea4ee845e16462aa5c55ce",
|
||||||
|
"semantic_hash": "299982f384ea4ee845e16462aa5c55ce"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/ai/state.rs": {
|
||||||
|
"mtime": 1781994883.4095483,
|
||||||
|
"ast_hash": "5b25a5fffc6be4182745780e04e40614",
|
||||||
|
"semantic_hash": "5b25a5fffc6be4182745780e04e40614"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/entity/entity.rs": {
|
||||||
|
"mtime": 1781994535.1578653,
|
||||||
|
"ast_hash": "dc597c2796cd69c6703d50be701ce9f0",
|
||||||
|
"semantic_hash": "dc597c2796cd69c6703d50be701ce9f0"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/entity/mod.rs": {
|
||||||
|
"mtime": 1781994733.5389633,
|
||||||
|
"ast_hash": "d720a8686f72b3f739a71acb1db16f18",
|
||||||
|
"semantic_hash": "d720a8686f72b3f739a71acb1db16f18"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/entity/player.rs": {
|
||||||
|
"mtime": 1781994571.4262488,
|
||||||
|
"ast_hash": "ddfd3ca0846c649df864ae44ff1dc64c",
|
||||||
|
"semantic_hash": "ddfd3ca0846c649df864ae44ff1dc64c"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/game.rs": {
|
||||||
|
"mtime": 1781994816.6048417,
|
||||||
|
"ast_hash": "7148e19d75808d22d6581639a8d5c311",
|
||||||
|
"semantic_hash": "7148e19d75808d22d6581639a8d5c311"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/input.rs": {
|
||||||
|
"mtime": 1781994775.8534107,
|
||||||
|
"ast_hash": "70ec1ff16bf13b3649f27bea9a3891c8",
|
||||||
|
"semantic_hash": "70ec1ff16bf13b3649f27bea9a3891c8"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/lib.rs": {
|
||||||
|
"mtime": 1781970270.862039,
|
||||||
|
"ast_hash": "abe33261862db85f4f4007a98efe1720",
|
||||||
|
"semantic_hash": "abe33261862db85f4f4007a98efe1720"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/main.rs": {
|
||||||
|
"mtime": 1781994426.1417122,
|
||||||
|
"ast_hash": "f8186418f5cfccdc11af1976c10d994f",
|
||||||
|
"semantic_hash": "f8186418f5cfccdc11af1976c10d994f"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/physics/collision.rs": {
|
||||||
|
"mtime": 1781969161.8692644,
|
||||||
|
"ast_hash": "bb0015e3335e47d8b25f3fa0a25a9afa",
|
||||||
|
"semantic_hash": "bb0015e3335e47d8b25f3fa0a25a9afa"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/physics/mod.rs": {
|
||||||
|
"mtime": 1781994728.4279091,
|
||||||
|
"ast_hash": "b6cfc7b3d47ddf5dfe4b55385b1aeb0e",
|
||||||
|
"semantic_hash": "b6cfc7b3d47ddf5dfe4b55385b1aeb0e"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/physics/verlet.rs": {
|
||||||
|
"mtime": 1781994612.3436816,
|
||||||
|
"ast_hash": "cdb55409206655f6826201b3a25d859f",
|
||||||
|
"semantic_hash": "cdb55409206655f6826201b3a25d859f"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/render/graphics.rs": {
|
||||||
|
"mtime": 1781994837.8480663,
|
||||||
|
"ast_hash": "c0f8cc8af597d07af099e307622b4f2b",
|
||||||
|
"semantic_hash": "c0f8cc8af597d07af099e307622b4f2b"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/render/mod.rs": {
|
||||||
|
"mtime": 1781992655.9960363,
|
||||||
|
"ast_hash": "1390b4f260548f51898abeaefa44c0d7",
|
||||||
|
"semantic_hash": "1390b4f260548f51898abeaefa44c0d7"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/render/terminal.rs": {
|
||||||
|
"mtime": 1781994877.423485,
|
||||||
|
"ast_hash": "e9eb6b706e04619794e5567b7ae71425",
|
||||||
|
"semantic_hash": "e9eb6b706e04619794e5567b7ae71425"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/render/vulkan.rs": {
|
||||||
|
"mtime": 1781994804.0007086,
|
||||||
|
"ast_hash": "d94730a5b91d78bb5271b7d18123fb5f",
|
||||||
|
"semantic_hash": "d94730a5b91d78bb5271b7d18123fb5f"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/render/window_input.rs": {
|
||||||
|
"mtime": 1781994633.7179077,
|
||||||
|
"ast_hash": "e8d2a0128959ce134a3e440e7fdef8cf",
|
||||||
|
"semantic_hash": "e8d2a0128959ce134a3e440e7fdef8cf"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/world/cell.rs": {
|
||||||
|
"mtime": 1781994439.0328486,
|
||||||
|
"ast_hash": "65f721a9878492ed06b059d605630c88",
|
||||||
|
"semantic_hash": "65f721a9878492ed06b059d605630c88"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/world/cellular.rs": {
|
||||||
|
"mtime": 1781994620.518768,
|
||||||
|
"ast_hash": "4299c4f6dffd685c4cff62d6da00962f",
|
||||||
|
"semantic_hash": "4299c4f6dffd685c4cff62d6da00962f"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/world/grid.rs": {
|
||||||
|
"mtime": 1781994901.0097344,
|
||||||
|
"ast_hash": "7e28468cb7d0e44dd95c663c45b523b3",
|
||||||
|
"semantic_hash": "7e28468cb7d0e44dd95c663c45b523b3"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/world/material.rs": {
|
||||||
|
"mtime": 1781994717.9467983,
|
||||||
|
"ast_hash": "7f70daf6658c7240dc576ca875dbdad0",
|
||||||
|
"semantic_hash": "7f70daf6658c7240dc576ca875dbdad0"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/src/world/mod.rs": {
|
||||||
|
"mtime": 1781994722.7638493,
|
||||||
|
"ast_hash": "72a8eea3bfe44a1ff11a4c69709d414e",
|
||||||
|
"semantic_hash": "72a8eea3bfe44a1ff11a4c69709d414e"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/collision_robust.rs": {
|
||||||
|
"mtime": 1781984005.8506877,
|
||||||
|
"ast_hash": "aa42931beb7fc8c329f8ac1041a3c6dd",
|
||||||
|
"semantic_hash": "aa42931beb7fc8c329f8ac1041a3c6dd"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/determinism.rs": {
|
||||||
|
"mtime": 1781983582.462159,
|
||||||
|
"ast_hash": "22197294f9d488ea47da4c528d2748f5",
|
||||||
|
"semantic_hash": "22197294f9d488ea47da4c528d2748f5"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/edge_cases.rs": {
|
||||||
|
"mtime": 1781994760.8232517,
|
||||||
|
"ast_hash": "161c3c3c243335166e3bbb568b2c74a4",
|
||||||
|
"semantic_hash": "161c3c3c243335166e3bbb568b2c74a4"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/entity_damage.rs": {
|
||||||
|
"mtime": 1781980721.7435043,
|
||||||
|
"ast_hash": "2deee58dcc1b6b44e8d25a48c0fc5897",
|
||||||
|
"semantic_hash": "2deee58dcc1b6b44e8d25a48c0fc5897"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/entity_movement.rs": {
|
||||||
|
"mtime": 1781981346.368212,
|
||||||
|
"ast_hash": "049056e445056bf6c4b0e2a70c187fb1",
|
||||||
|
"semantic_hash": "049056e445056bf6c4b0e2a70c187fb1"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/integration.rs": {
|
||||||
|
"mtime": 1781983295.271087,
|
||||||
|
"ast_hash": "8db0aae4fbd95fb1effd18bb8560f953",
|
||||||
|
"semantic_hash": "8db0aae4fbd95fb1effd18bb8560f953"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/physics_acid.rs": {
|
||||||
|
"mtime": 1781970221.685517,
|
||||||
|
"ast_hash": "e6034490a9607deeadce03505cadf731",
|
||||||
|
"semantic_hash": "e6034490a9607deeadce03505cadf731"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/physics_interactions.rs": {
|
||||||
|
"mtime": 1781983882.030363,
|
||||||
|
"ast_hash": "38b73ebc6c62cfefb20506db6dd1072d",
|
||||||
|
"semantic_hash": "38b73ebc6c62cfefb20506db6dd1072d"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/physics_lava.rs": {
|
||||||
|
"mtime": 1781980754.4328554,
|
||||||
|
"ast_hash": "c31c44a9f63bf8b6f1df51737f1a2de9",
|
||||||
|
"semantic_hash": "c31c44a9f63bf8b6f1df51737f1a2de9"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/physics_materials.rs": {
|
||||||
|
"mtime": 1781983693.2113435,
|
||||||
|
"ast_hash": "ef6d9d77564f4c02745639ec5807d7db",
|
||||||
|
"semantic_hash": "ef6d9d77564f4c02745639ec5807d7db"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/physics_sand.rs": {
|
||||||
|
"mtime": 1781983289.756028,
|
||||||
|
"ast_hash": "4b799fe61ebaa00d14c570d9284a37ec",
|
||||||
|
"semantic_hash": "4b799fe61ebaa00d14c570d9284a37ec"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/physics_water.rs": {
|
||||||
|
"mtime": 1781970629.040842,
|
||||||
|
"ast_hash": "a7141937d2e90d6cc16a6afef026bb1e",
|
||||||
|
"semantic_hash": "a7141937d2e90d6cc16a6afef026bb1e"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/player_controls.rs": {
|
||||||
|
"mtime": 1781984330.918165,
|
||||||
|
"ast_hash": "da75dda146361ea0e23ebd11f554fdba",
|
||||||
|
"semantic_hash": "da75dda146361ea0e23ebd11f554fdba"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/tests/ragdoll_death.rs": {
|
||||||
|
"mtime": 1781994739.1590228,
|
||||||
|
"ast_hash": "c4dfb537ecc663fbb2444de321e05385",
|
||||||
|
"semantic_hash": "c4dfb537ecc663fbb2444de321e05385"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/AGENTS.md": {
|
||||||
|
"mtime": 1781995334.9053233,
|
||||||
|
"ast_hash": "c301fc82f1fa9473c0354454b9b5ad55",
|
||||||
|
"semantic_hash": "c301fc82f1fa9473c0354454b9b5ad55"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/PLAN.md": {
|
||||||
|
"mtime": 1781995156.2924342,
|
||||||
|
"ast_hash": "cb55659d25cbbb523394cc0c383bff5a",
|
||||||
|
"semantic_hash": "cb55659d25cbbb523394cc0c383bff5a"
|
||||||
|
},
|
||||||
|
"/home/emil/Desktop/Verbatim/headless_dump.txt": {
|
||||||
|
"mtime": 1781989911.9880815,
|
||||||
|
"ast_hash": "1ab2647a155a1eed5d05b7292a29b63e",
|
||||||
|
"semantic_hash": "1ab2647a155a1eed5d05b7292a29b63e"
|
||||||
|
}
|
||||||
|
}
|
||||||
+129
-40
@@ -1,18 +1,21 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
use verbatim::ai;
|
||||||
use verbatim::game::Game;
|
use verbatim::game::Game;
|
||||||
use verbatim::render::terminal::TerminalRenderer;
|
use verbatim::render::terminal::TerminalRenderer;
|
||||||
use verbatim::render::window_input::WindowInput;
|
use verbatim::render::window_input::WindowInput;
|
||||||
use verbatim::world::cell::MaterialId;
|
use verbatim::world::cell::MaterialId;
|
||||||
use verbatim::ai;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
use winit::event_loop::{EventLoop, ControlFlow};
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(name = "verbatim", about = "ASCII physics RPG - Noita meets Caves of Qud")]
|
#[command(
|
||||||
|
name = "verbatim",
|
||||||
|
about = "ASCII physics RPG - Noita meets Caves of Qud"
|
||||||
|
)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
#[arg(long, default_value = "ascii")]
|
#[arg(long, default_value = "ascii")]
|
||||||
mode: String,
|
mode: String,
|
||||||
@@ -31,8 +34,16 @@ struct Cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait GpuRenderer {
|
trait GpuRenderer {
|
||||||
fn new(window: Arc<Window>) -> Result<Self, String> where Self: Sized;
|
fn new(window: Arc<Window>) -> Result<Self, String>
|
||||||
fn render(&mut self, grid: &verbatim::world::grid::Grid, entities: &verbatim::entity::EntityManager, cam_x: i32, cam_y: i32);
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn render(
|
||||||
|
&mut self,
|
||||||
|
grid: &verbatim::world::grid::Grid,
|
||||||
|
entities: &verbatim::entity::EntityManager,
|
||||||
|
cam_x: i32,
|
||||||
|
cam_y: i32,
|
||||||
|
);
|
||||||
fn grid_w(&self) -> usize;
|
fn grid_w(&self) -> usize;
|
||||||
fn grid_h(&self) -> usize;
|
fn grid_h(&self) -> usize;
|
||||||
}
|
}
|
||||||
@@ -41,22 +52,42 @@ impl GpuRenderer for verbatim::render::vulkan::VulkanRenderer {
|
|||||||
fn new(window: Arc<Window>) -> Result<Self, String> {
|
fn new(window: Arc<Window>) -> Result<Self, String> {
|
||||||
verbatim::render::vulkan::VulkanRenderer::new(window)
|
verbatim::render::vulkan::VulkanRenderer::new(window)
|
||||||
}
|
}
|
||||||
fn render(&mut self, grid: &verbatim::world::grid::Grid, entities: &verbatim::entity::EntityManager, cam_x: i32, cam_y: i32) {
|
fn render(
|
||||||
|
&mut self,
|
||||||
|
grid: &verbatim::world::grid::Grid,
|
||||||
|
entities: &verbatim::entity::EntityManager,
|
||||||
|
cam_x: i32,
|
||||||
|
cam_y: i32,
|
||||||
|
) {
|
||||||
verbatim::render::vulkan::VulkanRenderer::render(self, grid, entities, cam_x, cam_y)
|
verbatim::render::vulkan::VulkanRenderer::render(self, grid, entities, cam_x, cam_y)
|
||||||
}
|
}
|
||||||
fn grid_w(&self) -> usize { verbatim::render::vulkan::VulkanRenderer::grid_w(self) }
|
fn grid_w(&self) -> usize {
|
||||||
fn grid_h(&self) -> usize { verbatim::render::vulkan::VulkanRenderer::grid_h(self) }
|
verbatim::render::vulkan::VulkanRenderer::grid_w(self)
|
||||||
|
}
|
||||||
|
fn grid_h(&self) -> usize {
|
||||||
|
verbatim::render::vulkan::VulkanRenderer::grid_h(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GpuRenderer for verbatim::render::graphics::GraphicsRenderer {
|
impl GpuRenderer for verbatim::render::graphics::GraphicsRenderer {
|
||||||
fn new(window: Arc<Window>) -> Result<Self, String> {
|
fn new(window: Arc<Window>) -> Result<Self, String> {
|
||||||
verbatim::render::graphics::GraphicsRenderer::new(window)
|
verbatim::render::graphics::GraphicsRenderer::new(window)
|
||||||
}
|
}
|
||||||
fn render(&mut self, grid: &verbatim::world::grid::Grid, entities: &verbatim::entity::EntityManager, cam_x: i32, cam_y: i32) {
|
fn render(
|
||||||
|
&mut self,
|
||||||
|
grid: &verbatim::world::grid::Grid,
|
||||||
|
entities: &verbatim::entity::EntityManager,
|
||||||
|
cam_x: i32,
|
||||||
|
cam_y: i32,
|
||||||
|
) {
|
||||||
verbatim::render::graphics::GraphicsRenderer::render(self, grid, entities, cam_x, cam_y)
|
verbatim::render::graphics::GraphicsRenderer::render(self, grid, entities, cam_x, cam_y)
|
||||||
}
|
}
|
||||||
fn grid_w(&self) -> usize { verbatim::render::graphics::GraphicsRenderer::grid_w(self) }
|
fn grid_w(&self) -> usize {
|
||||||
fn grid_h(&self) -> usize { verbatim::render::graphics::GraphicsRenderer::grid_h(self) }
|
verbatim::render::graphics::GraphicsRenderer::grid_w(self)
|
||||||
|
}
|
||||||
|
fn grid_h(&self) -> usize {
|
||||||
|
verbatim::render::graphics::GraphicsRenderer::grid_h(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -103,7 +134,10 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Unknown mode: {}. Use terminal, ascii, graphics, pipe, test, replay, or headless.", cli.mode);
|
eprintln!(
|
||||||
|
"Unknown mode: {}. Use terminal, ascii, graphics, pipe, test, replay, or headless.",
|
||||||
|
cli.mode
|
||||||
|
);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,11 +145,13 @@ fn main() {
|
|||||||
|
|
||||||
fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
||||||
let event_loop = EventLoop::new().expect("Failed to create event loop");
|
let event_loop = EventLoop::new().expect("Failed to create event loop");
|
||||||
let window = event_loop.create_window(
|
let window = event_loop
|
||||||
|
.create_window(
|
||||||
Window::default_attributes()
|
Window::default_attributes()
|
||||||
.with_title(title)
|
.with_title(title)
|
||||||
.with_inner_size(winit::dpi::LogicalSize::new(160 * 16, 50 * 16))
|
.with_inner_size(winit::dpi::LogicalSize::new(160 * 10, 50 * 10)),
|
||||||
).expect("Failed to create window");
|
)
|
||||||
|
.expect("Failed to create window");
|
||||||
let window = Arc::new(window);
|
let window = Arc::new(window);
|
||||||
|
|
||||||
let mut renderer = match R::new(Arc::clone(&window)) {
|
let mut renderer = match R::new(Arc::clone(&window)) {
|
||||||
@@ -140,22 +176,23 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
|||||||
let mut accumulator = Duration::ZERO;
|
let mut accumulator = Duration::ZERO;
|
||||||
let mut running = true;
|
let mut running = true;
|
||||||
|
|
||||||
event_loop.run(|event, ctrl| {
|
event_loop
|
||||||
|
.run(|event, ctrl| {
|
||||||
ctrl.set_control_flow(ControlFlow::Poll);
|
ctrl.set_control_flow(ControlFlow::Poll);
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { event, .. } => {
|
Event::WindowEvent { event, .. } => match event {
|
||||||
match event {
|
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
running = false;
|
running = false;
|
||||||
ctrl.exit();
|
ctrl.exit();
|
||||||
}
|
}
|
||||||
WindowEvent::KeyboardInput { event: key_event, .. } => {
|
WindowEvent::KeyboardInput {
|
||||||
|
event: key_event, ..
|
||||||
|
} => {
|
||||||
input.on_key_event(key_event.physical_key, key_event.state);
|
input.on_key_event(key_event.physical_key, key_event.state);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
Event::AboutToWait => {
|
Event::AboutToWait => {
|
||||||
if !running {
|
if !running {
|
||||||
ctrl.exit();
|
ctrl.exit();
|
||||||
@@ -198,10 +235,18 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
|||||||
game.player.stop_horizontal(&mut game.entities);
|
game.player.stop_horizontal(&mut game.entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.cam_left { game.cam_x -= 3; }
|
if input.cam_left {
|
||||||
if input.cam_right { game.cam_x += 3; }
|
game.cam_x -= 3;
|
||||||
if input.cam_up { game.cam_y -= 3; }
|
}
|
||||||
if input.cam_down { game.cam_y += 3; }
|
if input.cam_right {
|
||||||
|
game.cam_x += 3;
|
||||||
|
}
|
||||||
|
if input.cam_up {
|
||||||
|
game.cam_y -= 3;
|
||||||
|
}
|
||||||
|
if input.cam_down {
|
||||||
|
game.cam_y += 3;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(brush_id) = input.paint {
|
if let Some(brush_id) = input.paint {
|
||||||
let mat = match brush_id {
|
let mat = match brush_id {
|
||||||
@@ -225,7 +270,11 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
|||||||
for dx in -r..=r {
|
for dx in -r..=r {
|
||||||
if dx * dx + dy * dy <= r * r + 1 {
|
if dx * dx + dy * dy <= r * r + 1 {
|
||||||
if mat == MaterialId::Empty {
|
if mat == MaterialId::Empty {
|
||||||
game.grid.set(cx + dx, cy + dy, verbatim::world::cell::Cell::empty());
|
game.grid.set(
|
||||||
|
cx + dx,
|
||||||
|
cy + dy,
|
||||||
|
verbatim::world::cell::Cell::empty(),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
game.grid.set_material(cx + dx, cy + dy, mat);
|
game.grid.set_material(cx + dx, cy + dy, mat);
|
||||||
}
|
}
|
||||||
@@ -242,7 +291,8 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}).expect("event loop error");
|
})
|
||||||
|
.expect("event loop error");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_test_mode(cli: &Cli) {
|
fn run_test_mode(cli: &Cli) {
|
||||||
@@ -292,8 +342,10 @@ fn run_replay_mode(cli: &Cli) {
|
|||||||
println!("=== Replay: {} events ===", player.recording().events.len());
|
println!("=== Replay: {} events ===", player.recording().events.len());
|
||||||
println!("Final tick: {}", state.tick);
|
println!("Final tick: {}", state.tick);
|
||||||
if let Some(ref p) = state.player {
|
if let Some(ref p) = state.player {
|
||||||
println!("Player: {} hp={:.1}/{:.1} pos=({:.1},{:.1}) alive={}",
|
println!(
|
||||||
p.kind, p.health, p.max_health, p.pos[0], p.pos[1], p.alive);
|
"Player: {} hp={:.1}/{:.1} pos=({:.1},{:.1}) alive={}",
|
||||||
|
p.kind, p.health, p.max_health, p.pos[0], p.pos[1], p.alive
|
||||||
|
);
|
||||||
}
|
}
|
||||||
println!("Entities: {}", state.entities.len());
|
println!("Entities: {}", state.entities.len());
|
||||||
println!("\nFinal view:\n{}", state.view);
|
println!("\nFinal view:\n{}", state.view);
|
||||||
@@ -314,8 +366,14 @@ fn run_headless(ticks: u32) {
|
|||||||
let cam_y = py as i32 - 12;
|
let cam_y = py as i32 - 12;
|
||||||
|
|
||||||
let mut log = String::new();
|
let mut log = String::new();
|
||||||
log.push_str(&format!("=== Verbatim Headless Run: {} ticks ===\n\n", ticks));
|
log.push_str(&format!(
|
||||||
log.push_str(&format!("World: {}x{}\n", game.grid.width, game.grid.height));
|
"=== Verbatim Headless Run: {} ticks ===\n\n",
|
||||||
|
ticks
|
||||||
|
));
|
||||||
|
log.push_str(&format!(
|
||||||
|
"World: {}x{}\n",
|
||||||
|
game.grid.width, game.grid.height
|
||||||
|
));
|
||||||
log.push_str(&format!("Player start: ({:.1}, {:.1})\n", px, py));
|
log.push_str(&format!("Player start: ({:.1}, {:.1})\n", px, py));
|
||||||
log.push_str(&format!("Camera: ({}, {})\n\n", cam_x, cam_y));
|
log.push_str(&format!("Camera: ({}, {})\n\n", cam_x, cam_y));
|
||||||
|
|
||||||
@@ -339,9 +397,19 @@ fn run_headless(ticks: u32) {
|
|||||||
log.push_str(&format!("Player: {:?}\n", player_info(&game)));
|
log.push_str(&format!("Player: {:?}\n", player_info(&game)));
|
||||||
log.push_str(&format!("Entities: {}\n", game.entities.all().len()));
|
log.push_str(&format!("Entities: {}\n", game.entities.all().len()));
|
||||||
|
|
||||||
let alive: Vec<_> = game.entities.all().iter()
|
let alive: Vec<_> = game
|
||||||
|
.entities
|
||||||
|
.all()
|
||||||
|
.iter()
|
||||||
.filter(|e| e.alive)
|
.filter(|e| e.alive)
|
||||||
.map(|e| format!("{}(hp={:.0}, pos={:?})", ai::entity_kind_name(e.kind), e.health, e.center()))
|
.map(|e| {
|
||||||
|
format!(
|
||||||
|
"{}(hp={:.0}, pos={:?})",
|
||||||
|
ai::entity_kind_name(e.kind),
|
||||||
|
e.health,
|
||||||
|
e.center()
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
log.push_str(&format!("Alive entities: {}\n\n", alive.join(", ")));
|
log.push_str(&format!("Alive entities: {}\n\n", alive.join(", ")));
|
||||||
}
|
}
|
||||||
@@ -349,16 +417,27 @@ fn run_headless(ticks: u32) {
|
|||||||
|
|
||||||
let mut f = std::fs::File::create("headless_dump.txt").expect("Cannot create dump file");
|
let mut f = std::fs::File::create("headless_dump.txt").expect("Cannot create dump file");
|
||||||
f.write_all(log.as_bytes()).expect("Cannot write dump");
|
f.write_all(log.as_bytes()).expect("Cannot write dump");
|
||||||
eprintln!("Headless run complete: {} ticks, dump written to headless_dump.txt", ticks);
|
eprintln!(
|
||||||
|
"Headless run complete: {} ticks, dump written to headless_dump.txt",
|
||||||
|
ticks
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_view(grid: &verbatim::world::grid::Grid, entities: &verbatim::entity::EntityManager, cam_x: i32, cam_y: i32, vw: usize, vh: usize) -> String {
|
fn dump_view(
|
||||||
|
grid: &verbatim::world::grid::Grid,
|
||||||
|
entities: &verbatim::entity::EntityManager,
|
||||||
|
cam_x: i32,
|
||||||
|
cam_y: i32,
|
||||||
|
vw: usize,
|
||||||
|
vh: usize,
|
||||||
|
) -> String {
|
||||||
ai::render_view(grid, entities, cam_x, cam_y, vw, vh)
|
ai::render_view(grid, entities, cam_x, cam_y, vw, vh)
|
||||||
.lines()
|
.lines()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, line)| format!("{:2}{}", (cam_y + i as i32) % 100, line))
|
.map(|(i, line)| format!("{:2}{}", (cam_y + i as i32) % 100, line))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n") + "\n"
|
.join("\n")
|
||||||
|
+ "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn player_info(game: &Game) -> String {
|
fn player_info(game: &Game) -> String {
|
||||||
@@ -367,7 +446,17 @@ fn player_info(game: &Game) -> String {
|
|||||||
let body_count = e.bodies.iter().filter(|b| b.alive).count();
|
let body_count = e.bodies.iter().filter(|b| b.alive).count();
|
||||||
let on_fire = e.on_fire;
|
let on_fire = e.on_fire;
|
||||||
let kind = ai::entity_kind_name(e.kind);
|
let kind = ai::entity_kind_name(e.kind);
|
||||||
format!("{} hp={:.1}/{:.1} pos=({:.1},{:.1}) bodies={}/{} on_fire={}", kind, e.health, e.max_health, cx, cy, body_count, e.bodies.len(), on_fire)
|
format!(
|
||||||
|
"{} hp={:.1}/{:.1} pos=({:.1},{:.1}) bodies={}/{} on_fire={}",
|
||||||
|
kind,
|
||||||
|
e.health,
|
||||||
|
e.max_health,
|
||||||
|
cx,
|
||||||
|
cy,
|
||||||
|
body_count,
|
||||||
|
e.bodies.len(),
|
||||||
|
on_fire
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
"None".to_string()
|
"None".to_string()
|
||||||
}
|
}
|
||||||
|
|||||||
+506
-154
@@ -2,12 +2,12 @@ use ash::vk;
|
|||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::entity::{EntityManager, EntityKind};
|
use crate::entity::{EntityKind, EntityManager};
|
||||||
use crate::world::cell::MaterialId;
|
use crate::world::cell::MaterialId;
|
||||||
use crate::world::grid::Grid;
|
use crate::world::grid::Grid;
|
||||||
|
|
||||||
const CHAR_W: u32 = 16;
|
const CHAR_W: u32 = 10;
|
||||||
const CHAR_H: u32 = 16;
|
const CHAR_H: u32 = 10;
|
||||||
const MAX_FRAMES: usize = 2;
|
const MAX_FRAMES: usize = 2;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -75,7 +75,9 @@ impl GraphicsRenderer {
|
|||||||
let entry = unsafe { ash::Entry::load().map_err(|e| format!("Vulkan load: {e}"))? };
|
let entry = unsafe { ash::Entry::load().map_err(|e| format!("Vulkan load: {e}"))? };
|
||||||
|
|
||||||
use raw_window_handle::HasDisplayHandle;
|
use raw_window_handle::HasDisplayHandle;
|
||||||
let dh = window.display_handle().map_err(|e| format!("display_handle: {e}"))?;
|
let dh = window
|
||||||
|
.display_handle()
|
||||||
|
.map_err(|e| format!("display_handle: {e}"))?;
|
||||||
let required_exts = ash_window::enumerate_required_extensions(dh.as_raw())
|
let required_exts = ash_window::enumerate_required_extensions(dh.as_raw())
|
||||||
.map_err(|e| format!("enumerate_required_extensions: {e:?}"))?;
|
.map_err(|e| format!("enumerate_required_extensions: {e:?}"))?;
|
||||||
|
|
||||||
@@ -84,15 +86,20 @@ impl GraphicsRenderer {
|
|||||||
.application_name(&app_name)
|
.application_name(&app_name)
|
||||||
.api_version(vk::API_VERSION_1_2);
|
.api_version(vk::API_VERSION_1_2);
|
||||||
let mut ext_ptrs: Vec<*const i8> = required_exts.iter().map(|&p| p as *const i8).collect();
|
let mut ext_ptrs: Vec<*const i8> = required_exts.iter().map(|&p| p as *const i8).collect();
|
||||||
let avail_exts = unsafe { entry.enumerate_instance_extension_properties(None) }.unwrap_or_default();
|
let avail_exts =
|
||||||
|
unsafe { entry.enumerate_instance_extension_properties(None) }.unwrap_or_default();
|
||||||
let has_debug = avail_exts.iter().any(|e| {
|
let has_debug = avail_exts.iter().any(|e| {
|
||||||
let name = unsafe { std::ffi::CStr::from_ptr(e.extension_name.as_ptr() as *const i8) };
|
let name = unsafe { std::ffi::CStr::from_ptr(e.extension_name.as_ptr() as *const i8) };
|
||||||
name.to_str().unwrap_or("") == "VK_EXT_debug_utils"
|
name.to_str().unwrap_or("") == "VK_EXT_debug_utils"
|
||||||
});
|
});
|
||||||
if has_debug { ext_ptrs.push(b"VK_EXT_debug_utils\0".as_ptr() as *const i8); }
|
if has_debug {
|
||||||
|
ext_ptrs.push(b"VK_EXT_debug_utils\0".as_ptr() as *const i8);
|
||||||
|
}
|
||||||
let ci = vk::InstanceCreateInfo::default()
|
let ci = vk::InstanceCreateInfo::default()
|
||||||
.application_info(&app_info).enabled_extension_names(&ext_ptrs);
|
.application_info(&app_info)
|
||||||
let instance = unsafe { entry.create_instance(&ci, None) }.map_err(|e| format!("instance: {e:?}"))?;
|
.enabled_extension_names(&ext_ptrs);
|
||||||
|
let instance =
|
||||||
|
unsafe { entry.create_instance(&ci, None) }.map_err(|e| format!("instance: {e:?}"))?;
|
||||||
|
|
||||||
let surface = {
|
let surface = {
|
||||||
use raw_window_handle::HasWindowHandle;
|
use raw_window_handle::HasWindowHandle;
|
||||||
@@ -103,70 +110,118 @@ impl GraphicsRenderer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let sl = ash::khr::surface::Instance::new(&entry, &instance);
|
let sl = ash::khr::surface::Instance::new(&entry, &instance);
|
||||||
let devices = unsafe { instance.enumerate_physical_devices() }.map_err(|e| format!("enum: {e:?}"))?;
|
let devices =
|
||||||
|
unsafe { instance.enumerate_physical_devices() }.map_err(|e| format!("enum: {e:?}"))?;
|
||||||
let mut physical_device = vk::PhysicalDevice::null();
|
let mut physical_device = vk::PhysicalDevice::null();
|
||||||
let mut qf = 0u32;
|
let mut qf = 0u32;
|
||||||
for &pd in &devices {
|
for &pd in &devices {
|
||||||
let props = unsafe { instance.get_physical_device_properties(pd) };
|
let props = unsafe { instance.get_physical_device_properties(pd) };
|
||||||
if props.device_type == vk::PhysicalDeviceType::CPU { continue; }
|
if props.device_type == vk::PhysicalDeviceType::CPU {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let qfs = unsafe { instance.get_physical_device_queue_family_properties(pd) };
|
let qfs = unsafe { instance.get_physical_device_queue_family_properties(pd) };
|
||||||
for (i, q) in qfs.iter().enumerate() {
|
for (i, q) in qfs.iter().enumerate() {
|
||||||
if q.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
|
if q.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
|
||||||
let ok = unsafe { sl.get_physical_device_surface_support(pd, i as u32, surface) }.unwrap_or(false);
|
let ok =
|
||||||
if ok { physical_device = pd; qf = i as u32; break; }
|
unsafe { sl.get_physical_device_surface_support(pd, i as u32, surface) }
|
||||||
|
.unwrap_or(false);
|
||||||
|
if ok {
|
||||||
|
physical_device = pd;
|
||||||
|
qf = i as u32;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if physical_device != vk::PhysicalDevice::null() { break; }
|
|
||||||
}
|
}
|
||||||
if physical_device == vk::PhysicalDevice::null() { return Err("No GPU".to_string()); }
|
if physical_device != vk::PhysicalDevice::null() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if physical_device == vk::PhysicalDevice::null() {
|
||||||
|
return Err("No GPU".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
let qp = [1.0f32];
|
let qp = [1.0f32];
|
||||||
let qi = vk::DeviceQueueCreateInfo::default().queue_family_index(qf).queue_priorities(&qp);
|
let qi = vk::DeviceQueueCreateInfo::default()
|
||||||
|
.queue_family_index(qf)
|
||||||
|
.queue_priorities(&qp);
|
||||||
let dev_ext_names: Vec<CString> = vec![CString::new("VK_KHR_swapchain").unwrap()];
|
let dev_ext_names: Vec<CString> = vec![CString::new("VK_KHR_swapchain").unwrap()];
|
||||||
let dev_ext_ptrs: Vec<*const i8> = dev_ext_names.iter().map(|n| n.as_ptr()).collect();
|
let dev_ext_ptrs: Vec<*const i8> = dev_ext_names.iter().map(|n| n.as_ptr()).collect();
|
||||||
let dci = vk::DeviceCreateInfo::default()
|
let dci = vk::DeviceCreateInfo::default()
|
||||||
.queue_create_infos(std::slice::from_ref(&qi))
|
.queue_create_infos(std::slice::from_ref(&qi))
|
||||||
.enabled_extension_names(&dev_ext_ptrs);
|
.enabled_extension_names(&dev_ext_ptrs);
|
||||||
let device = unsafe { instance.create_device(physical_device, &dci, None) }.map_err(|e| format!("device: {e:?}"))?;
|
let device = unsafe { instance.create_device(physical_device, &dci, None) }
|
||||||
|
.map_err(|e| format!("device: {e:?}"))?;
|
||||||
let graphics_queue = unsafe { device.get_device_queue(qf, 0) };
|
let graphics_queue = unsafe { device.get_device_queue(qf, 0) };
|
||||||
|
|
||||||
let swapchain_loader = ash::khr::swapchain::Device::new(&instance, &device);
|
let swapchain_loader = ash::khr::swapchain::Device::new(&instance, &device);
|
||||||
let caps = unsafe { sl.get_physical_device_surface_capabilities(physical_device, surface) }.map_err(|e| format!("caps: {e:?}"))?;
|
let caps = unsafe { sl.get_physical_device_surface_capabilities(physical_device, surface) }
|
||||||
let format = vk::SurfaceFormatKHR { format: vk::Format::B8G8R8A8_UNORM, color_space: vk::ColorSpaceKHR::SRGB_NONLINEAR };
|
.map_err(|e| format!("caps: {e:?}"))?;
|
||||||
let extent = if caps.current_extent.width != u32::MAX { caps.current_extent }
|
let format = vk::SurfaceFormatKHR {
|
||||||
else { vk::Extent2D { width: grid_w as u32 * CHAR_W, height: grid_h as u32 * CHAR_H } };
|
format: vk::Format::B8G8R8A8_UNORM,
|
||||||
|
color_space: vk::ColorSpaceKHR::SRGB_NONLINEAR,
|
||||||
|
};
|
||||||
|
let extent = if caps.current_extent.width != u32::MAX {
|
||||||
|
caps.current_extent
|
||||||
|
} else {
|
||||||
|
vk::Extent2D {
|
||||||
|
width: grid_w as u32 * CHAR_W,
|
||||||
|
height: grid_h as u32 * CHAR_H,
|
||||||
|
}
|
||||||
|
};
|
||||||
let ic = caps.min_image_count.max(2);
|
let ic = caps.min_image_count.max(2);
|
||||||
let qf_slice = [qf];
|
let qf_slice = [qf];
|
||||||
let sci = vk::SwapchainCreateInfoKHR::default()
|
let sci = vk::SwapchainCreateInfoKHR::default()
|
||||||
.surface(surface).min_image_count(ic)
|
.surface(surface)
|
||||||
.image_format(format.format).image_color_space(format.color_space)
|
.min_image_count(ic)
|
||||||
.image_extent(extent).image_array_layers(1)
|
.image_format(format.format)
|
||||||
|
.image_color_space(format.color_space)
|
||||||
|
.image_extent(extent)
|
||||||
|
.image_array_layers(1)
|
||||||
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
||||||
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||||
.queue_family_indices(&qf_slice)
|
.queue_family_indices(&qf_slice)
|
||||||
.pre_transform(caps.current_transform)
|
.pre_transform(caps.current_transform)
|
||||||
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
|
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
|
||||||
.present_mode(vk::PresentModeKHR::FIFO).clipped(true);
|
.present_mode(vk::PresentModeKHR::FIFO)
|
||||||
let swapchain = unsafe { swapchain_loader.create_swapchain(&sci, None) }.map_err(|e| format!("swapchain: {e:?}"))?;
|
.clipped(true);
|
||||||
let swapchain_images = unsafe { swapchain_loader.get_swapchain_images(swapchain) }.map_err(|e| format!("images: {e:?}"))?;
|
let swapchain = unsafe { swapchain_loader.create_swapchain(&sci, None) }
|
||||||
let swapchain_image_views: Vec<_> = swapchain_images.iter()
|
.map_err(|e| format!("swapchain: {e:?}"))?;
|
||||||
|
let swapchain_images = unsafe { swapchain_loader.get_swapchain_images(swapchain) }
|
||||||
|
.map_err(|e| format!("images: {e:?}"))?;
|
||||||
|
let swapchain_image_views: Vec<_> = swapchain_images
|
||||||
|
.iter()
|
||||||
.map(|&img| {
|
.map(|&img| {
|
||||||
let vi = vk::ImageViewCreateInfo::default()
|
let vi = vk::ImageViewCreateInfo::default()
|
||||||
.image(img).view_type(vk::ImageViewType::TYPE_2D).format(format.format)
|
.image(img)
|
||||||
.subresource_range(vk::ImageSubresourceRange { aspect_mask: vk::ImageAspectFlags::COLOR, base_mip_level: 0, level_count: 1, base_array_layer: 0, layer_count: 1 });
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
|
.format(format.format)
|
||||||
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
|
base_mip_level: 0,
|
||||||
|
level_count: 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
layer_count: 1,
|
||||||
|
});
|
||||||
unsafe { device.create_image_view(&vi, None).expect("image_view") }
|
unsafe { device.create_image_view(&vi, None).expect("image_view") }
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let att = vk::AttachmentDescription::default()
|
let att = vk::AttachmentDescription::default()
|
||||||
.format(format.format).samples(vk::SampleCountFlags::TYPE_1)
|
.format(format.format)
|
||||||
.load_op(vk::AttachmentLoadOp::CLEAR).store_op(vk::AttachmentStoreOp::STORE)
|
.samples(vk::SampleCountFlags::TYPE_1)
|
||||||
.initial_layout(vk::ImageLayout::UNDEFINED).final_layout(vk::ImageLayout::PRESENT_SRC_KHR);
|
.load_op(vk::AttachmentLoadOp::CLEAR)
|
||||||
let att_ref = vk::AttachmentReference::default().attachment(0).layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
|
.store_op(vk::AttachmentStoreOp::STORE)
|
||||||
|
.initial_layout(vk::ImageLayout::UNDEFINED)
|
||||||
|
.final_layout(vk::ImageLayout::PRESENT_SRC_KHR);
|
||||||
|
let att_ref = vk::AttachmentReference::default()
|
||||||
|
.attachment(0)
|
||||||
|
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
|
||||||
let subpass = vk::SubpassDescription::default()
|
let subpass = vk::SubpassDescription::default()
|
||||||
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
|
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
|
||||||
.color_attachments(std::slice::from_ref(&att_ref));
|
.color_attachments(std::slice::from_ref(&att_ref));
|
||||||
let dep = vk::SubpassDependency::default()
|
let dep = vk::SubpassDependency::default()
|
||||||
.src_subpass(vk::SUBPASS_EXTERNAL).dst_subpass(0)
|
.src_subpass(vk::SUBPASS_EXTERNAL)
|
||||||
|
.dst_subpass(0)
|
||||||
.src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
|
.src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
|
||||||
.dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
|
.dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
|
||||||
.dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE);
|
.dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE);
|
||||||
@@ -174,67 +229,159 @@ impl GraphicsRenderer {
|
|||||||
.attachments(std::slice::from_ref(&att))
|
.attachments(std::slice::from_ref(&att))
|
||||||
.subpasses(std::slice::from_ref(&subpass))
|
.subpasses(std::slice::from_ref(&subpass))
|
||||||
.dependencies(std::slice::from_ref(&dep));
|
.dependencies(std::slice::from_ref(&dep));
|
||||||
let render_pass = unsafe { device.create_render_pass(&rpci, None) }.map_err(|e| format!("render_pass: {e:?}"))?;
|
let render_pass = unsafe { device.create_render_pass(&rpci, None) }
|
||||||
|
.map_err(|e| format!("render_pass: {e:?}"))?;
|
||||||
|
|
||||||
// Pipeline — no atlas, no descriptor set, just colored quads
|
// Pipeline — no atlas, no descriptor set, just colored quads
|
||||||
let vert_spv = include_bytes!("../../assets/shaders/graphics_vert.spv");
|
let vert_spv = include_bytes!("../../assets/shaders/graphics_vert.spv");
|
||||||
let frag_spv = include_bytes!("../../assets/shaders/graphics_frag.spv");
|
let frag_spv = include_bytes!("../../assets/shaders/graphics_frag.spv");
|
||||||
let vert_code: Vec<u32> = vert_spv.chunks_exact(4).map(|c| u32::from_ne_bytes([c[0], c[1], c[2], c[3]])).collect();
|
let vert_code: Vec<u32> = vert_spv
|
||||||
let frag_code: Vec<u32> = frag_spv.chunks_exact(4).map(|c| u32::from_ne_bytes([c[0], c[1], c[2], c[3]])).collect();
|
.chunks_exact(4)
|
||||||
let vm = unsafe { device.create_shader_module(&vk::ShaderModuleCreateInfo::default().code(&vert_code), None) }.map_err(|e| format!("vert: {e:?}"))?;
|
.map(|c| u32::from_ne_bytes([c[0], c[1], c[2], c[3]]))
|
||||||
let fm = unsafe { device.create_shader_module(&vk::ShaderModuleCreateInfo::default().code(&frag_code), None) }.map_err(|e| format!("frag: {e:?}"))?;
|
.collect();
|
||||||
|
let frag_code: Vec<u32> = frag_spv
|
||||||
|
.chunks_exact(4)
|
||||||
|
.map(|c| u32::from_ne_bytes([c[0], c[1], c[2], c[3]]))
|
||||||
|
.collect();
|
||||||
|
let vm = unsafe {
|
||||||
|
device.create_shader_module(
|
||||||
|
&vk::ShaderModuleCreateInfo::default().code(&vert_code),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.map_err(|e| format!("vert: {e:?}"))?;
|
||||||
|
let fm = unsafe {
|
||||||
|
device.create_shader_module(
|
||||||
|
&vk::ShaderModuleCreateInfo::default().code(&frag_code),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.map_err(|e| format!("frag: {e:?}"))?;
|
||||||
let main = CString::new("main").unwrap();
|
let main = CString::new("main").unwrap();
|
||||||
let vs = vk::PipelineShaderStageCreateInfo::default().stage(vk::ShaderStageFlags::VERTEX).module(vm).name(&main);
|
let vs = vk::PipelineShaderStageCreateInfo::default()
|
||||||
let fs = vk::PipelineShaderStageCreateInfo::default().stage(vk::ShaderStageFlags::FRAGMENT).module(fm).name(&main);
|
.stage(vk::ShaderStageFlags::VERTEX)
|
||||||
|
.module(vm)
|
||||||
|
.name(&main);
|
||||||
|
let fs = vk::PipelineShaderStageCreateInfo::default()
|
||||||
|
.stage(vk::ShaderStageFlags::FRAGMENT)
|
||||||
|
.module(fm)
|
||||||
|
.name(&main);
|
||||||
|
|
||||||
let bindings = [
|
let bindings = [
|
||||||
vk::VertexInputBindingDescription { binding: 0, stride: 8, input_rate: vk::VertexInputRate::VERTEX },
|
vk::VertexInputBindingDescription {
|
||||||
vk::VertexInputBindingDescription { binding: 1, stride: std::mem::size_of::<ColorInstance>() as u32, input_rate: vk::VertexInputRate::INSTANCE },
|
binding: 0,
|
||||||
|
stride: 8,
|
||||||
|
input_rate: vk::VertexInputRate::VERTEX,
|
||||||
|
},
|
||||||
|
vk::VertexInputBindingDescription {
|
||||||
|
binding: 1,
|
||||||
|
stride: std::mem::size_of::<ColorInstance>() as u32,
|
||||||
|
input_rate: vk::VertexInputRate::INSTANCE,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
let attrs = [
|
let attrs = [
|
||||||
vk::VertexInputAttributeDescription { location: 0, binding: 0, format: vk::Format::R32G32_SFLOAT, offset: 0 },
|
vk::VertexInputAttributeDescription {
|
||||||
vk::VertexInputAttributeDescription { location: 1, binding: 1, format: vk::Format::R32G32_SFLOAT, offset: 0 },
|
location: 0,
|
||||||
vk::VertexInputAttributeDescription { location: 2, binding: 1, format: vk::Format::R8G8B8A8_UNORM, offset: 8 },
|
binding: 0,
|
||||||
|
format: vk::Format::R32G32_SFLOAT,
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
vk::VertexInputAttributeDescription {
|
||||||
|
location: 1,
|
||||||
|
binding: 1,
|
||||||
|
format: vk::Format::R32G32_SFLOAT,
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
vk::VertexInputAttributeDescription {
|
||||||
|
location: 2,
|
||||||
|
binding: 1,
|
||||||
|
format: vk::Format::R8G8B8A8_UNORM,
|
||||||
|
offset: 8,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
let vi = vk::PipelineVertexInputStateCreateInfo::default()
|
let vi = vk::PipelineVertexInputStateCreateInfo::default()
|
||||||
.vertex_binding_descriptions(&bindings).vertex_attribute_descriptions(&attrs);
|
.vertex_binding_descriptions(&bindings)
|
||||||
let ia = vk::PipelineInputAssemblyStateCreateInfo::default().topology(vk::PrimitiveTopology::TRIANGLE_LIST);
|
.vertex_attribute_descriptions(&attrs);
|
||||||
|
let ia = vk::PipelineInputAssemblyStateCreateInfo::default()
|
||||||
|
.topology(vk::PrimitiveTopology::TRIANGLE_LIST);
|
||||||
let dynamic_states = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
|
let dynamic_states = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
|
||||||
let dynamic_state = vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&dynamic_states);
|
let dynamic_state =
|
||||||
let vs_state = vk::PipelineViewportStateCreateInfo::default().viewport_count(1).scissor_count(1);
|
vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&dynamic_states);
|
||||||
let rs = vk::PipelineRasterizationStateCreateInfo::default().line_width(1.0).cull_mode(vk::CullModeFlags::NONE);
|
let vs_state = vk::PipelineViewportStateCreateInfo::default()
|
||||||
let ms = vk::PipelineMultisampleStateCreateInfo::default().rasterization_samples(vk::SampleCountFlags::TYPE_1);
|
.viewport_count(1)
|
||||||
let cba = vk::PipelineColorBlendAttachmentState::default().color_write_mask(vk::ColorComponentFlags::RGBA);
|
.scissor_count(1);
|
||||||
let cb = vk::PipelineColorBlendStateCreateInfo::default().attachments(std::slice::from_ref(&cba));
|
let rs = vk::PipelineRasterizationStateCreateInfo::default()
|
||||||
let pcr = vk::PushConstantRange { stage_flags: vk::ShaderStageFlags::VERTEX, offset: 0, size: std::mem::size_of::<PushConstants>() as u32 };
|
.line_width(1.0)
|
||||||
let pli = vk::PipelineLayoutCreateInfo::default().push_constant_ranges(std::slice::from_ref(&pcr));
|
.cull_mode(vk::CullModeFlags::NONE);
|
||||||
let pipeline_layout = unsafe { device.create_pipeline_layout(&pli, None) }.map_err(|e| format!("pipeline_layout: {e:?}"))?;
|
let ms = vk::PipelineMultisampleStateCreateInfo::default()
|
||||||
|
.rasterization_samples(vk::SampleCountFlags::TYPE_1);
|
||||||
|
let cba = vk::PipelineColorBlendAttachmentState::default()
|
||||||
|
.color_write_mask(vk::ColorComponentFlags::RGBA);
|
||||||
|
let cb = vk::PipelineColorBlendStateCreateInfo::default()
|
||||||
|
.attachments(std::slice::from_ref(&cba));
|
||||||
|
let pcr = vk::PushConstantRange {
|
||||||
|
stage_flags: vk::ShaderStageFlags::VERTEX,
|
||||||
|
offset: 0,
|
||||||
|
size: std::mem::size_of::<PushConstants>() as u32,
|
||||||
|
};
|
||||||
|
let pli = vk::PipelineLayoutCreateInfo::default()
|
||||||
|
.push_constant_ranges(std::slice::from_ref(&pcr));
|
||||||
|
let pipeline_layout = unsafe { device.create_pipeline_layout(&pli, None) }
|
||||||
|
.map_err(|e| format!("pipeline_layout: {e:?}"))?;
|
||||||
let stages = [vs, fs];
|
let stages = [vs, fs];
|
||||||
let gpci = vk::GraphicsPipelineCreateInfo::default()
|
let gpci = vk::GraphicsPipelineCreateInfo::default()
|
||||||
.stages(&stages).vertex_input_state(&vi).input_assembly_state(&ia)
|
.stages(&stages)
|
||||||
.viewport_state(&vs_state).rasterization_state(&rs).multisample_state(&ms)
|
.vertex_input_state(&vi)
|
||||||
.color_blend_state(&cb).dynamic_state(&dynamic_state)
|
.input_assembly_state(&ia)
|
||||||
.layout(pipeline_layout).render_pass(render_pass).subpass(0);
|
.viewport_state(&vs_state)
|
||||||
let pipes = unsafe { device.create_graphics_pipelines(vk::PipelineCache::null(), std::slice::from_ref(&gpci), None) }
|
.rasterization_state(&rs)
|
||||||
|
.multisample_state(&ms)
|
||||||
|
.color_blend_state(&cb)
|
||||||
|
.dynamic_state(&dynamic_state)
|
||||||
|
.layout(pipeline_layout)
|
||||||
|
.render_pass(render_pass)
|
||||||
|
.subpass(0);
|
||||||
|
let pipes = unsafe {
|
||||||
|
device.create_graphics_pipelines(
|
||||||
|
vk::PipelineCache::null(),
|
||||||
|
std::slice::from_ref(&gpci),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
.map_err(|(_, e)| format!("pipeline: {e:?}"))?;
|
.map_err(|(_, e)| format!("pipeline: {e:?}"))?;
|
||||||
unsafe { device.destroy_shader_module(vm, None); device.destroy_shader_module(fm, None); }
|
unsafe {
|
||||||
|
device.destroy_shader_module(vm, None);
|
||||||
|
device.destroy_shader_module(fm, None);
|
||||||
|
}
|
||||||
let pipeline = pipes[0];
|
let pipeline = pipes[0];
|
||||||
|
|
||||||
let framebuffers: Vec<_> = swapchain_image_views.iter()
|
let framebuffers: Vec<_> = swapchain_image_views
|
||||||
|
.iter()
|
||||||
.map(|&view| {
|
.map(|&view| {
|
||||||
let fci = vk::FramebufferCreateInfo::default()
|
let fci = vk::FramebufferCreateInfo::default()
|
||||||
.render_pass(render_pass).attachments(std::slice::from_ref(&view))
|
.render_pass(render_pass)
|
||||||
.width(extent.width).height(extent.height).layers(1);
|
.attachments(std::slice::from_ref(&view))
|
||||||
|
.width(extent.width)
|
||||||
|
.height(extent.height)
|
||||||
|
.layers(1);
|
||||||
unsafe { device.create_framebuffer(&fci, None).expect("fb") }
|
unsafe { device.create_framebuffer(&fci, None).expect("fb") }
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let command_pool = {
|
let command_pool = {
|
||||||
let cpci = vk::CommandPoolCreateInfo::default().queue_family_index(qf).flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER);
|
let cpci = vk::CommandPoolCreateInfo::default()
|
||||||
unsafe { device.create_command_pool(&cpci, None) }.map_err(|e| format!("cmd_pool: {e:?}"))?
|
.queue_family_index(qf)
|
||||||
|
.flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER);
|
||||||
|
unsafe { device.create_command_pool(&cpci, None) }
|
||||||
|
.map_err(|e| format!("cmd_pool: {e:?}"))?
|
||||||
};
|
};
|
||||||
let command_buffers = {
|
let command_buffers = {
|
||||||
let cai = vk::CommandBufferAllocateInfo::default().command_pool(command_pool).level(vk::CommandBufferLevel::PRIMARY).command_buffer_count(framebuffers.len() as u32);
|
let cai = vk::CommandBufferAllocateInfo::default()
|
||||||
unsafe { device.allocate_command_buffers(&cai) }.map_err(|e| format!("cmd_bufs: {e:?}"))?
|
.command_pool(command_pool)
|
||||||
|
.level(vk::CommandBufferLevel::PRIMARY)
|
||||||
|
.command_buffer_count(framebuffers.len() as u32);
|
||||||
|
unsafe { device.allocate_command_buffers(&cai) }
|
||||||
|
.map_err(|e| format!("cmd_bufs: {e:?}"))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut image_available = Vec::new();
|
let mut image_available = Vec::new();
|
||||||
@@ -242,9 +389,24 @@ impl GraphicsRenderer {
|
|||||||
let mut in_flight = Vec::new();
|
let mut in_flight = Vec::new();
|
||||||
for _ in 0..MAX_FRAMES {
|
for _ in 0..MAX_FRAMES {
|
||||||
unsafe {
|
unsafe {
|
||||||
image_available.push(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None).map_err(|e| format!("sem: {e:?}"))?);
|
image_available.push(
|
||||||
render_finished.push(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None).map_err(|e| format!("sem: {e:?}"))?);
|
device
|
||||||
in_flight.push(device.create_fence(&vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED), None).map_err(|e| format!("fence: {e:?}"))?);
|
.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)
|
||||||
|
.map_err(|e| format!("sem: {e:?}"))?,
|
||||||
|
);
|
||||||
|
render_finished.push(
|
||||||
|
device
|
||||||
|
.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)
|
||||||
|
.map_err(|e| format!("sem: {e:?}"))?,
|
||||||
|
);
|
||||||
|
in_flight.push(
|
||||||
|
device
|
||||||
|
.create_fence(
|
||||||
|
&vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("fence: {e:?}"))?,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,20 +414,41 @@ impl GraphicsRenderer {
|
|||||||
let find_mem = |filter: u32, props: vk::MemoryPropertyFlags| -> Result<u32, String> {
|
let find_mem = |filter: u32, props: vk::MemoryPropertyFlags| -> Result<u32, String> {
|
||||||
let mp = unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
let mp = unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
||||||
for (i, mt) in mp.memory_types.iter().enumerate() {
|
for (i, mt) in mp.memory_types.iter().enumerate() {
|
||||||
if (filter & (1 << i)) != 0 && mt.property_flags.contains(props) { return Ok(i as u32); }
|
if (filter & (1 << i)) != 0 && mt.property_flags.contains(props) {
|
||||||
|
return Ok(i as u32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err("No memory type".to_string())
|
Err("No memory type".to_string())
|
||||||
};
|
};
|
||||||
let make_buf = |data: &[u8], usage: vk::BufferUsageFlags| -> Result<(vk::Buffer, vk::DeviceMemory), String> {
|
let make_buf = |data: &[u8],
|
||||||
|
usage: vk::BufferUsageFlags|
|
||||||
|
-> Result<(vk::Buffer, vk::DeviceMemory), String> {
|
||||||
let sz = data.len() as vk::DeviceSize;
|
let sz = data.len() as vk::DeviceSize;
|
||||||
let bi = vk::BufferCreateInfo::default().size(sz).usage(usage).sharing_mode(vk::SharingMode::EXCLUSIVE);
|
let bi = vk::BufferCreateInfo::default()
|
||||||
let buf = unsafe { device.create_buffer(&bi, None) }.map_err(|e| format!("buf: {e:?}"))?;
|
.size(sz)
|
||||||
|
.usage(usage)
|
||||||
|
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||||
|
let buf =
|
||||||
|
unsafe { device.create_buffer(&bi, None) }.map_err(|e| format!("buf: {e:?}"))?;
|
||||||
let req = unsafe { device.get_buffer_memory_requirements(buf) };
|
let req = unsafe { device.get_buffer_memory_requirements(buf) };
|
||||||
let mt = find_mem(req.memory_type_bits, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT)?;
|
let mt = find_mem(
|
||||||
let mem = unsafe { device.allocate_memory(&vk::MemoryAllocateInfo::default().allocation_size(req.size).memory_type_index(mt), None) }.map_err(|e| format!("mem: {e:?}"))?;
|
req.memory_type_bits,
|
||||||
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
||||||
|
)?;
|
||||||
|
let mem = unsafe {
|
||||||
|
device.allocate_memory(
|
||||||
|
&vk::MemoryAllocateInfo::default()
|
||||||
|
.allocation_size(req.size)
|
||||||
|
.memory_type_index(mt),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.map_err(|e| format!("mem: {e:?}"))?;
|
||||||
unsafe {
|
unsafe {
|
||||||
device.bind_buffer_memory(buf, mem, 0).expect("bind");
|
device.bind_buffer_memory(buf, mem, 0).expect("bind");
|
||||||
let ptr = device.map_memory(mem, 0, sz, vk::MemoryMapFlags::default()).expect("map");
|
let ptr = device
|
||||||
|
.map_memory(mem, 0, sz, vk::MemoryMapFlags::default())
|
||||||
|
.expect("map");
|
||||||
std::ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len());
|
std::ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len());
|
||||||
device.unmap_memory(mem);
|
device.unmap_memory(mem);
|
||||||
}
|
}
|
||||||
@@ -273,32 +456,79 @@ impl GraphicsRenderer {
|
|||||||
};
|
};
|
||||||
let verts: [f32; 8] = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
|
let verts: [f32; 8] = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
|
||||||
let indices: [u16; 6] = [0, 1, 2, 1, 3, 2];
|
let indices: [u16; 6] = [0, 1, 2, 1, 3, 2];
|
||||||
let (vertex_buffer, vertex_memory) = make_buf(bytemuck::cast_slice(&verts), vk::BufferUsageFlags::VERTEX_BUFFER)?;
|
let (vertex_buffer, vertex_memory) = make_buf(
|
||||||
let (index_buffer, index_memory) = make_buf(bytemuck::cast_slice(&indices), vk::BufferUsageFlags::INDEX_BUFFER)?;
|
bytemuck::cast_slice(&verts),
|
||||||
|
vk::BufferUsageFlags::VERTEX_BUFFER,
|
||||||
|
)?;
|
||||||
|
let (index_buffer, index_memory) = make_buf(
|
||||||
|
bytemuck::cast_slice(&indices),
|
||||||
|
vk::BufferUsageFlags::INDEX_BUFFER,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Instance buffer
|
// Instance buffer
|
||||||
let instance_count = grid_w * grid_h;
|
let instance_count = grid_w * grid_h;
|
||||||
let inst_sz = (instance_count * std::mem::size_of::<ColorInstance>()) as vk::DeviceSize;
|
let inst_sz = (instance_count * std::mem::size_of::<ColorInstance>()) as vk::DeviceSize;
|
||||||
let ibi = vk::BufferCreateInfo::default().size(inst_sz).usage(vk::BufferUsageFlags::VERTEX_BUFFER).sharing_mode(vk::SharingMode::EXCLUSIVE);
|
let ibi = vk::BufferCreateInfo::default()
|
||||||
let instance_buffer = unsafe { device.create_buffer(&ibi, None) }.map_err(|e| format!("inst buf: {e:?}"))?;
|
.size(inst_sz)
|
||||||
|
.usage(vk::BufferUsageFlags::VERTEX_BUFFER)
|
||||||
|
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||||
|
let instance_buffer =
|
||||||
|
unsafe { device.create_buffer(&ibi, None) }.map_err(|e| format!("inst buf: {e:?}"))?;
|
||||||
let ireq = unsafe { device.get_buffer_memory_requirements(instance_buffer) };
|
let ireq = unsafe { device.get_buffer_memory_requirements(instance_buffer) };
|
||||||
let imt = find_mem(ireq.memory_type_bits, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT)?;
|
let imt = find_mem(
|
||||||
let instance_memory = unsafe { device.allocate_memory(&vk::MemoryAllocateInfo::default().allocation_size(ireq.size).memory_type_index(imt), None) }.map_err(|e| format!("inst mem: {e:?}"))?;
|
ireq.memory_type_bits,
|
||||||
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
||||||
|
)?;
|
||||||
|
let instance_memory = unsafe {
|
||||||
|
device.allocate_memory(
|
||||||
|
&vk::MemoryAllocateInfo::default()
|
||||||
|
.allocation_size(ireq.size)
|
||||||
|
.memory_type_index(imt),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.map_err(|e| format!("inst mem: {e:?}"))?;
|
||||||
let instance_ptr = unsafe {
|
let instance_ptr = unsafe {
|
||||||
device.bind_buffer_memory(instance_buffer, instance_memory, 0).expect("bind inst");
|
device
|
||||||
let ptr = device.map_memory(instance_memory, 0, inst_sz, vk::MemoryMapFlags::default()).expect("map inst");
|
.bind_buffer_memory(instance_buffer, instance_memory, 0)
|
||||||
|
.expect("bind inst");
|
||||||
|
let ptr = device
|
||||||
|
.map_memory(instance_memory, 0, inst_sz, vk::MemoryMapFlags::default())
|
||||||
|
.expect("map inst");
|
||||||
ptr as *mut ColorInstance
|
ptr as *mut ColorInstance
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
grid_w, grid_h,
|
grid_w,
|
||||||
entry, instance, surface, physical_device, device, graphics_queue,
|
grid_h,
|
||||||
swapchain_loader, swapchain, swapchain_image_views, swapchain_extent: extent,
|
entry,
|
||||||
render_pass, pipeline, pipeline_layout, framebuffers,
|
instance,
|
||||||
command_pool, command_buffers,
|
surface,
|
||||||
image_available, render_finished, in_flight, frame_index: 0,
|
physical_device,
|
||||||
vertex_buffer, vertex_memory, index_buffer, index_memory,
|
device,
|
||||||
instance_buffer, instance_memory, instance_ptr, instance_count,
|
graphics_queue,
|
||||||
|
swapchain_loader,
|
||||||
|
swapchain,
|
||||||
|
swapchain_image_views,
|
||||||
|
swapchain_extent: extent,
|
||||||
|
render_pass,
|
||||||
|
pipeline,
|
||||||
|
pipeline_layout,
|
||||||
|
framebuffers,
|
||||||
|
command_pool,
|
||||||
|
command_buffers,
|
||||||
|
image_available,
|
||||||
|
render_finished,
|
||||||
|
in_flight,
|
||||||
|
frame_index: 0,
|
||||||
|
vertex_buffer,
|
||||||
|
vertex_memory,
|
||||||
|
index_buffer,
|
||||||
|
index_memory,
|
||||||
|
instance_buffer,
|
||||||
|
instance_memory,
|
||||||
|
instance_ptr,
|
||||||
|
instance_count,
|
||||||
window,
|
window,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -306,16 +536,21 @@ impl GraphicsRenderer {
|
|||||||
pub fn render(&mut self, grid: &Grid, entities: &EntityManager, cam_x: i32, cam_y: i32) {
|
pub fn render(&mut self, grid: &Grid, entities: &EntityManager, cam_x: i32, cam_y: i32) {
|
||||||
self.check_resize();
|
self.check_resize();
|
||||||
|
|
||||||
let mut entity_map: std::collections::HashMap<(i32, i32), [u8; 4]> = std::collections::HashMap::new();
|
let mut entity_map: std::collections::HashMap<(i32, i32), [u8; 4]> =
|
||||||
|
std::collections::HashMap::new();
|
||||||
for e in entities.all() {
|
for e in entities.all() {
|
||||||
for b in &e.bodies {
|
for b in &e.bodies {
|
||||||
if !b.alive { continue; }
|
if !b.alive {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let sx = b.x as i32 - cam_x;
|
let sx = b.x as i32 - cam_x;
|
||||||
let sy = b.y as i32 - cam_y;
|
let sy = b.y as i32 - cam_y;
|
||||||
if sx >= 0 && sx < self.grid_w as i32 && sy >= 0 && sy < self.grid_h as i32 {
|
if sx >= 0 && sx < self.grid_w as i32 && sy >= 0 && sy < self.grid_h as i32 {
|
||||||
let fg = if e.on_fire { [255, 160, 40, 255] }
|
let fg = if e.on_fire {
|
||||||
else if !e.alive { [100, 60, 60, 255] }
|
[255, 160, 40, 255]
|
||||||
else {
|
} else if !e.alive {
|
||||||
|
[100, 60, 60, 255]
|
||||||
|
} else {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
EntityKind::Player => [255, 255, 100, 255],
|
EntityKind::Player => [255, 255, 100, 255],
|
||||||
EntityKind::Goblin => [100, 220, 100, 255],
|
EntityKind::Goblin => [100, 220, 100, 255],
|
||||||
@@ -327,7 +562,8 @@ impl GraphicsRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let instances = unsafe { std::slice::from_raw_parts_mut(self.instance_ptr, self.instance_count) };
|
let instances =
|
||||||
|
unsafe { std::slice::from_raw_parts_mut(self.instance_ptr, self.instance_count) };
|
||||||
let bg_default = [10u8, 10, 15, 255];
|
let bg_default = [10u8, 10, 15, 255];
|
||||||
|
|
||||||
for dy in 0..self.grid_h {
|
for dy in 0..self.grid_h {
|
||||||
@@ -370,10 +606,16 @@ impl GraphicsRenderer {
|
|||||||
let _ = device.reset_fences(&[self.in_flight[frame]]);
|
let _ = device.reset_fences(&[self.in_flight[frame]]);
|
||||||
|
|
||||||
let image_index = match self.swapchain_loader.acquire_next_image(
|
let image_index = match self.swapchain_loader.acquire_next_image(
|
||||||
self.swapchain, u64::MAX, self.image_available[frame], vk::Fence::null()
|
self.swapchain,
|
||||||
|
u64::MAX,
|
||||||
|
self.image_available[frame],
|
||||||
|
vk::Fence::null(),
|
||||||
) {
|
) {
|
||||||
Ok((idx, _)) => idx as usize,
|
Ok((idx, _)) => idx as usize,
|
||||||
Err(e) => { eprintln!("acquire: {e:?}"); return; }
|
Err(e) => {
|
||||||
|
eprintln!("acquire: {e:?}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let cmd = self.command_buffers[frame];
|
let cmd = self.command_buffers[frame];
|
||||||
@@ -381,36 +623,59 @@ impl GraphicsRenderer {
|
|||||||
let _ = device.begin_command_buffer(cmd, &vk::CommandBufferBeginInfo::default());
|
let _ = device.begin_command_buffer(cmd, &vk::CommandBufferBeginInfo::default());
|
||||||
|
|
||||||
let clear = vk::ClearValue {
|
let clear = vk::ClearValue {
|
||||||
color: vk::ClearColorValue { float32: [10.0/255.0, 10.0/255.0, 15.0/255.0, 1.0] },
|
color: vk::ClearColorValue {
|
||||||
|
float32: [10.0 / 255.0, 10.0 / 255.0, 15.0 / 255.0, 1.0],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let rp_info = vk::RenderPassBeginInfo::default()
|
let rp_info = vk::RenderPassBeginInfo::default()
|
||||||
.render_pass(self.render_pass)
|
.render_pass(self.render_pass)
|
||||||
.framebuffer(self.framebuffers[image_index])
|
.framebuffer(self.framebuffers[image_index])
|
||||||
.render_area(vk::Rect2D { offset: vk::Offset2D::default(), extent: self.swapchain_extent })
|
.render_area(vk::Rect2D {
|
||||||
|
offset: vk::Offset2D::default(),
|
||||||
|
extent: self.swapchain_extent,
|
||||||
|
})
|
||||||
.clear_values(std::slice::from_ref(&clear));
|
.clear_values(std::slice::from_ref(&clear));
|
||||||
|
|
||||||
device.cmd_begin_render_pass(cmd, &rp_info, vk::SubpassContents::INLINE);
|
device.cmd_begin_render_pass(cmd, &rp_info, vk::SubpassContents::INLINE);
|
||||||
device.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, self.pipeline);
|
device.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, self.pipeline);
|
||||||
|
|
||||||
let viewport = vk::Viewport {
|
let viewport = vk::Viewport {
|
||||||
x: 0.0, y: 0.0,
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
width: self.swapchain_extent.width as f32,
|
width: self.swapchain_extent.width as f32,
|
||||||
height: self.swapchain_extent.height as f32,
|
height: self.swapchain_extent.height as f32,
|
||||||
min_depth: 0.0, max_depth: 1.0,
|
min_depth: 0.0,
|
||||||
|
max_depth: 1.0,
|
||||||
|
};
|
||||||
|
let scissor = vk::Rect2D {
|
||||||
|
offset: vk::Offset2D::default(),
|
||||||
|
extent: self.swapchain_extent,
|
||||||
};
|
};
|
||||||
let scissor = vk::Rect2D { offset: vk::Offset2D::default(), extent: self.swapchain_extent };
|
|
||||||
device.cmd_set_viewport(cmd, 0, std::slice::from_ref(&viewport));
|
device.cmd_set_viewport(cmd, 0, std::slice::from_ref(&viewport));
|
||||||
device.cmd_set_scissor(cmd, 0, std::slice::from_ref(&scissor));
|
device.cmd_set_scissor(cmd, 0, std::slice::from_ref(&scissor));
|
||||||
|
|
||||||
device.cmd_bind_vertex_buffers(cmd, 0, &[self.vertex_buffer, self.instance_buffer], &[0, 0]);
|
device.cmd_bind_vertex_buffers(
|
||||||
|
cmd,
|
||||||
|
0,
|
||||||
|
&[self.vertex_buffer, self.instance_buffer],
|
||||||
|
&[0, 0],
|
||||||
|
);
|
||||||
device.cmd_bind_index_buffer(cmd, self.index_buffer, 0, vk::IndexType::UINT16);
|
device.cmd_bind_index_buffer(cmd, self.index_buffer, 0, vk::IndexType::UINT16);
|
||||||
|
|
||||||
let pc = PushConstants {
|
let pc = PushConstants {
|
||||||
screen_size: [self.swapchain_extent.width as f32, self.swapchain_extent.height as f32],
|
screen_size: [
|
||||||
|
self.swapchain_extent.width as f32,
|
||||||
|
self.swapchain_extent.height as f32,
|
||||||
|
],
|
||||||
cell_size: [CHAR_W as f32, CHAR_H as f32],
|
cell_size: [CHAR_W as f32, CHAR_H as f32],
|
||||||
};
|
};
|
||||||
device.cmd_push_constants(cmd, self.pipeline_layout, vk::ShaderStageFlags::VERTEX,
|
device.cmd_push_constants(
|
||||||
0, bytemuck::bytes_of(&pc));
|
cmd,
|
||||||
|
self.pipeline_layout,
|
||||||
|
vk::ShaderStageFlags::VERTEX,
|
||||||
|
0,
|
||||||
|
bytemuck::bytes_of(&pc),
|
||||||
|
);
|
||||||
|
|
||||||
device.cmd_draw_indexed(cmd, 6, self.instance_count as u32, 0, 0, 0);
|
device.cmd_draw_indexed(cmd, 6, self.instance_count as u32, 0, 0, 0);
|
||||||
device.cmd_end_render_pass(cmd);
|
device.cmd_end_render_pass(cmd);
|
||||||
@@ -422,25 +687,37 @@ impl GraphicsRenderer {
|
|||||||
.wait_dst_stage_mask(&wait_stages)
|
.wait_dst_stage_mask(&wait_stages)
|
||||||
.command_buffers(std::slice::from_ref(&cmd))
|
.command_buffers(std::slice::from_ref(&cmd))
|
||||||
.signal_semaphores(std::slice::from_ref(&self.render_finished[frame]));
|
.signal_semaphores(std::slice::from_ref(&self.render_finished[frame]));
|
||||||
let _ = device.queue_submit(self.graphics_queue, std::slice::from_ref(&submit_info), self.in_flight[frame]);
|
let _ = device.queue_submit(
|
||||||
|
self.graphics_queue,
|
||||||
|
std::slice::from_ref(&submit_info),
|
||||||
|
self.in_flight[frame],
|
||||||
|
);
|
||||||
|
|
||||||
let img_idx = image_index as u32;
|
let img_idx = image_index as u32;
|
||||||
let present_info = vk::PresentInfoKHR::default()
|
let present_info = vk::PresentInfoKHR::default()
|
||||||
.wait_semaphores(std::slice::from_ref(&self.render_finished[frame]))
|
.wait_semaphores(std::slice::from_ref(&self.render_finished[frame]))
|
||||||
.swapchains(std::slice::from_ref(&self.swapchain))
|
.swapchains(std::slice::from_ref(&self.swapchain))
|
||||||
.image_indices(std::slice::from_ref(&img_idx));
|
.image_indices(std::slice::from_ref(&img_idx));
|
||||||
let _ = self.swapchain_loader.queue_present(self.graphics_queue, &present_info);
|
let _ = self
|
||||||
|
.swapchain_loader
|
||||||
|
.queue_present(self.graphics_queue, &present_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.frame_index = (self.frame_index + 1) % MAX_FRAMES;
|
self.frame_index = (self.frame_index + 1) % MAX_FRAMES;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grid_w(&self) -> usize { self.grid_w }
|
pub fn grid_w(&self) -> usize {
|
||||||
pub fn grid_h(&self) -> usize { self.grid_h }
|
self.grid_w
|
||||||
|
}
|
||||||
|
pub fn grid_h(&self) -> usize {
|
||||||
|
self.grid_h
|
||||||
|
}
|
||||||
|
|
||||||
fn check_resize(&mut self) {
|
fn check_resize(&mut self) {
|
||||||
let sl = ash::khr::surface::Instance::new(&self.entry, &self.instance);
|
let sl = ash::khr::surface::Instance::new(&self.entry, &self.instance);
|
||||||
let caps = match unsafe { sl.get_physical_device_surface_capabilities(self.physical_device, self.surface) } {
|
let caps = match unsafe {
|
||||||
|
sl.get_physical_device_surface_capabilities(self.physical_device, self.surface)
|
||||||
|
} {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
@@ -457,7 +734,8 @@ impl GraphicsRenderer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if new_extent.width == self.swapchain_extent.width
|
if new_extent.width == self.swapchain_extent.width
|
||||||
&& new_extent.height == self.swapchain_extent.height {
|
&& new_extent.height == self.swapchain_extent.height
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,11 +743,21 @@ impl GraphicsRenderer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { let _ = self.device.device_wait_idle(); }
|
unsafe {
|
||||||
|
let _ = self.device.device_wait_idle();
|
||||||
|
}
|
||||||
|
|
||||||
// Destroy old swapchain resources
|
// Destroy old swapchain resources
|
||||||
for &fb in &self.framebuffers { unsafe { self.device.destroy_framebuffer(fb, None); } }
|
for &fb in &self.framebuffers {
|
||||||
for &v in &self.swapchain_image_views { unsafe { self.device.destroy_image_view(v, None); } }
|
unsafe {
|
||||||
|
self.device.destroy_framebuffer(fb, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &v in &self.swapchain_image_views {
|
||||||
|
unsafe {
|
||||||
|
self.device.destroy_image_view(v, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Recreate swapchain
|
// Recreate swapchain
|
||||||
let sci = vk::SwapchainCreateInfoKHR::default()
|
let sci = vk::SwapchainCreateInfoKHR::default()
|
||||||
@@ -492,40 +780,61 @@ impl GraphicsRenderer {
|
|||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_images = match unsafe { self.swapchain_loader.get_swapchain_images(new_swapchain) } {
|
let new_images = match unsafe { self.swapchain_loader.get_swapchain_images(new_swapchain) }
|
||||||
|
{
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_views: Vec<_> = new_images.iter()
|
let new_views: Vec<_> = new_images
|
||||||
|
.iter()
|
||||||
.map(|&img| {
|
.map(|&img| {
|
||||||
let vi = vk::ImageViewCreateInfo::default()
|
let vi = vk::ImageViewCreateInfo::default()
|
||||||
.image(img).view_type(vk::ImageViewType::TYPE_2D)
|
.image(img)
|
||||||
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
.format(vk::Format::B8G8R8A8_UNORM)
|
.format(vk::Format::B8G8R8A8_UNORM)
|
||||||
.subresource_range(vk::ImageSubresourceRange {
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
base_mip_level: 0, level_count: 1,
|
base_mip_level: 0,
|
||||||
base_array_layer: 0, layer_count: 1,
|
level_count: 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
layer_count: 1,
|
||||||
});
|
});
|
||||||
unsafe { self.device.create_image_view(&vi, None).expect("image_view") }
|
unsafe {
|
||||||
}).collect();
|
self.device
|
||||||
|
.create_image_view(&vi, None)
|
||||||
|
.expect("image_view")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let new_framebuffers: Vec<_> = new_views.iter()
|
let new_framebuffers: Vec<_> = new_views
|
||||||
|
.iter()
|
||||||
.map(|&view| {
|
.map(|&view| {
|
||||||
let fci = vk::FramebufferCreateInfo::default()
|
let fci = vk::FramebufferCreateInfo::default()
|
||||||
.render_pass(self.render_pass)
|
.render_pass(self.render_pass)
|
||||||
.attachments(std::slice::from_ref(&view))
|
.attachments(std::slice::from_ref(&view))
|
||||||
.width(new_extent.width).height(new_extent.height).layers(1);
|
.width(new_extent.width)
|
||||||
|
.height(new_extent.height)
|
||||||
|
.layers(1);
|
||||||
unsafe { self.device.create_framebuffer(&fci, None).expect("fb") }
|
unsafe { self.device.create_framebuffer(&fci, None).expect("fb") }
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Reallocate command buffers for new count
|
// Reallocate command buffers for new count
|
||||||
unsafe { self.device.free_command_buffers(self.command_pool, &self.command_buffers); }
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.free_command_buffers(self.command_pool, &self.command_buffers);
|
||||||
|
}
|
||||||
let cai = vk::CommandBufferAllocateInfo::default()
|
let cai = vk::CommandBufferAllocateInfo::default()
|
||||||
.command_pool(self.command_pool)
|
.command_pool(self.command_pool)
|
||||||
.level(vk::CommandBufferLevel::PRIMARY)
|
.level(vk::CommandBufferLevel::PRIMARY)
|
||||||
.command_buffer_count(new_framebuffers.len() as u32);
|
.command_buffer_count(new_framebuffers.len() as u32);
|
||||||
let new_cmd_bufs = unsafe { self.device.allocate_command_buffers(&cai).expect("cmd_bufs") };
|
let new_cmd_bufs = unsafe {
|
||||||
|
self.device
|
||||||
|
.allocate_command_buffers(&cai)
|
||||||
|
.expect("cmd_bufs")
|
||||||
|
};
|
||||||
|
|
||||||
// Reallocate instance buffer if grid size changed
|
// Reallocate instance buffer if grid size changed
|
||||||
let new_grid_w = (new_extent.width / CHAR_W) as usize;
|
let new_grid_w = (new_extent.width / CHAR_W) as usize;
|
||||||
@@ -544,30 +853,61 @@ impl GraphicsRenderer {
|
|||||||
.size(inst_sz)
|
.size(inst_sz)
|
||||||
.usage(vk::BufferUsageFlags::VERTEX_BUFFER)
|
.usage(vk::BufferUsageFlags::VERTEX_BUFFER)
|
||||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||||
self.instance_buffer = unsafe { self.device.create_buffer(&ibi, None) }.expect("inst buf");
|
self.instance_buffer =
|
||||||
let ireq = unsafe { self.device.get_buffer_memory_requirements(self.instance_buffer) };
|
unsafe { self.device.create_buffer(&ibi, None) }.expect("inst buf");
|
||||||
|
let ireq = unsafe {
|
||||||
|
self.device
|
||||||
|
.get_buffer_memory_requirements(self.instance_buffer)
|
||||||
|
};
|
||||||
|
|
||||||
let find_mem = |filter: u32, props: vk::MemoryPropertyFlags| -> u32 {
|
let find_mem = |filter: u32, props: vk::MemoryPropertyFlags| -> u32 {
|
||||||
let mp = unsafe { self.instance.get_physical_device_memory_properties(self.physical_device) };
|
let mp = unsafe {
|
||||||
|
self.instance
|
||||||
|
.get_physical_device_memory_properties(self.physical_device)
|
||||||
|
};
|
||||||
for (i, mt) in mp.memory_types.iter().enumerate() {
|
for (i, mt) in mp.memory_types.iter().enumerate() {
|
||||||
if (filter & (1 << i)) != 0 && mt.property_flags.contains(props) { return i as u32; }
|
if (filter & (1 << i)) != 0 && mt.property_flags.contains(props) {
|
||||||
|
return i as u32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let imt = find_mem(ireq.memory_type_bits, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT);
|
let imt = find_mem(
|
||||||
self.instance_memory = unsafe { self.device.allocate_memory(
|
ireq.memory_type_bits,
|
||||||
&vk::MemoryAllocateInfo::default().allocation_size(ireq.size).memory_type_index(imt), None)
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
||||||
}.expect("inst mem");
|
);
|
||||||
|
self.instance_memory = unsafe {
|
||||||
|
self.device.allocate_memory(
|
||||||
|
&vk::MemoryAllocateInfo::default()
|
||||||
|
.allocation_size(ireq.size)
|
||||||
|
.memory_type_index(imt),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.expect("inst mem");
|
||||||
self.instance_ptr = unsafe {
|
self.instance_ptr = unsafe {
|
||||||
self.device.bind_buffer_memory(self.instance_buffer, self.instance_memory, 0).expect("bind");
|
self.device
|
||||||
let ptr = self.device.map_memory(self.instance_memory, 0, inst_sz, vk::MemoryMapFlags::default()).expect("map");
|
.bind_buffer_memory(self.instance_buffer, self.instance_memory, 0)
|
||||||
|
.expect("bind");
|
||||||
|
let ptr = self
|
||||||
|
.device
|
||||||
|
.map_memory(
|
||||||
|
self.instance_memory,
|
||||||
|
0,
|
||||||
|
inst_sz,
|
||||||
|
vk::MemoryMapFlags::default(),
|
||||||
|
)
|
||||||
|
.expect("map");
|
||||||
ptr as *mut ColorInstance
|
ptr as *mut ColorInstance
|
||||||
};
|
};
|
||||||
self.instance_count = new_count;
|
self.instance_count = new_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy old swapchain
|
// Destroy old swapchain
|
||||||
unsafe { self.swapchain_loader.destroy_swapchain(self.swapchain, None); }
|
unsafe {
|
||||||
|
self.swapchain_loader
|
||||||
|
.destroy_swapchain(self.swapchain, None);
|
||||||
|
}
|
||||||
|
|
||||||
self.swapchain = new_swapchain;
|
self.swapchain = new_swapchain;
|
||||||
self.swapchain_image_views = new_views;
|
self.swapchain_image_views = new_views;
|
||||||
@@ -583,13 +923,22 @@ impl Drop for GraphicsRenderer {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = self.device.device_wait_idle();
|
let _ = self.device.device_wait_idle();
|
||||||
for &f in &self.in_flight { self.device.destroy_fence(f, None); }
|
for &f in &self.in_flight {
|
||||||
for &s in &self.image_available { self.device.destroy_semaphore(s, None); }
|
self.device.destroy_fence(f, None);
|
||||||
for &s in &self.render_finished { self.device.destroy_semaphore(s, None); }
|
}
|
||||||
|
for &s in &self.image_available {
|
||||||
|
self.device.destroy_semaphore(s, None);
|
||||||
|
}
|
||||||
|
for &s in &self.render_finished {
|
||||||
|
self.device.destroy_semaphore(s, None);
|
||||||
|
}
|
||||||
self.device.destroy_command_pool(self.command_pool, None);
|
self.device.destroy_command_pool(self.command_pool, None);
|
||||||
for &fb in &self.framebuffers { self.device.destroy_framebuffer(fb, None); }
|
for &fb in &self.framebuffers {
|
||||||
|
self.device.destroy_framebuffer(fb, None);
|
||||||
|
}
|
||||||
self.device.destroy_pipeline(self.pipeline, None);
|
self.device.destroy_pipeline(self.pipeline, None);
|
||||||
self.device.destroy_pipeline_layout(self.pipeline_layout, None);
|
self.device
|
||||||
|
.destroy_pipeline_layout(self.pipeline_layout, None);
|
||||||
self.device.destroy_render_pass(self.render_pass, None);
|
self.device.destroy_render_pass(self.render_pass, None);
|
||||||
self.device.destroy_buffer(self.instance_buffer, None);
|
self.device.destroy_buffer(self.instance_buffer, None);
|
||||||
self.device.free_memory(self.instance_memory, None);
|
self.device.free_memory(self.instance_memory, None);
|
||||||
@@ -597,8 +946,11 @@ impl Drop for GraphicsRenderer {
|
|||||||
self.device.free_memory(self.vertex_memory, None);
|
self.device.free_memory(self.vertex_memory, None);
|
||||||
self.device.destroy_buffer(self.index_buffer, None);
|
self.device.destroy_buffer(self.index_buffer, None);
|
||||||
self.device.free_memory(self.index_memory, None);
|
self.device.free_memory(self.index_memory, None);
|
||||||
for &v in &self.swapchain_image_views { self.device.destroy_image_view(v, None); }
|
for &v in &self.swapchain_image_views {
|
||||||
self.swapchain_loader.destroy_swapchain(self.swapchain, None);
|
self.device.destroy_image_view(v, None);
|
||||||
|
}
|
||||||
|
self.swapchain_loader
|
||||||
|
.destroy_swapchain(self.swapchain, None);
|
||||||
let sl = ash::khr::surface::Instance::new(&self.entry, &self.instance);
|
let sl = ash::khr::surface::Instance::new(&self.entry, &self.instance);
|
||||||
sl.destroy_surface(self.surface, None);
|
sl.destroy_surface(self.surface, None);
|
||||||
self.device.destroy_device(None);
|
self.device.destroy_device(None);
|
||||||
|
|||||||
+837
-233
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user