Skip to content

Commit 8e15297

Browse files
committed
Add vertex buffer attribute descriptors to resolve sorting issues
- Vertex attribute buffer descriptors can be set as a resource (typed with `Mesh` and `SpriteBatch`, for 3D and 2D renderers respectively) to override the vertex attribute buffer layout at runtime. Defaults to sane layouts provided by `Mesh` and `SpriteBatch`. - `SpecializedPipeline` has a new associated type for the vertex attribute buffer descriptor accepted by the `specialize` method. - Discussion: https://discord.com/channels/691052431525675048/743663924229963868/908484759833960489 Fix vertex buffer layout overrides for `Sprite`
1 parent 9a4cc42 commit 8e15297

File tree

9 files changed

+368
-202
lines changed

9 files changed

+368
-202
lines changed

examples/shader/custom_shader_pipelined.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,14 @@ pub struct CustomPipeline {
134134

135135
impl SpecializedPipeline for CustomPipeline {
136136
type Key = PbrPipelineKey;
137-
138-
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
139-
let mut descriptor = self.pbr_pipeline.specialize(key);
137+
type VertexSpecialization = Mesh;
138+
139+
fn specialize(
140+
&self,
141+
key: Self::Key,
142+
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
143+
) -> RenderPipelineDescriptor {
144+
let mut descriptor = self.pbr_pipeline.specialize(key, vbd);
140145
descriptor.vertex.shader = self.shader.clone();
141146
descriptor.fragment.as_mut().unwrap().shader = self.shader.clone();
142147
descriptor.layout = Some(vec![
@@ -201,6 +206,7 @@ pub fn queue_custom(
201206
&mut pipeline_cache,
202207
&custom_pipeline,
203208
key,
209+
&Mesh::get_default_vertex_buffer_descriptor(),
204210
),
205211
draw_function: draw_custom,
206212
distance: view_row_2.dot(mesh_uniform.transform.col(3)),

examples/shader/shader_defs_pipelined.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,18 @@ impl FromWorld for IsRedPipeline {
104104

105105
impl SpecializedPipeline for IsRedPipeline {
106106
type Key = (IsRed, PbrPipelineKey);
107+
type VertexSpecialization = Mesh;
107108

108-
fn specialize(&self, (is_red, pbr_pipeline_key): Self::Key) -> RenderPipelineDescriptor {
109+
fn specialize(
110+
&self,
111+
(is_red, pbr_pipeline_key): Self::Key,
112+
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
113+
) -> RenderPipelineDescriptor {
109114
let mut shader_defs = Vec::new();
110115
if is_red.0 {
111116
shader_defs.push("IS_RED".to_string());
112117
}
113-
let mut descriptor = self.pbr_pipeline.specialize(pbr_pipeline_key);
118+
let mut descriptor = self.pbr_pipeline.specialize(pbr_pipeline_key, vbd);
114119
descriptor.vertex.shader = self.shader.clone();
115120
descriptor.vertex.shader_defs = shader_defs.clone();
116121
let fragment = descriptor.fragment.as_mut().unwrap();
@@ -149,8 +154,12 @@ fn queue_custom(
149154
let view_matrix = view.transform.compute_matrix();
150155
let view_row_2 = view_matrix.row(2);
151156
for (entity, mesh_uniform, is_red) in material_meshes.iter() {
152-
let pipeline =
153-
pipelines.specialize(&mut pipeline_cache, &custom_pipeline, (*is_red, key));
157+
let pipeline = pipelines.specialize(
158+
&mut pipeline_cache,
159+
&custom_pipeline,
160+
(*is_red, key),
161+
&Mesh::get_default_vertex_buffer_descriptor(),
162+
);
154163
transparent_phase.add(Transparent3d {
155164
entity,
156165
pipeline,

pipelined/bevy_pbr2/src/render/light.rs

+24-63
Original file line numberDiff line numberDiff line change
@@ -179,73 +179,22 @@ bitflags::bitflags! {
179179

180180
impl SpecializedPipeline for ShadowPipeline {
181181
type Key = ShadowPipelineKey;
182+
type VertexSpecialization = Mesh;
182183

183-
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
184-
let (vertex_array_stride, vertex_attributes) =
185-
if key.contains(ShadowPipelineKey::VERTEX_TANGENTS) {
186-
(
187-
48,
188-
vec![
189-
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
190-
VertexAttribute {
191-
format: VertexFormat::Float32x3,
192-
offset: 12,
193-
shader_location: 0,
194-
},
195-
// Normal
196-
VertexAttribute {
197-
format: VertexFormat::Float32x3,
198-
offset: 0,
199-
shader_location: 1,
200-
},
201-
// Uv (GOTCHA! uv is no longer third in the buffer due to how Mesh sorts attributes (alphabetically))
202-
VertexAttribute {
203-
format: VertexFormat::Float32x2,
204-
offset: 40,
205-
shader_location: 2,
206-
},
207-
// Tangent
208-
VertexAttribute {
209-
format: VertexFormat::Float32x4,
210-
offset: 24,
211-
shader_location: 3,
212-
},
213-
],
214-
)
215-
} else {
216-
(
217-
32,
218-
vec![
219-
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
220-
VertexAttribute {
221-
format: VertexFormat::Float32x3,
222-
offset: 12,
223-
shader_location: 0,
224-
},
225-
// Normal
226-
VertexAttribute {
227-
format: VertexFormat::Float32x3,
228-
offset: 0,
229-
shader_location: 1,
230-
},
231-
// Uv
232-
VertexAttribute {
233-
format: VertexFormat::Float32x2,
234-
offset: 24,
235-
shader_location: 2,
236-
},
237-
],
238-
)
239-
};
184+
fn specialize(
185+
&self,
186+
_key: Self::Key,
187+
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
188+
) -> RenderPipelineDescriptor {
240189
RenderPipelineDescriptor {
241190
vertex: VertexState {
242191
shader: SHADOW_SHADER_HANDLE.typed::<Shader>(),
243192
entry_point: "vertex".into(),
244193
shader_defs: vec![],
245194
buffers: vec![VertexBufferLayout {
246-
array_stride: vertex_array_stride,
195+
array_stride: vbd.stride(),
247196
step_mode: VertexStepMode::Vertex,
248-
attributes: vertex_attributes,
197+
attributes: vbd.to_raw(),
249198
}],
250199
},
251200
fragment: None,
@@ -755,13 +704,25 @@ pub fn queue_shadows(
755704
for VisibleEntity { entity, .. } in visible_entities.iter() {
756705
let mut key = ShadowPipelineKey::empty();
757706
if let Ok(mesh_handle) = casting_meshes.get(*entity) {
758-
if let Some(mesh) = render_meshes.get(mesh_handle) {
707+
let pipeline_id = if let Some(mesh) = render_meshes.get(mesh_handle) {
759708
if mesh.has_tangents {
760709
key |= ShadowPipelineKey::VERTEX_TANGENTS;
761710
}
762-
}
763-
let pipeline_id =
764-
pipelines.specialize(&mut pipeline_cache, &shadow_pipeline, key);
711+
712+
pipelines.specialize(
713+
&mut pipeline_cache,
714+
&shadow_pipeline,
715+
key,
716+
&mesh.vertex_buffer_descriptor,
717+
)
718+
} else {
719+
pipelines.specialize(
720+
&mut pipeline_cache,
721+
&shadow_pipeline,
722+
key,
723+
&Mesh::get_default_vertex_buffer_descriptor(),
724+
)
725+
};
765726

766727
shadow_phase.add(Shadow {
767728
draw_function: draw_shadow_mesh,

pipelined/bevy_pbr2/src/render/mod.rs

+24-62
Original file line numberDiff line numberDiff line change
@@ -446,64 +446,13 @@ impl PbrPipelineKey {
446446

447447
impl SpecializedPipeline for PbrPipeline {
448448
type Key = PbrPipelineKey;
449+
type VertexSpecialization = Mesh;
449450

450-
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
451-
let (vertex_array_stride, vertex_attributes) =
452-
if key.contains(PbrPipelineKey::VERTEX_TANGENTS) {
453-
(
454-
48,
455-
vec![
456-
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
457-
VertexAttribute {
458-
format: VertexFormat::Float32x3,
459-
offset: 12,
460-
shader_location: 0,
461-
},
462-
// Normal
463-
VertexAttribute {
464-
format: VertexFormat::Float32x3,
465-
offset: 0,
466-
shader_location: 1,
467-
},
468-
// Uv (GOTCHA! uv is no longer third in the buffer due to how Mesh sorts attributes (alphabetically))
469-
VertexAttribute {
470-
format: VertexFormat::Float32x2,
471-
offset: 40,
472-
shader_location: 2,
473-
},
474-
// Tangent
475-
VertexAttribute {
476-
format: VertexFormat::Float32x4,
477-
offset: 24,
478-
shader_location: 3,
479-
},
480-
],
481-
)
482-
} else {
483-
(
484-
32,
485-
vec![
486-
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
487-
VertexAttribute {
488-
format: VertexFormat::Float32x3,
489-
offset: 12,
490-
shader_location: 0,
491-
},
492-
// Normal
493-
VertexAttribute {
494-
format: VertexFormat::Float32x3,
495-
offset: 0,
496-
shader_location: 1,
497-
},
498-
// Uv
499-
VertexAttribute {
500-
format: VertexFormat::Float32x2,
501-
offset: 24,
502-
shader_location: 2,
503-
},
504-
],
505-
)
506-
};
451+
fn specialize(
452+
&self,
453+
key: Self::Key,
454+
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
455+
) -> RenderPipelineDescriptor {
507456
let mut shader_defs = Vec::new();
508457
if key.contains(PbrPipelineKey::VERTEX_TANGENTS) {
509458
shader_defs.push(String::from("VERTEX_TANGENTS"));
@@ -517,9 +466,9 @@ impl SpecializedPipeline for PbrPipeline {
517466
entry_point: "vertex".into(),
518467
shader_defs: shader_defs.clone(),
519468
buffers: vec![VertexBufferLayout {
520-
array_stride: vertex_array_stride,
469+
array_stride: vbd.stride(),
521470
step_mode: VertexStepMode::Vertex,
522-
attributes: vertex_attributes,
471+
attributes: vbd.to_raw(),
523472
}],
524473
},
525474
fragment: Some(FragmentState {
@@ -704,12 +653,25 @@ pub fn queue_meshes(
704653
} else {
705654
continue;
706655
}
707-
if let Some(mesh) = render_meshes.get(mesh_handle) {
656+
let pipeline_id = if let Some(mesh) = render_meshes.get(mesh_handle) {
708657
if mesh.has_tangents {
709658
key |= PbrPipelineKey::VERTEX_TANGENTS;
710659
}
711-
}
712-
let pipeline_id = pipelines.specialize(&mut pipeline_cache, &pbr_pipeline, key);
660+
661+
pipelines.specialize(
662+
&mut pipeline_cache,
663+
&pbr_pipeline,
664+
key,
665+
&mesh.vertex_buffer_descriptor,
666+
)
667+
} else {
668+
pipelines.specialize(
669+
&mut pipeline_cache,
670+
&pbr_pipeline,
671+
key,
672+
&Mesh::get_default_vertex_buffer_descriptor(),
673+
)
674+
};
713675

714676
// NOTE: row 2 of the view matrix dotted with column 3 of the model matrix
715677
// gives the z component of translation of the mesh in view space

0 commit comments

Comments
 (0)