From 7bb76ab74b1ee0609e414b054a5ea1153f587896 Mon Sep 17 00:00:00 2001 From: Sludge Date: Mon, 26 Aug 2024 19:54:33 +0200 Subject: [PATCH] Add `VertexBufferLayout::offset_locations` (#9805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective When using instancing, 2 `VertexBufferLayout`s are needed, one for per-vertex and one for per-instance data. Shader locations of all attributes must not overlap, so one of the layouts needs to start its locations at an offset. However, `VertexBufferLayout::from_vertex_formats` will always start locations at 0, requiring manual adjustment, which is currently pretty verbose. ## Solution Add `VertexBufferLayout::offset_locations`, which adds an offset to all attribute locations. Code using this method looks like this: ```rust VertexState { shader: BACKBUFFER_SHADER_HANDLE.typed(), shader_defs: Vec::new(), entry_point: "vertex".into(), buffers: vec![ VertexBufferLayout::from_vertex_formats( VertexStepMode::Vertex, [VertexFormat::Float32x2], ), VertexBufferLayout::from_vertex_formats( VertexStepMode::Instance, [VertexFormat::Float32x2, VertexFormat::Float32x3], ) .offset_locations(1), ], } ``` Alternative solutions include: - Pass the starting location to `from_vertex_formats` – this is a bit simpler than my solution here, but most calls don't need an offset, so they'd always pass 0 there. - Do nothing and make the user hand-write this. --- ## Changelog - Add `VertexBufferLayout::offset_locations` to simplify buffer layout construction when using instancing. --------- Co-authored-by: Nicola Papale Co-authored-by: Alice Cecile --- crates/bevy_render/src/render_resource/pipeline.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/bevy_render/src/render_resource/pipeline.rs b/crates/bevy_render/src/render_resource/pipeline.rs index 8eafdaf289..93f76d3f56 100644 --- a/crates/bevy_render/src/render_resource/pipeline.rs +++ b/crates/bevy_render/src/render_resource/pipeline.rs @@ -158,6 +158,15 @@ impl VertexBufferLayout { attributes, } } + + /// Returns a [`VertexBufferLayout`] with the shader location of every attribute offset by + /// `location`. + pub fn offset_locations_by(mut self, location: u32) -> Self { + self.attributes.iter_mut().for_each(|attr| { + attr.shader_location += location; + }); + self + } } /// Describes the fragment process in a render pipeline.