diff --git a/docs/renderer.md b/docs/renderer.md new file mode 100644 index 0000000..c23a4cc --- /dev/null +++ b/docs/renderer.md @@ -0,0 +1,168 @@ +# Renderer and repository guide + +## Repository overview + +Vidya is a Rust 2024 workspace containing a low-level Vulkan renderer, a Bevy-facing integration crate, small game/window crates, and a separate Bevy text crate. The root package is named `vidya`; the current runnable entry point is the `bevy_integration` example. The renderer is primarily an `ash`-based Vulkan layer, while `bevy_vulkan_render` sets up Bevy render-world infrastructure and currently contains a mock render system rather than a finished Bevy rendering backend. + +Line counts below are `wc -l` counts over Rust source files in each package (not generated/dependency code); for the renderer the 22 files total 14,100 lines. This source inventory differs from the supplied starting estimate of about 24,600 lines across 23 files: the current `crates/renderer/src` glob has 22 `.rs` files and their measured total is 14,100 lines. + +| Workspace member | Approx. Rust LOC | Purpose | +|---|---:|---| +| `crates/renderer` | 14,100 | Vulkan instance/device/resources, command recording, swapchains, render graph, egui and glyph-atlas code. | +| `crates/bevy_vulkan_render` | 1,518 | Bevy render sub-app, world synchronization/extraction, threaded scheduling, and window surfaces. | +| `crates/game` | 315 | Standalone winit/egui demo using `renderer::Renderer2`. | +| `crates/text` | 484 | Bevy asset/ECS-oriented text and font-atlas implementation built on `cosmic-text`. | +| `crates/window` | 1 | Minimal winit dependency crate; its `src/lib.rs` is empty. | +| root `vidya` package | 45 | Example host and dependency on `bevy_vulkan_render`; three lines of `src/lib.rs` plus the 42-line example. | + +The code has two overlapping integration paths: `crates/game` directly creates the renderer and surfaces; the root example constructs a Bevy `App` with Bevy's standard plugins plus `bevy_vulkan_render::RenderPlugin`. + +## Dependencies and toolchain + +| Area | Repository configuration | +|---|---| +| Rust | `rust-toolchain` pins `nightly`; packages use edition 2024. | +| Local Bevy | Workspace dependencies point to `/var/code/bevy-engine/bevy` and its crate directories, not crates.io: `bevy`, `bevy_app`, `bevy_asset`, `bevy_derive`, `bevy_ecs`, `bevy_hierarchy`, `bevy_log`, `bevy_math`, `bevy_platform`, `bevy_reflect`, `bevy_tasks`, `bevy_time`, `bevy_transform`, `bevy_utils`, `bevy_window`, and `bevy_winit`. This checkout is Bevy `0.20.0-dev` as recorded in the project setup. `bevy_ecs` enables `multi_threaded` and `trace`. | +| Vulkan/window | `ash 0.38.0`, `ash-formats` for Vulkan format metadata/helpers, including the adopted `FormatHelpers` sizing and clear-value helpers, `ash-window 0.13.0`, `vk-mem 0.5.0`, `gpu-allocator` from the `janis-bhm/gpu-allocator` GitHub `main` branch, `winit 0.30.5`, and `raw-window-handle 0.6`. Renderer allocation code specifically uses `gpu-allocator`; `vk-mem` is declared but is not the allocation path in `device.rs`, `buffers.rs`, or `images.rs`. | +| Shared crates | `glam 0.33` with `bytemuck`, `rand 0.10`, `derive_more 2`, `petgraph 0.8`, `egui 0.32`, `tracing`, `parking_lot`, among others. See root `[workspace.dependencies]` for the complete list. | +| Text | `cosmic-text 0.12.1`, `guillotiere 0.6.2`, and `sys-locale 0.3.2` are used in the renderer and/or text crate. | + +`crates/renderer/src/lib.rs` enables these nightly features (the `text` crate separately opts in to `debug_closure_helpers`): + +| Feature gate | Use visible in the code | +|---|---| +| `negative_impls` | Explicitly marks command pools/buffers and single-use command objects as `!Send`/`!Sync` where Vulkan command-pool thread ownership is constrained (`commands.rs`). | +| `map_try_insert` | Uses `BTreeMap::try_insert`/`HashMap::try_insert` in graph and resource bookkeeping. | +| `core_io` | Imports `core::io::BorrowedBuf` in the graph-builder egui demo. | +| `core_io_borrowed_buf` | Enables the borrowed-buffer fill APIs used alongside `BorrowedBuf` in that demo. | +| `slice_partition_dedup` | Deduplicates selected queue family indices in-place (`queue.rs`). | + +## Renderer crate + +### Public surface and code map + +`renderer/src/lib.rs` owns core device/feature types and exports `ash`, `instance`, `device`, `queue`, `commands`, `render_graph`, `rendering`, `swapchain`, `sync`, and `util`. `buffers`, `images`, `pipeline`, `text`, `debug`, and the egui implementation are declared as private modules. `egui.rs` is loaded as the private `egui_pass` module; `rendering` re-exports its two egui pass functions. The `render_graph` submodules are also private; `render_graph/mod.rs` currently re-exports the legacy graph API only. + +| Source | Responsibilities and key types | Relationship / visibility | +|---|---|---| +| [`lib.rs`](../crates/renderer/src/lib.rs) | Crate root, feature/property representations (`PhysicalDeviceFeatures`, `PhysicalDeviceProperties`, `PhysicalDeviceInfo`), `Error`/`Result`, `SamplerCache`, `EguiState`, `Renderer2`, and the internal texture manager. `Renderer2::new`, `create_surface`, and async `draw_graph` are the higher-level convenience flow. | Public exports and renderer assembly; creates the instance, adapter, device, graph, and submission/presentation flow. | +| [`instance.rs`](../crates/renderer/src/instance.rs) | Vulkan loader/instance setup (`Instance`, `InstanceDesc`, `DebugUtilsCreateInfo`), layer and extension selection, physical-device enumeration, adapter ranking via `choose_adapter_default`, and surface capability queries. | `Instance` is re-exported from crate root and hands `PhysicalDeviceInfo` to `device.rs`. | +| [`device.rs`](../crates/renderer/src/device.rs) | Logical `Device`/`DeviceInner`, required extensions and feature chain, GPU allocator, device object lifetime helpers (`DeviceOwned`, `DeviceObject` family), resource allocation types (`Allocation`, `AllocationStrategy`), and reusable device pools. | Adapter creation calls into `queue.rs`, sets up queues and `gpu_allocator`, and is held by buffers, images, commands, and sync objects. | +| [`queue.rs`](../crates/renderer/src/queue.rs) | `Queue`, `QueueFamily`, `DeviceQueues`, `DeviceQueueInfos`, queue capability flags and family selection. | Called by logical device initialization; supplies graphics/main, compute and transfer queues to the device. | +| [`buffers.rs`](../crates/renderer/src/buffers.rs) | `BufferDesc` and `Buffer`: Vulkan buffer creation, queue-sharing mode, memory allocation/binding, optional mapped `map`/`map_mut`, raw handle and length. | Private module; used by commands, renderer helpers, graph implementations and egui uploads. | +| [`images.rs`](../crates/renderer/src/images.rs) | `ImageDesc`, `Image`, `ImageViewDesc`, `ImageView`, `Extent`, `Offset`, `MipRange`, `QueueOwnership`. Uses `ash-formats` format metadata. Handles owned and swapchain images, memory, views, extents and subresources. | Private module; swapchains wrap their external images here. Used by render graph and egui. | +| [`memory.rs`](../crates/renderer/src/memory.rs) | Empty placeholder (one blank line). | Not an allocation implementation; allocation is in `device.rs` and resource constructors. | +| [`pipeline.rs`](../crates/renderer/src/pipeline.rs) | Descriptor/pipeline descriptions and objects: `DescriptorPool`, `DescriptorSetLayout`, `PipelineLayout`, `Sampler`, `ShaderModule`, `Pipeline`, `PipelineCache`; supports compute and graphics pipeline construction. `ShaderModule::new_from_path` reads SPIR-V words and `new_from_memory` accepts words directly. | Private module; `commands.rs` binds pipelines/descriptors; `EguiState` and rendering helpers build concrete pipelines. No shader compiler/build pipeline is defined here. | +| [`commands.rs`](../crates/renderer/src/commands.rs) | Low-level command-pool and command-buffer abstractions (`SingleUseCommandPool`, `CommandList`, command-buffer types/state, `CommandBufferExt`), recording/copy/barrier operations and queue submission/futures. | The legacy graph and one-off uploads use these command buffers; synchronization objects come from `sync.rs`. | +| [`swapchain.rs`](../crates/renderer/src/swapchain.rs) | `Surface`, `Swapchain`, `SwapchainConfiguration`, `SwapchainImage`, `SwapchainFrame`; creates/configures surfaces and swapchains, acquires images, and presents them. | Surface owns a replaceable optional swapchain. Swapchain images are represented by `images::Image`/`ImageView`; uses `Fence` and semaphores. | +| [`sync.rs`](../crates/renderer/src/sync.rs) | `Fence`, binary/timeline `Semaphore`, `SyncThreadpool`, `FenceFuture`, and pooled synchronization objects. | The swapchain and command submission code use fences/semaphores; `DeviceInner` owns a sync waiter pool and device pools. | +| [`render_graph/mod.rs`](../crates/renderer/src/render_graph/mod.rs) | Declares `legacy`, `commands`, `graph_builder`, `recorder`, and `resources`; re-exports `legacy::*`. | Despite the internal new graph files, the externally reachable `RenderGraph` is the `legacy.rs` implementation. `#![allow(dead_code)]` covers the module tree. | +| [`render_graph/legacy.rs`](../crates/renderer/src/render_graph/legacy.rs) | Current reachable graph API: `RenderGraph`, `GraphResourceId`, `GraphResourceDesc`, `GraphResource`, `PassDesc`, `RenderContext`, `Access`, load/store ops and helpers such as `clear_pass`/`present_pass`. Stores imported/created resources, pass access declarations and output resources; `resolve` orders passes and records a `CommandList` for its caller to submit. | Re-exported by `render_graph/mod.rs`; used by `Renderer2::draw_graph`, `rendering/mod.rs` and `egui.rs`. Although named legacy, this is the path called by the current rendering code. | +| [`render_graph/resources.rs`](../crates/renderer/src/render_graph/resources.rs) | Newer command-graph resource abstraction: `Resource`, `ResourceId`, ranges/access records, `Buffer`/`Texture` handles and slices/regions, `Read`/`Write`/`ReadWrite` wrappers. | Internal to newer `commands.rs`/`recorder.rs`; not re-exported from `render_graph/mod.rs`. | +| [`render_graph/commands.rs`](../crates/renderer/src/render_graph/commands.rs) | New command API (`Command`, `ImportResource`, `Copy`, `ClearTexture`, `UpdateBuffer`, rendering/pipeline/buffer/descriptor/draw commands, `PipelineBarrier`); each command declares resource side effects and implements recording. | Uses newer resource wrappers and `CommandRecorder`, separate from the currently re-exported legacy `PassDesc` graph. Several commands remain incomplete; see current state. | +| [`render_graph/recorder.rs`](../crates/renderer/src/render_graph/recorder.rs) | New `CommandRecorder`, `CommandList`, `RenderPass`, side-effect maps, command metadata and access/barrier collection. | Intended to translate new graph commands to Vulkan command buffers; recorder resource lookups and barrier application contain explicit unimplemented code. | +| [`render_graph/graph_builder.rs`](../crates/renderer/src/render_graph/graph_builder.rs) | New `GraphResourceRegistry` and `GraphBuilder`, wrappers for buffer and staging resources, plus an `api_demo::egui_graph` sample that packs vertices/indices/draw data with `BorrowedBuf`. | Not a wired-up implementation of the current legacy graph: the resource-creation methods are `todo!()` and part of the sample is `unimplemented!()`. | +| [`rendering/mod.rs`](../crates/renderer/src/rendering/mod.rs) | `Wireframe` GPU data/pipeline example and `Wireframe::pass`; exports `egui_pre_pass` and `egui_pass` from the egui module. | Builds passes on the legacy `RenderGraph`; uses `Buffer`, `Pipeline`, graph access declarations, and commands. | +| [`egui.rs`](../crates/renderer/src/egui.rs) | `egui_pre_pass` uploads egui texture deltas (including staging/atlas packing) and `egui_pass` adds drawing work; uses `EguiState`, texture IDs, buffers, images, samplers, pipeline, and graph commands. | Private module imported by `rendering/mod.rs`; current code exercises the legacy graph, not the in-progress typed graph API. | +| [`text.rs`](../crates/renderer/src/text.rs) | Private glyph rasterization and atlas data structures (`FontId`, font stores/atlas sets, `get_outlined_glyph_texture`) based on `cosmic-text` and `guillotiere`. Embeds `assets/fonts/Roboto.ttf` and `NotoSansSC.ttf`. | Renderer-local/private text implementation; not the same module as the public Bevy-oriented `crates/text` crate. Contains an unfinished subpixel-mask case. | +| [`util.rs`](../crates/renderer/src/util.rs) | Shared Vulkan helpers and data types (`DebugName`, `Rect2D`, `F32`, `Rgba`, `Rgba8`, bit iterators, `CStringList`, drop/lifetime helpers and internal `WeakVec`). | Used across resource, debug, image and graph code. | +| [`debug.rs`](../crates/renderer/src/debug.rs) | Vulkan debug messenger callback, translating validation severities into `tracing` levels. | Used by instance setup; intentionally private. | + +### Initialization, resources, and commands + +The normal setup path begins with `Instance::new(&InstanceDesc)` (`instance.rs`), which loads Vulkan through `ash`, enables supported requested/WSI extensions and creates debug-utils state. The default description requests surface support and the Khronos validation layer/settings (unsupported layers are logged and filtered). Adapter enumeration exposes device properties/features as `PhysicalDeviceInfo`. + +`Instance::choose_adapter_default(surface, required_extensions, required_features)` ranks adapters. Its comparator attempts to prefer swapchain/required-extension support and requested `PhysicalDeviceFeatures`, requires preference for Vulkan 1.3 `synchronization2`, `dynamic_rendering`, and `maintenance4`, then prefers discrete GPUs, newer API versions, more device-local memory, and larger 2D image limits. It is ranking logic, not a robust suitability filter: required extension checks return `Less` for the left-hand candidate rather than first excluding every unsuitable device, and `create_logical_device` warns and omits unsupported requested extensions. An important limitation visible in code: the `surface` argument is currently ignored at the `// TODO` surface-compatibility check; choosing an adapter does not actually validate that it can present to that surface. `PhysicalDeviceFeatures` is a chain of core and version/extension feature structs; `create_logical_device` pushes those into `vk::DeviceCreateInfo`. + +`PhysicalDeviceInfo::create_logical_device` asks `DeviceQueueInfos::select_queue_families` for queue families, creates the logical device, retrieves queues, creates extension loaders, then creates `gpu_allocator::vulkan::Allocator` and resource pools. Queue selection chooses the first family containing both `GRAPHICS` and `COMPUTE`, decrements its available queue count, and asserts that this selected family has `PRESENT`. It then takes another available compute family and transfer family if found; missing compute/transfer queues alias the graphics queue. Therefore a display handle that did not produce presentation support can reach the explicit `Selected graphics queue family does not support presentation` assertion. The presentation flags are derived from a display handle, and the queue-selection path is not a general strategy for selecting a distinct present-only family. + +The allocator is stored behind a mutex on `DeviceInner`. Both `Buffer::new` and `Image::new` create the Vulkan object, query memory requirements, allocate using `AllocationStrategy::{AllocatorManaged,Dedicated}`, bind the returned allocation, and retain it for destruction. `BufferDesc`/`ImageDesc` include memory location, usage, queue family flags and allocation strategy. Buffers may expose mapped bytes when the allocator returns a mapped allocation. Images also support externally owned swapchain images and cached weak image-view references. `memory.rs` itself has no implementation. + +There is no universal upload subsystem in `buffers.rs`/`images.rs`; upload paths are explicit at call sites. For example, `Wireframe::from_triangles_indexed` writes positions/indices/colors to a `CpuToGpu` staging buffer, copies into `GpuOnly` vertex/index buffers via a one-off command buffer, and adds transfer-to-vertex/index barriers. The egui pre-pass similarly writes texture data to mapped staging storage and records graph copy work. Shader modules load SPIR-V from a path or word slice; pipeline creation consumes `GraphicsPipelineDesc` or `ComputePipelineDesc`, descriptor layouts/pools, and optional `PipelineCache`. Shader source compilation is outside this crate's code. + +### Surfaces, frames, and synchronization + +`Surface::new_from_raw_window_handle` creates a Vulkan surface from raw handles; `Surface::headless` is also defined. `Surface::configure` avoids recreation for an equal config on the same device, otherwise creates a replacement swapchain using the old swapchain handle. `SwapchainConfiguration` includes extent/format/present mode/usage and image-count options, while capability validation chooses compatible settings. Acquiring a frame asynchronously reserves a per-frame acquire semaphore, performs `acquire_next_image` through `smol::unblock` under the swapchain lock, creates an `Image` and view for the acquired swapchain image, and waits on a fence. `SwapchainImage` and `SwapchainFrame` are `must_use` and expose `present`. + +Swapchain synchronization is not just a generic frame fence ring: the implementation creates acquire semaphores based on the number of in-flight frames and a release semaphore for every swapchain image. Submission waits on the acquire semaphore and signals the release semaphore; presentation waits on the release semaphore. `Swapchain::max_in_flight_images` is image count minus the surface minimum image count. The general `sync.rs` API also supports dedicated/pooled fences, binary/timeline semaphores, and fence futures serviced by a bounded waiter thread pool. `Renderer2::draw_graph` demonstrates acquire → import framebuffer → graph resolve → submit using acquire/release semaphores → await → present. + +### Render graph: current path and in-progress path + +The currently wired graph is `render_graph::legacy::RenderGraph`, re-exported by `render_graph/mod.rs`. It owns resources and `PassDesc`s with declared read/write `Access` values and optional one-shot `RecordFn`s. Imported framebuffer/images/buffers and created resource descriptions receive graph IDs. Outputs are marked explicitly; resolution determines which passes feed outputs and prepares resources/barriers before executing recorded passes. `Renderer2::draw_graph` constructs this graph and calls `resolve`; the wireframe and egui rendering functions add passes to it. In `legacy.rs`, comments discuss future resource aliasing, but should not be read as proof that aliasing is fully implemented. + +The sibling `resources.rs`, `commands.rs`, `recorder.rs`, and `graph_builder.rs` form a newer typed command/resource design, but are private submodules and are not re-exported or connected to the root `RenderGraph` API. `resources.rs` tracks buffer/image ranges and stage/access/layout side effects; `commands.rs` describes copies, clears, updates, rendering scopes, binding, draws and barriers; `recorder.rs` is intended to lower command lists and insert transitions; `graph_builder.rs` contains the graph-resource registry and a sample upload/build path. That path uses staging buffers and `core::io::BorrowedBuf` for writing several egui draw-data arrays into one mapped region. However, the builder methods that create command lists and make/import buffers are `todo!()`, and the recorder still has unimplemented handle accessors/barrier code. Treat this as an experimental/incomplete path, not as the graph used by `draw_graph`. + +### Text, egui, and orchestration + +The renderer's private `text.rs` embeds two font files and manages per-font/per-size glyph atlases; `get_outlined_glyph_texture` rasterizes glyphs through `cosmic-text`/Swash and packs masks/color glyphs. It is separate from `crates/text/src/lib.rs`, which defines a Bevy `FontData` asset, font loader, ECS text component and its own atlas machinery. Both source trees embed font paths from `assets/fonts`. + +The renderer egui path in `egui.rs` consumes `egui::FullOutput`: texture deltas are converted to image/atlas staging uploads, and tessellated primitives are emitted as rendering passes using the egui pipeline and descriptor state. `rendering/mod.rs` re-exports `egui_pre_pass` and `egui_pass` alongside the `Wireframe` graph pass. `Renderer2` is a direct-use convenience owner for instance/device/samplers/textures/egui state and surfaces; its `draw_graph` orchestrates one frame. Bevy has a separate plugin/schedule integration and currently does not call this orchestration as an active render backend. + +## Bevy integration crate + +`crates/bevy_vulkan_render/src/lib.rs` declares `RenderPlugin`, the `RenderApp` sub-app label, `Render` and `RenderStartup` schedules, and ordered `RenderSystems` sets (`ExtractCommands`, `Prepare`, `Render`, `Cleanup`, `PostCleanup`). `RenderPlugin::build` adds `ExtractPlugin`, initializes render schedules on the sub-app and installs `mock_render_system`. `RenderDevice` is a Bevy resource wrapper around `renderer::device::Device`. An `init_vulkan` function exists and requests sampler anisotropy, non-solid fill, multi-draw-indirect, Vulkan 1.1/1.2/1.3 features and mesh shaders, but it is unused according to both source and compiler dead-code warnings. + +`extract_plugin.rs` creates the `RenderApp` `SubApp`, installs `ExtractSchedule`, and arranges sync/extract each frame. It moves the main `World` into a temporary `MainWorld` resource for extraction, restores it afterward, and delays `ExtractSchedule` deferred-command application into the render schedule's `ExtractCommands` set. This leaves the main thread free earlier for pipelining. + +`extract_param.rs` defines `Extract<'w, 's, P>`, a `SystemParam` wrapper for applying a read-only system parameter to `MainWorld` during `ExtractSchedule`. It registers read-only main-world access and intentionally disallows contained mutating system params. + +`sync_world.rs` implements `SyncWorldPlugin` and the `SyncToRenderWorld` marker. Observer records are processed by `entity_sync_system` to maintain the main/render entity link: `RenderEntity` on the main side points to the render entity; `MainEntity` points back. Custom `QueryData` implementations let `Query` and `Query` return the wrapped `Entity` directly. Temporary render entities are despawned in post-cleanup. A TODO calls out batching pending sync records. + +`window/mod.rs` holds extracted physical window metadata in `ExtractedWindows`, keyed by entity, and stores a `Surfaces` map keyed per window entity. `extract_windows` tracks primary window, dimensions, closing/removal, and initial presentation state. `need_surface_configuration` detects new/unconfigured or resized windows; `configure_surfaces` creates a `Surface` from the raw handles and configures/reconfigures its swapchain. These functions and resources are currently reported unused by the compiler, so their source structure is present but not yet integrated into active plugin systems. + +`rendering.rs` defines `RenderingPlugin` and `RenderExtractApp`. When installed after `RenderPlugin`, it transfers the `RenderApp` between the main app and a spawned render thread using bounded async channels, executes render-app updates there, and extracts/sends it back each frame. The root example installs `RenderPlugin`, but does not install `RenderingPlugin`; the current `RenderPlugin` only installs a mock render function. + +## Current state and known unfinished work + +### Build and warnings + +On the checked-out tree, `cargo check --workspace --all-targets` completes successfully. It emits warnings, including deprecated `glam::Mat4::perspective_lh` and `Mat4::look_at_rh` calls in `rendering/mod.rs`, a deprecated standard-library atomic `fetch_update` use, unused imports/variables, and dead code. Specifically, compiler warnings expose that `init_vulkan`, the window extraction/configuration functions, `render_start`/`render_startup`, and parts of sync tracking are unused. This is a compile check, not evidence that a Vulkan device/surface runs successfully on a target machine. + +### Marker inventory (source scan) + +Across `crates/renderer/src`, `crates/bevy_vulkan_render/src`, `crates/game/src`, and `crates/text/src`, a literal scan finds **21 `TODO`/`FIXME` occurrences** and **19 `todo!`/`unimplemented!` occurrences**. The latter includes test-only code; it does not imply 19 active runtime paths. The locations and notable behaviors are: + +| File / lines | Finding | +|---|---| +| `renderer/src/instance.rs:368` | Surface compatibility in default adapter ranking is a TODO; `:474` XCB presentation support is `todo!("xcb")`. | +| `renderer/src/queue.rs:326-329` | Explicit assertion requires selected graphics+compute family to present. | +| `renderer/src/render_graph/graph_builder.rs:41,44,53,59` | New builder methods are `todo!()`; `:266` has an `unimplemented!()` factory in the demo path. | +| `renderer/src/render_graph/recorder.rs:23,27,31,35,39,43,344` | `CommandRecorder` accessors and image barrier recording are unimplemented/todo. `:339` also notes missing image aspect information. | +| `renderer/src/render_graph/commands.rs:316,592` | Render load/store operations are noted as TODO; `PipelineBarrier::apply` is `todo!()`. | +| `renderer/src/render_graph/resources.rs:46,250` | TODOs flag buffer-row range units and possible write-order conflict handling. | +| `renderer/src/render_graph/legacy.rs:799,809` | TODOs in graph hazard/dependency handling for first-pass checks. | +| `renderer/src/text.rs:71,162,281-282` | Atlas naming, host-visible/coherent image considerations, and `SubpixelMask` glyph content remain TODO/todo. | +| `renderer/src/sync.rs:361,373` | `vk::Handle::from_raw` for binary and timeline semaphore wrappers is unimplemented. | +| `renderer/src/device.rs:1107-1113` | A `#[cfg(test)]` helper contains a `summon` stub with `unimplemented!()`; test-only. | +| `renderer/src/lib.rs:610`; `swapchain.rs:593`; `commands.rs:749`; `egui.rs:320` | Additional behavior/design TODO comments; swapchain present-id/wait support is noted as optional work. | +| `bevy_vulkan_render/src/sync_world.rs:217` | TODO to batch pending sync records. | +| `game/src/main.rs:49,58,85` | TODOs call out error handling, resize handling and unfinished draw-request logging/path. | +| `text/src/lib.rs:123,214,336-337` | Separate Bevy text implementation has similar atlas/image TODOs and an unfinished subpixel-mask case. | + +The largest architectural caveat is that the typed `render_graph` command/recorder/builder files are not active wiring: the legacy graph is still the sole graph re-export, and the new recorder contains explicit stubs. The Bevy crate likewise has substantial extraction/window/thread infrastructure, but its current installed render schedule uses a mock system and its Vulkan initializer/surface functions are unused. Bevy-facing rendering should therefore be described as scaffolding/integration work in progress rather than a complete rendered-frame backend. + +## Build and run + +1. Use the repository's nightly toolchain (`rustup` will honor `rust-toolchain`). The renderer has compile-time `include_bytes!` references to font files; the repository currently contains the generated flat and directory layouts. To regenerate the expected layouts, run the fetch script from the font directory: + + ```sh + cd assets/fonts + ./fetch.sh + cd ../.. + ``` + + `fetch.sh` downloads the upstream Google Fonts files; network access is needed only for this prerequisite. It creates `Roboto/Roboto-VariableFont_wdth,wght.ttf` and `Noto_Sans_SC/NotoSansSC-VariableFont_wght.ttf` from flat files. Renderer-local text also includes flat `Roboto.ttf` and `NotoSansSC.ttf`. + +2. Check the workspace and all targets: + + ```sh + cargo check --workspace --all-targets + ``` + +3. Run the Bevy example: + + ```sh + cargo run --example bevy_integration + ``` + + The example creates a Bevy app with minimal, asset, window/winit, camera/mesh/text and `VulkanRenderPlugin` plugins. It currently prints `Hello, world!` before running; the installed Vulkan render plugin uses a mock render system. For direct renderer/egui experimentation, `crates/game/src/main.rs` is the standalone winit entry point, though it too has TODO-marked draw/resize work and requires a Vulkan-capable system/display.