# renderer_resources ## Purpose `renderer_resources` owns Vulkan buffer, image, view, descriptor, sampler, shader-module, and pipeline construction on the `renderer_device` layer. It handles resource memory and handle lifetimes, but contains no window, swapchain, or presentation orchestration; those remain in `renderer`. It must not depend on `renderer`. ## Module map - `lib.rs`: re-exports `Device`, `Error`, `Result`, `device`, and `make_extension` from `renderer_device`; declares four public resource modules. - `buffers.rs`: `BufferDesc` and `Buffer`; Vulkan buffer creation, GPU allocation/binding, raw access, and host mapping. - `images.rs`: `ImageDesc`, `Image`, `ImageViewDesc`, `ImageView`, subresource ranges, extents, offsets, and queue ownership. `ImageInner` distinguishes allocated images from borrowed swapchain images. - `pipeline.rs`: shader-stage and graphics/compute pipeline descriptions; `DescriptorPool`, `DescriptorSetLayout`, `PipelineLayout`, `Sampler`, `ShaderModule`, and `Pipeline`. - `util.rs`: `eq_f32`, `ord_f32`, `hash_f32`, `F32`, and the crate-private `weak_vec` module / `WeakVec` used by image view tracking. ## Key types and API - These modules are public from `renderer_resources`; the crate root re-exports the core device types and `device` module from `renderer_device` for resource construction. - `BufferDesc` configures Vulkan buffer flags, size, usage, queue families, memory location, allocation strategy, and optional debug name. `Buffer::new` allocates/binds memory; `map` and `map_mut` return mapped slices when available. - `Buffer::raw` returns the Vulkan handle and `len` returns the configured size. Mapping is bounded to the descriptor size, not the allocator block size. - `ImageDesc` configures image type, format, extent, layers/mips, samples, tiling, usage, initial layout, queue sharing, and allocation. - `Image::new` creates an allocated image. `Image::new_with_allocation` accepts an explicit `renderer_device::device::Allocation` and validates size and memory-type compatibility. - `Image::from_swapchain_raw(image, device, format, extent, usage)` builds an image wrapper for an image owned by a swapchain; renderer calls it from `Swapchain::acquire_image`. - `ImageViewDesc` describes a view's type, format, component mapping, aspect, mip range, and layer range. `Image::create_view` validates compatibility and returns `ManuallyDrop`. - `Image::create_view` resolves remaining mip/layer sentinels against the parent image, defaults an undefined view format to the image format, and checks image/view kind and format compatibility. - `Extent`, `Offset`, and `MipRange` represent image dimensions, offsets, and mip/layer ranges. `QueueOwnership` carries source and destination family indices. - `Image` exposes its raw handle, format, dimensions, and optional allocation; swapchain-backed images have no allocation. - Pipeline configuration records include `ShaderStageDesc`, `GraphicsPipelineDesc`, `ComputePipelineDesc`, `PipelineLayoutDesc`, `DescriptorSetLayoutDesc`, `DescriptorSetLayoutBindingDesc`, `DescriptorPoolDesc`, `DescriptorSetAllocDesc`, `SamplerDesc`, and fixed-function state descriptions. - Fixed-function state records are `VertexInputState`, `TessellationState`, `InputAssemblyState`, `ViewportState`, `DepthBiasState`, `RasterizationState`, `MultisampleState`, `DepthBounds`, `DepthState`, `StencilState`, `DepthStencilState`, `ColorBlendState`, `RenderingState`, and `DynamicState`. - `Pipeline` wraps graphics or compute Vulkan pipelines and retains its `PipelineLayout` in an `Arc`. Creation uses `device.pools.pipeline_cache.raw`. - `DescriptorPool` serializes allocation/reset with a mutex; descriptor set layouts and pipeline layouts own their Vulkan handles. - `DescriptorPool::allocate` returns raw descriptor-set handles from the provided `DescriptorSetLayout` values and optionally assigns names from `DescriptorSetAllocDesc`. - `DescriptorSetLayout::new` applies per-binding descriptor flags when the device supports Vulkan 1.2 or `VK_EXT_descriptor_indexing`. - `PipelineLayoutDesc` references descriptor-set layouts and push-constant ranges; `PipelineLayout` owns the created Vulkan layout. - `SamplerDesc` describes filtering, addressing, anisotropy, compare, LOD, and border settings; `Sampler::new` creates the Vulkan sampler. - `ShaderModule::new_from_path` reads a shader file relative to the process working directory; file-open failures map to `Error::AssetMissing`, while read/Vulkan failures use their corresponding `Error` conversions. `new_from_memory` accepts SPIR-V words. - `GraphicsPipelineDesc` supports render-pass/subpass inputs or dynamic `RenderingState`; optional fixed-function states are converted during pipeline creation. - `SamplerDesc` uses `eq_f32` / `hash_f32` for float-valued fields. `F32` provides `Eq`/`Ord`/`Hash` semantics using the same helpers. - `WeakVec` stores `Weak` references and prunes entries whose strong count is zero when growing; it is crate-private, not public API. ## Invariants and gotchas - This crate consumes the `renderer_device` ownership types and re-exports; do not add a parallel device model or a dependency on `renderer`. - `Image::from_swapchain_raw` stores the raw image in the `ImageInner::Swapchain` variant with its device. The swapchain owns that Vulkan image; never destroy it as an independently allocated image. - `from_swapchain_raw` records a 2D, one-mip, one-layer, single-sample, optimal-tiled image with PRESENT queue sharing and UNDEFINED initial layout; the caller supplies format, extent, and usage. - `from_swapchain_raw` retains a `Device` for views and device queries, but not ownership of the image handle or swapchain lifetime; the renderer's frame/swapchain token must keep the swapchain alive. - Allocated images and buffers use `DeviceObject` for Vulkan handles and allocation ownership. Keep resource destruction ordered before freeing bound memory. - `Buffer` equality compares the raw buffer handle; `Image` equality compares the raw image handle. Descriptor equality is separate from resource object identity. - `Allocation::Owned` owns a device-managed allocation; `Shared` shares it through `Arc` and permits mutable access only when uniquely held; `Unmanaged` carries no allocation. - `ImageView` retains `Arc` so the source image outlives the view. `Image::create_view` returns `ManuallyDrop`; callers must transfer/drop it deliberately. - `Image` tracks views through `WeakVec` to avoid a strong-reference cycle. The weak list does not keep views alive. - `ImageView`'s `DeviceObject` owns and destroys the Vulkan view; its parent `Arc` must remain alive through view destruction. - `ImageDesc` and `BufferDesc` omit `alloc_scheme` from both `Hash` and `Eq`; their `Hash` implementations omit `name`, and `Eq` also omits `name`. Do not treat these descriptors as complete resource identities without accounting for these fields. - Descriptor hashing/equality covers resource shape, usage, sharing, and memory location but not every construction input. Update both implementations together if adding descriptor-keyed resource deduplication. - `Pipeline` retains its layout with `Arc`; descriptor-pool operations are mutex-serialized. Keep these lifetime and synchronization guarantees when changing constructors or wrappers. - `DescriptorPool::allocate` returns raw `vk::DescriptorSet` handles; keep the owning pool alive while those sets are in use. Descriptor sets are not wrapped in owning resource objects here. - Descriptor-set layout binding flags are chained into layout creation when the device API version or descriptor-indexing extension supports them. - Pipeline cache lifetime and teardown belong to `renderer_device`; use the device's existing cache rather than adding a resource-crate cache. - Renderer shader assets remain under `crates/renderer/shaders`; this crate does not own those assets. - `renderer` accesses these modules through crate-private aliases. Making a resource type available in `renderer`'s public API requires an explicit API/re-export decision there. ## Conventions - `renderer_resources` has no crate-level nightly feature attributes; use APIs available under the workspace's pinned nightly toolchain and edition 2024. - Depend on `renderer_device` paths re-exported at this crate root (`crate::Device`, `crate::device::...`, and `crate::make_extension`) rather than introducing a dependency on `renderer`. - Do not commit changes. Verify with `cargo check -p renderer_resources` and `cargo check --workspace` from the workspace root. ## Change guidance - Add buffer, image, view, descriptor, sampler, shader, and pipeline constructors in this crate, not in `renderer`'s orchestration layer. - For each Vulkan handle, preserve the distinction between resource-owned handles and externally owned handles such as raw swapchain images. - Keep image-view range/format/kind validation close to image/view construction. Cover `REMAINING_MIP_LEVELS` and `REMAINING_ARRAY_LAYERS` normalization when changing range handling. - When modifying descriptor equality/hash behavior, update both together and account for `name` and `alloc_scheme` deliberately. - Preserve `renderer_device::device::Allocation` ownership semantics when accepting shared or unmanaged memory; ensure bound resources outlive their allocation use. - Keep `SamplerDesc` float equality and hashing consistent across every float field. - `renderer_resources::util::weak_vec` is internal support for images; do not expose or move it back into `renderer` without reviewing view ownership cycles. - Keep shader loading errors compatible with `renderer_device::Error`, and test path-based loading relative to the workspace runtime working directory. - Keep this crate independent of swapchain/window wrappers. Integrate swapchain images through the raw image plus explicit device, format, extent, and usage, not renderer types. - Keep pipeline descriptors, Vulkan state conversion, and handle ownership in this crate rather than moving resource ownership back into renderer orchestration.