Skip to content

Commit fb43380

Browse files
parasytecart
authored andcommitted
Mesh refactor and mesh pipeline specialization
1 parent b3a1db6 commit fb43380

File tree

25 files changed

+664
-514
lines changed

25 files changed

+664
-514
lines changed

crates/bevy_gltf/src/loader.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,33 +125,33 @@ async fn load_gltf<'a, 'b>(
125125
.read_positions()
126126
.map(|v| VertexAttributeValues::Float32x3(v.collect()))
127127
{
128-
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, vertex_attribute);
128+
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vertex_attribute);
129129
}
130130

131131
if let Some(vertex_attribute) = reader
132132
.read_normals()
133133
.map(|v| VertexAttributeValues::Float32x3(v.collect()))
134134
{
135-
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, vertex_attribute);
135+
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vertex_attribute);
136136
}
137137

138138
if let Some(vertex_attribute) = reader
139139
.read_tangents()
140140
.map(|v| VertexAttributeValues::Float32x4(v.collect()))
141141
{
142-
mesh.set_attribute(Mesh::ATTRIBUTE_TANGENT, vertex_attribute);
142+
mesh.insert_attribute(Mesh::ATTRIBUTE_TANGENT, vertex_attribute);
143143
}
144144

145145
if let Some(vertex_attribute) = reader
146146
.read_tex_coords(0)
147147
.map(|v| VertexAttributeValues::Float32x2(v.into_f32().collect()))
148148
{
149-
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, vertex_attribute);
149+
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vertex_attribute);
150150
} else {
151151
let len = mesh.count_vertices();
152152
let uvs = vec![[0.0, 0.0]; len];
153153
bevy_log::debug!("missing `TEXCOORD_0` vertex attribute, loading zeroed out UVs");
154-
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
154+
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
155155
}
156156

157157
// if let Some(vertex_attribute) = reader

crates/bevy_pbr/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use bevy_render::{
4040
prelude::Color,
4141
render_graph::RenderGraph,
4242
render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions},
43-
render_resource::{Shader, SpecializedPipelines},
43+
render_resource::{Shader, SpecializedMeshPipelines},
4444
view::VisibilitySystems,
4545
RenderApp, RenderStage,
4646
};
@@ -178,7 +178,7 @@ impl Plugin for PbrPlugin {
178178
.init_resource::<DrawFunctions<Shadow>>()
179179
.init_resource::<LightMeta>()
180180
.init_resource::<GlobalLightMeta>()
181-
.init_resource::<SpecializedPipelines<ShadowPipeline>>();
181+
.init_resource::<SpecializedMeshPipelines<ShadowPipeline>>();
182182

183183
let shadow_pass_node = ShadowPassNode::new(&mut render_app.world);
184184
render_app.add_render_command::<Shadow, DrawShadowMesh>();

crates/bevy_pbr/src/material.rs

Lines changed: 79 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use bevy_ecs::{
1515
world::FromWorld,
1616
};
1717
use bevy_render::{
18-
mesh::Mesh,
18+
mesh::{Mesh, MeshVertexBufferLayout},
1919
render_asset::{RenderAsset, RenderAssetPlugin, RenderAssets},
2020
render_component::ExtractComponentPlugin,
2121
render_phase::{
@@ -24,7 +24,7 @@ use bevy_render::{
2424
},
2525
render_resource::{
2626
BindGroup, BindGroupLayout, RenderPipelineCache, RenderPipelineDescriptor, Shader,
27-
SpecializedPipeline, SpecializedPipelines,
27+
SpecializedMeshPipeline, SpecializedMeshPipelines,
2828
},
2929
renderer::RenderDevice,
3030
view::{ExtractedView, Msaa, VisibleEntities},
@@ -81,7 +81,12 @@ impl<M: Material> SpecializedMaterial for M {
8181
fn key(_material: &<Self as RenderAsset>::PreparedAsset) -> Self::Key {}
8282

8383
#[inline]
84-
fn specialize(_key: Self::Key, _descriptor: &mut RenderPipelineDescriptor) {}
84+
fn specialize(
85+
_descriptor: &mut RenderPipelineDescriptor,
86+
_key: Self::Key,
87+
_layout: &MeshVertexBufferLayout,
88+
) {
89+
}
8590

8691
#[inline]
8792
fn bind_group(material: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup {
@@ -130,7 +135,11 @@ pub trait SpecializedMaterial: Asset + RenderAsset {
130135
fn key(material: &<Self as RenderAsset>::PreparedAsset) -> Self::Key;
131136

132137
/// Specializes the given `descriptor` according to the given `key`.
133-
fn specialize(key: Self::Key, descriptor: &mut RenderPipelineDescriptor);
138+
fn specialize(
139+
descriptor: &mut RenderPipelineDescriptor,
140+
key: Self::Key,
141+
layout: &MeshVertexBufferLayout,
142+
);
134143

135144
/// Returns this material's [`BindGroup`]. This should match the layout returned by [`SpecializedMaterial::bind_group_layout`].
136145
fn bind_group(material: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup;
@@ -188,7 +197,7 @@ impl<M: SpecializedMaterial> Plugin for MaterialPlugin<M> {
188197
.add_render_command::<Opaque3d, DrawMaterial<M>>()
189198
.add_render_command::<AlphaMask3d, DrawMaterial<M>>()
190199
.init_resource::<MaterialPipeline<M>>()
191-
.init_resource::<SpecializedPipelines<MaterialPipeline<M>>>()
200+
.init_resource::<SpecializedMeshPipelines<MaterialPipeline<M>>>()
192201
.add_system_to_stage(RenderStage::Queue, queue_material_meshes::<M>);
193202
}
194203
}
@@ -202,11 +211,15 @@ pub struct MaterialPipeline<M: SpecializedMaterial> {
202211
marker: PhantomData<M>,
203212
}
204213

205-
impl<M: SpecializedMaterial> SpecializedPipeline for MaterialPipeline<M> {
214+
impl<M: SpecializedMaterial> SpecializedMeshPipeline for MaterialPipeline<M> {
206215
type Key = (MeshPipelineKey, M::Key);
207216

208-
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
209-
let mut descriptor = self.mesh_pipeline.specialize(key.0);
217+
fn specialize(
218+
&self,
219+
key: Self::Key,
220+
layout: &MeshVertexBufferLayout,
221+
) -> RenderPipelineDescriptor {
222+
let mut descriptor = self.mesh_pipeline.specialize(key.0, layout);
210223
if let Some(vertex_shader) = &self.vertex_shader {
211224
descriptor.vertex.shader = vertex_shader.clone();
212225
}
@@ -220,7 +233,7 @@ impl<M: SpecializedMaterial> SpecializedPipeline for MaterialPipeline<M> {
220233
self.mesh_pipeline.mesh_layout.clone(),
221234
]);
222235

223-
M::specialize(key.1, &mut descriptor);
236+
M::specialize(&mut descriptor, key.1, layout);
224237
descriptor
225238
}
226239
}
@@ -275,7 +288,7 @@ pub fn queue_material_meshes<M: SpecializedMaterial>(
275288
alpha_mask_draw_functions: Res<DrawFunctions<AlphaMask3d>>,
276289
transparent_draw_functions: Res<DrawFunctions<Transparent3d>>,
277290
material_pipeline: Res<MaterialPipeline<M>>,
278-
mut pipelines: ResMut<SpecializedPipelines<MaterialPipeline<M>>>,
291+
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipeline<M>>>,
279292
mut pipeline_cache: ResMut<RenderPipelineCache>,
280293
msaa: Res<Msaa>,
281294
render_meshes: Res<RenderAssets<Mesh>>,
@@ -307,72 +320,71 @@ pub fn queue_material_meshes<M: SpecializedMaterial>(
307320

308321
let inverse_view_matrix = view.transform.compute_matrix().inverse();
309322
let inverse_view_row_2 = inverse_view_matrix.row(2);
310-
let mesh_key = MeshPipelineKey::from_msaa_samples(msaa.samples);
323+
let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples);
311324

312325
for visible_entity in &visible_entities.entities {
313326
if let Ok((material_handle, mesh_handle, mesh_uniform)) =
314327
material_meshes.get(*visible_entity)
315328
{
316329
if let Some(material) = render_materials.get(material_handle) {
317-
let mut mesh_key = mesh_key;
318330
if let Some(mesh) = render_meshes.get(mesh_handle) {
319-
if mesh.has_tangents {
320-
mesh_key |= MeshPipelineKey::VERTEX_TANGENTS;
331+
let mut mesh_key =
332+
MeshPipelineKey::from_primitive_topology(mesh.primitive_topology)
333+
| msaa_key;
334+
let alpha_mode = M::alpha_mode(material);
335+
if let AlphaMode::Blend = alpha_mode {
336+
mesh_key |= MeshPipelineKey::TRANSPARENT_MAIN_PASS;
321337
}
322-
mesh_key |=
323-
MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
324-
}
325-
let alpha_mode = M::alpha_mode(material);
326-
if let AlphaMode::Blend = alpha_mode {
327-
mesh_key |= MeshPipelineKey::TRANSPARENT_MAIN_PASS;
328-
}
329338

330-
let specialized_key = M::key(material);
331-
let pipeline_id = pipelines.specialize(
332-
&mut pipeline_cache,
333-
&material_pipeline,
334-
(mesh_key, specialized_key),
335-
);
336-
337-
// NOTE: row 2 of the inverse view matrix dotted with column 3 of the model matrix
338-
// gives the z component of translation of the mesh in view space
339-
let mesh_z = inverse_view_row_2.dot(mesh_uniform.transform.col(3));
340-
match alpha_mode {
341-
AlphaMode::Opaque => {
342-
opaque_phase.add(Opaque3d {
343-
entity: *visible_entity,
344-
draw_function: draw_opaque_pbr,
345-
pipeline: pipeline_id,
346-
// NOTE: Front-to-back ordering for opaque with ascending sort means near should have the
347-
// lowest sort key and getting further away should increase. As we have
348-
// -z in front of the camera, values in view space decrease away from the
349-
// camera. Flipping the sign of mesh_z results in the correct front-to-back ordering
350-
distance: -mesh_z,
351-
});
352-
}
353-
AlphaMode::Mask(_) => {
354-
alpha_mask_phase.add(AlphaMask3d {
355-
entity: *visible_entity,
356-
draw_function: draw_alpha_mask_pbr,
357-
pipeline: pipeline_id,
358-
// NOTE: Front-to-back ordering for alpha mask with ascending sort means near should have the
359-
// lowest sort key and getting further away should increase. As we have
360-
// -z in front of the camera, values in view space decrease away from the
361-
// camera. Flipping the sign of mesh_z results in the correct front-to-back ordering
362-
distance: -mesh_z,
363-
});
364-
}
365-
AlphaMode::Blend => {
366-
transparent_phase.add(Transparent3d {
367-
entity: *visible_entity,
368-
draw_function: draw_transparent_pbr,
369-
pipeline: pipeline_id,
370-
// NOTE: Back-to-front ordering for transparent with ascending sort means far should have the
371-
// lowest sort key and getting closer should increase. As we have
372-
// -z in front of the camera, the largest distance is -far with values increasing toward the
373-
// camera. As such we can just use mesh_z as the distance
374-
distance: mesh_z,
375-
});
339+
let specialized_key = M::key(material);
340+
341+
let pipeline_id = pipelines.specialize(
342+
&mut pipeline_cache,
343+
&material_pipeline,
344+
(mesh_key, specialized_key),
345+
&mesh.layout,
346+
);
347+
348+
// NOTE: row 2 of the inverse view matrix dotted with column 3 of the model matrix
349+
// gives the z component of translation of the mesh in view space
350+
let mesh_z = inverse_view_row_2.dot(mesh_uniform.transform.col(3));
351+
match alpha_mode {
352+
AlphaMode::Opaque => {
353+
opaque_phase.add(Opaque3d {
354+
entity: *visible_entity,
355+
draw_function: draw_opaque_pbr,
356+
pipeline: pipeline_id,
357+
// NOTE: Front-to-back ordering for opaque with ascending sort means near should have the
358+
// lowest sort key and getting further away should increase. As we have
359+
// -z in front of the camera, values in view space decrease away from the
360+
// camera. Flipping the sign of mesh_z results in the correct front-to-back ordering
361+
distance: -mesh_z,
362+
});
363+
}
364+
AlphaMode::Mask(_) => {
365+
alpha_mask_phase.add(AlphaMask3d {
366+
entity: *visible_entity,
367+
draw_function: draw_alpha_mask_pbr,
368+
pipeline: pipeline_id,
369+
// NOTE: Front-to-back ordering for alpha mask with ascending sort means near should have the
370+
// lowest sort key and getting further away should increase. As we have
371+
// -z in front of the camera, values in view space decrease away from the
372+
// camera. Flipping the sign of mesh_z results in the correct front-to-back ordering
373+
distance: -mesh_z,
374+
});
375+
}
376+
AlphaMode::Blend => {
377+
transparent_phase.add(Transparent3d {
378+
entity: *visible_entity,
379+
draw_function: draw_transparent_pbr,
380+
pipeline: pipeline_id,
381+
// NOTE: Back-to-front ordering for transparent with ascending sort means far should have the
382+
// lowest sort key and getting closer should increase. As we have
383+
// -z in front of the camera, the largest distance is -far with values increasing toward the
384+
// camera. As such we can just use mesh_z as the distance
385+
distance: mesh_z,
386+
});
387+
}
376388
}
377389
}
378390
}

crates/bevy_pbr/src/pbr_material.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bevy_math::Vec4;
55
use bevy_reflect::TypeUuid;
66
use bevy_render::{
77
color::Color,
8+
mesh::MeshVertexBufferLayout,
89
prelude::Shader,
910
render_asset::{PrepareAssetError, RenderAsset, RenderAssets},
1011
render_resource::{
@@ -338,7 +339,11 @@ impl SpecializedMaterial for StandardMaterial {
338339
}
339340
}
340341

341-
fn specialize(key: Self::Key, descriptor: &mut RenderPipelineDescriptor) {
342+
fn specialize(
343+
descriptor: &mut RenderPipelineDescriptor,
344+
key: Self::Key,
345+
_layout: &MeshVertexBufferLayout,
346+
) {
342347
if key.normal_map {
343348
descriptor
344349
.fragment

0 commit comments

Comments
 (0)