-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Overview
Buffer defaults bias toward CPU-visible memory (adds COPY_DST), even for static vertex buffers that are uploaded once and never modified. This results in suboptimal memory placement on discrete GPUs and unnecessary overhead. Static geometry should default to DEVICE_LOCAL memory, with CPU-visible properties reserved for buffers that require CPU updates (uniform streams, dynamic meshes).
Current State
Properties::default() returns CPU_VISIBLE:
// crates/lambda-rs/src/render/buffer.rs
impl Default for Properties {
fn default() -> Self {
Properties::CPU_VISIBLE
}
}Additionally, build_from_mesh hardcodes CPU_VISIBLE for vertex buffers created from meshes:
// crates/lambda-rs/src/render/buffer.rs
pub fn build_from_mesh(
mesh: &Mesh,
gpu: &Gpu,
) -> Result<Buffer, &'static str> {
let builder = Self::new();
return builder
.with_length(std::mem::size_of_val(mesh.vertices()))
.with_usage(Usage::VERTEX)
.with_properties(Properties::CPU_VISIBLE)
.with_buffer_type(BufferType::Vertex)
.build(gpu, mesh.vertices().to_vec());
}This means static meshes that are loaded once and never modified are placed in CPU-visible memory, which on discrete GPUs means system RAM accessed over PCIe rather than fast VRAM.
Scope
Goals:
- Default
PropertiestoDEVICE_LOCALfor optimal GPU performance - Update
build_from_meshto useDEVICE_LOCAL - Provide clear guidance on when to use
CPU_VISIBLEvsDEVICE_LOCAL
Non-Goals:
- Automatic memory tier selection based on update frequency
- Staging buffer abstraction for uploads (future work)
Proposed API
// crates/lambda-rs/src/render/buffer.rs
impl Default for Properties {
fn default() -> Self {
Properties::DEVICE_LOCAL // Changed from CPU_VISIBLE
}
}
// build_from_mesh updated to use DEVICE_LOCAL
pub fn build_from_mesh(
mesh: &Mesh,
gpu: &Gpu,
) -> Result<Buffer, &'static str> {
let builder = Self::new();
return builder
.with_length(std::mem::size_of_val(mesh.vertices()))
.with_usage(Usage::VERTEX)
.with_properties(Properties::DEVICE_LOCAL) // Changed from CPU_VISIBLE
.with_buffer_type(BufferType::Vertex)
.build(gpu, mesh.vertices().to_vec());
}Usage guidance:
// Static geometry (loaded once, never updated) - use default DEVICE_LOCAL
let static_mesh_buffer = BufferBuilder::new()
.with_usage(Usage::VERTEX)
.build(&gpu, vertices)?;
// Dynamic geometry (updated per-frame) - explicit CPU_VISIBLE
let dynamic_buffer = BufferBuilder::new()
.with_usage(Usage::VERTEX)
.with_properties(Properties::CPU_VISIBLE)
.build(&gpu, initial_vertices)?;
// Uniform buffers (updated frequently) - explicit CPU_VISIBLE
let uniform_buffer = BufferBuilder::new()
.with_usage(Usage::UNIFORM)
.with_properties(Properties::CPU_VISIBLE)
.build(&gpu, uniform_data)?;Acceptance Criteria
-
Properties::default()returnsDEVICE_LOCAL -
build_from_meshusesDEVICE_LOCAL - Documentation updated explaining
DEVICE_LOCALvsCPU_VISIBLEtradeoffs - Examples using uniform buffers explicitly specify
CPU_VISIBLE - Migration guide for users relying on implicit
CPU_VISIBLE - Unit tests updated to reflect new defaults
Affected Crates
lambda-rs
Notes
- This is a breaking change for users who rely on implicit
CPU_VISIBLEfor buffers they update from the CPU - Migration: add explicit
.with_properties(Properties::CPU_VISIBLE)for dynamic buffers - Future work: staging buffer helper for efficient DEVICE_LOCAL uploads
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request