Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intern mesh vertex buffer layouts so that we don't have to compare them over and over. #12216

Merged
6 changes: 3 additions & 3 deletions crates/bevy_pbr/src/extended_material.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bevy_asset::{Asset, Handle};
use bevy_reflect::{impl_type_path, Reflect};
use bevy_render::{
mesh::MeshVertexBufferLayout,
mesh::MeshVertexBufferLayoutRef,
render_asset::RenderAssets,
render_resource::{
AsBindGroup, AsBindGroupError, BindGroupLayout, RenderPipelineDescriptor, Shader,
Expand Down Expand Up @@ -75,7 +75,7 @@ pub trait MaterialExtension: Asset + AsBindGroup + Clone + Sized {
fn specialize(
pipeline: &MaterialExtensionPipeline,
descriptor: &mut RenderPipelineDescriptor,
layout: &MeshVertexBufferLayout,
layout: &MeshVertexBufferLayoutRef,
key: MaterialExtensionKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
Ok(())
Expand Down Expand Up @@ -214,7 +214,7 @@ impl<B: Material, E: MaterialExtension> Material for ExtendedMaterial<B, E> {
fn specialize(
pipeline: &MaterialPipeline<Self>,
descriptor: &mut RenderPipelineDescriptor,
layout: &MeshVertexBufferLayout,
layout: &MeshVertexBufferLayoutRef,
key: MaterialPipelineKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
// Call the base material's specialize function
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/lightmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ fn extract_lightmaps(
|| !render_mesh_instances
.get(&entity)
.and_then(|mesh_instance| meshes.get(mesh_instance.mesh_asset_id))
.is_some_and(|mesh| mesh.layout.contains(Mesh::ATTRIBUTE_UV_1.id))
.is_some_and(|mesh| mesh.layout.0.contains(Mesh::ATTRIBUTE_UV_1.id))
{
continue;
}
Expand Down
7 changes: 4 additions & 3 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use bevy_render::{
camera::TemporalJitter,
extract_instances::{ExtractInstancesPlugin, ExtractedInstances},
extract_resource::ExtractResource,
mesh::{Mesh, MeshVertexBufferLayout},
mesh::{Mesh, MeshVertexBufferLayoutRef},
render_asset::RenderAssets,
render_phase::*,
render_resource::*,
Expand Down Expand Up @@ -177,7 +177,7 @@ pub trait Material: Asset + AsBindGroup + Clone + Sized {
fn specialize(
pipeline: &MaterialPipeline<Self>,
descriptor: &mut RenderPipelineDescriptor,
layout: &MeshVertexBufferLayout,
layout: &MeshVertexBufferLayoutRef,
key: MaterialPipelineKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
Ok(())
Expand Down Expand Up @@ -326,7 +326,7 @@ where
fn specialize(
&self,
key: Self::Key,
layout: &MeshVertexBufferLayout,
layout: &MeshVertexBufferLayoutRef,
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
let mut descriptor = self.mesh_pipeline.specialize(key.mesh_key, layout)?;
if let Some(vertex_shader) = &self.vertex_shader {
Expand Down Expand Up @@ -585,6 +585,7 @@ pub fn queue_material_meshes<M: Material>(
camera_3d.screen_space_specular_transmission_quality,
);
}

let rangefinder = view.rangefinder3d();
for visible_entity in &visible_entities.entities {
let Some(material_asset_id) = render_material_instances.get(visible_entity) else {
Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use bevy_asset::Asset;
use bevy_color::Alpha;
use bevy_math::{Affine2, Mat3, Vec4};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{mesh::MeshVertexBufferLayout, render_asset::RenderAssets, render_resource::*};
use bevy_render::{
mesh::MeshVertexBufferLayoutRef, render_asset::RenderAssets, render_resource::*,
};

use crate::deferred::DEFAULT_PBR_DEFERRED_LIGHTING_PASS_ID;
use crate::*;
Expand Down Expand Up @@ -813,7 +815,7 @@ impl Material for StandardMaterial {
fn specialize(
_pipeline: &MaterialPipeline<Self>,
descriptor: &mut RenderPipelineDescriptor,
_layout: &MeshVertexBufferLayout,
_layout: &MeshVertexBufferLayoutRef,
key: MaterialPipelineKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
if let Some(fragment) = descriptor.fragment.as_mut() {
Expand Down
16 changes: 8 additions & 8 deletions crates/bevy_pbr/src/prepass/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod prepass_bindings;

use bevy_render::mesh::MeshVertexBufferLayoutRef;
use bevy_render::render_resource::binding_types::uniform_buffer;
pub use prepass_bindings::*;

Expand All @@ -17,7 +18,6 @@ use bevy_math::{Affine3A, Mat4};
use bevy_render::{
batching::batch_and_prepare_render_phase,
globals::{GlobalsBuffer, GlobalsUniform},
mesh::MeshVertexBufferLayout,
prelude::{Camera, Mesh},
render_asset::RenderAssets,
render_phase::*,
Expand Down Expand Up @@ -302,7 +302,7 @@ where
fn specialize(
&self,
key: Self::Key,
layout: &MeshVertexBufferLayout,
layout: &MeshVertexBufferLayoutRef,
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
let mut bind_group_layouts = vec![if key
.mesh_key
Expand Down Expand Up @@ -347,7 +347,7 @@ where
shader_defs.push("BLEND_ALPHA".into());
}

if layout.contains(Mesh::ATTRIBUTE_POSITION) {
if layout.0.contains(Mesh::ATTRIBUTE_POSITION) {
shader_defs.push("VERTEX_POSITIONS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
}
Expand All @@ -363,12 +363,12 @@ where
shader_defs.push("PREPASS_FRAGMENT".into());
}

if layout.contains(Mesh::ATTRIBUTE_UV_0) {
if layout.0.contains(Mesh::ATTRIBUTE_UV_0) {
shader_defs.push("VERTEX_UVS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(1));
}

if layout.contains(Mesh::ATTRIBUTE_UV_1) {
if layout.0.contains(Mesh::ATTRIBUTE_UV_1) {
shader_defs.push("VERTEX_UVS_B".into());
vertex_attributes.push(Mesh::ATTRIBUTE_UV_1.at_shader_location(2));
}
Expand All @@ -383,7 +383,7 @@ where
{
vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(3));
shader_defs.push("NORMAL_PREPASS_OR_DEFERRED_PREPASS".into());
if layout.contains(Mesh::ATTRIBUTE_TANGENT) {
if layout.0.contains(Mesh::ATTRIBUTE_TANGENT) {
shader_defs.push("VERTEX_TANGENTS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(4));
}
Expand All @@ -400,7 +400,7 @@ where
shader_defs.push("DEFERRED_PREPASS".into());
}

if layout.contains(Mesh::ATTRIBUTE_COLOR) {
if layout.0.contains(Mesh::ATTRIBUTE_COLOR) {
shader_defs.push("VERTEX_COLORS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(7));
}
Expand Down Expand Up @@ -430,7 +430,7 @@ where
);
bind_group_layouts.insert(1, bind_group);

let vertex_buffer_layout = layout.get_layout(&vertex_attributes)?;
let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;

// Setup prepass fragment targets - normals in slot 0 (or None if not needed), motion vectors in slot 1
let mut targets = vec![
Expand Down
25 changes: 13 additions & 12 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use bevy_render::{
Extract,
};
use bevy_transform::components::GlobalTransform;
use bevy_utils::{tracing::error, Entry, HashMap, Hashed, Parallel};
use bevy_utils::{tracing::error, Entry, HashMap, Parallel};

#[cfg(debug_assertions)]
use bevy_utils::warn_once;
Expand Down Expand Up @@ -595,12 +595,13 @@ impl MeshPipelineKey {
}
}

fn is_skinned(layout: &Hashed<InnerMeshVertexBufferLayout>) -> bool {
layout.contains(Mesh::ATTRIBUTE_JOINT_INDEX) && layout.contains(Mesh::ATTRIBUTE_JOINT_WEIGHT)
fn is_skinned(layout: &MeshVertexBufferLayoutRef) -> bool {
layout.0.contains(Mesh::ATTRIBUTE_JOINT_INDEX)
&& layout.0.contains(Mesh::ATTRIBUTE_JOINT_WEIGHT)
}
pub fn setup_morph_and_skinning_defs(
mesh_layouts: &MeshLayouts,
layout: &Hashed<InnerMeshVertexBufferLayout>,
layout: &MeshVertexBufferLayoutRef,
offset: u32,
key: &MeshPipelineKey,
shader_defs: &mut Vec<ShaderDefVal>,
Expand Down Expand Up @@ -638,7 +639,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
fn specialize(
&self,
key: Self::Key,
layout: &MeshVertexBufferLayout,
layout: &MeshVertexBufferLayoutRef,
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
let mut shader_defs = Vec::new();
let mut vertex_attributes = Vec::new();
Expand All @@ -648,32 +649,32 @@ impl SpecializedMeshPipeline for MeshPipeline {

shader_defs.push("VERTEX_OUTPUT_INSTANCE_INDEX".into());

if layout.contains(Mesh::ATTRIBUTE_POSITION) {
if layout.0.contains(Mesh::ATTRIBUTE_POSITION) {
shader_defs.push("VERTEX_POSITIONS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
}

if layout.contains(Mesh::ATTRIBUTE_NORMAL) {
if layout.0.contains(Mesh::ATTRIBUTE_NORMAL) {
shader_defs.push("VERTEX_NORMALS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(1));
}

if layout.contains(Mesh::ATTRIBUTE_UV_0) {
if layout.0.contains(Mesh::ATTRIBUTE_UV_0) {
shader_defs.push("VERTEX_UVS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(2));
}

if layout.contains(Mesh::ATTRIBUTE_UV_1) {
if layout.0.contains(Mesh::ATTRIBUTE_UV_1) {
shader_defs.push("VERTEX_UVS_B".into());
vertex_attributes.push(Mesh::ATTRIBUTE_UV_1.at_shader_location(3));
}

if layout.contains(Mesh::ATTRIBUTE_TANGENT) {
if layout.0.contains(Mesh::ATTRIBUTE_TANGENT) {
shader_defs.push("VERTEX_TANGENTS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(4));
}

if layout.contains(Mesh::ATTRIBUTE_COLOR) {
if layout.0.contains(Mesh::ATTRIBUTE_COLOR) {
shader_defs.push("VERTEX_COLORS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(5));
}
Expand Down Expand Up @@ -701,7 +702,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
shader_defs.push("SCREEN_SPACE_AMBIENT_OCCLUSION".into());
}

let vertex_buffer_layout = layout.get_layout(&vertex_attributes)?;
let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;

let (label, blend, depth_write_enabled);
let pass = key.intersection(MeshPipelineKey::BLEND_RESERVED_BITS);
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_pbr/src/wireframe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use bevy_color::{Color, LinearRgba};
use bevy_ecs::prelude::*;
use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
use bevy_render::{
extract_resource::ExtractResource, mesh::MeshVertexBufferLayout, prelude::*, render_resource::*,
extract_resource::ExtractResource, mesh::MeshVertexBufferLayoutRef, prelude::*,
render_resource::*,
};

pub const WIREFRAME_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(192598014480025766);
Expand Down Expand Up @@ -208,7 +209,7 @@ impl Material for WireframeMaterial {
fn specialize(
_pipeline: &MaterialPipeline<Self>,
descriptor: &mut RenderPipelineDescriptor,
_layout: &MeshVertexBufferLayout,
_layout: &MeshVertexBufferLayoutRef,
_key: MaterialPipelineKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
descriptor.primitive.polygon_mode = PolygonMode::Line;
Expand Down
40 changes: 27 additions & 13 deletions crates/bevy_render/src/mesh/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,23 @@ use crate::{
use bevy_asset::{Asset, Handle};
use bevy_core::cast_slice;
use bevy_derive::EnumVariantMeta;
use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem};
use bevy_ecs::system::{
lifetimeless::{SRes, SResMut},
SystemParamItem,
};
use bevy_log::warn;
use bevy_math::*;
use bevy_reflect::Reflect;
use bevy_utils::{tracing::error, Hashed};
use bevy_utils::tracing::error;
use std::{collections::BTreeMap, hash::Hash, iter::FusedIterator};
use thiserror::Error;
use wgpu::{
util::BufferInitDescriptor, BufferUsages, IndexFormat, VertexAttribute, VertexFormat,
VertexStepMode,
};

use super::{MeshVertexBufferLayoutRef, MeshVertexBufferLayouts};

pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;

Expand Down Expand Up @@ -377,7 +382,10 @@ impl Mesh {
/// Get this `Mesh`'s [`MeshVertexBufferLayout`], used in [`SpecializedMeshPipeline`].
///
/// [`SpecializedMeshPipeline`]: crate::render_resource::SpecializedMeshPipeline
pub fn get_mesh_vertex_buffer_layout(&self) -> MeshVertexBufferLayout {
pub fn get_mesh_vertex_buffer_layout(
&self,
mesh_vertex_buffer_layouts: &mut MeshVertexBufferLayouts,
) -> MeshVertexBufferLayoutRef {
let mut attributes = Vec::with_capacity(self.attributes.len());
let mut attribute_ids = Vec::with_capacity(self.attributes.len());
let mut accumulated_offset = 0;
Expand All @@ -391,14 +399,15 @@ impl Mesh {
accumulated_offset += data.attribute.format.get_size();
}

MeshVertexBufferLayout::new(InnerMeshVertexBufferLayout {
let layout = MeshVertexBufferLayout {
layout: VertexBufferLayout {
array_stride: accumulated_offset,
step_mode: VertexStepMode::Vertex,
attributes,
},
attribute_ids,
})
};
mesh_vertex_buffer_layouts.insert(layout)
}

/// Counts all vertices of the mesh.
Expand Down Expand Up @@ -967,15 +976,13 @@ impl From<MeshVertexAttribute> for MeshVertexAttributeId {
}
}

pub type MeshVertexBufferLayout = Hashed<InnerMeshVertexBufferLayout>;

#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct InnerMeshVertexBufferLayout {
pub struct MeshVertexBufferLayout {
attribute_ids: Vec<MeshVertexAttributeId>,
layout: VertexBufferLayout,
}

impl InnerMeshVertexBufferLayout {
impl MeshVertexBufferLayout {
pub fn new(attribute_ids: Vec<MeshVertexAttributeId>, layout: VertexBufferLayout) -> Self {
Self {
attribute_ids,
Expand Down Expand Up @@ -1350,7 +1357,7 @@ pub struct GpuMesh {
pub morph_targets: Option<TextureView>,
pub buffer_info: GpuBufferInfo,
pub primitive_topology: PrimitiveTopology,
pub layout: MeshVertexBufferLayout,
pub layout: MeshVertexBufferLayoutRef,
}

/// The index/vertex buffer info of a [`GpuMesh`].
Expand All @@ -1367,7 +1374,11 @@ pub enum GpuBufferInfo {

impl RenderAsset for Mesh {
type PreparedAsset = GpuMesh;
type Param = (SRes<RenderDevice>, SRes<RenderAssets<Image>>);
type Param = (
SRes<RenderDevice>,
SRes<RenderAssets<Image>>,
SResMut<MeshVertexBufferLayouts>,
);

fn asset_usage(&self) -> RenderAssetUsages {
self.asset_usage
Expand All @@ -1376,7 +1387,9 @@ impl RenderAsset for Mesh {
/// Converts the extracted mesh a into [`GpuMesh`].
fn prepare_asset(
self,
(render_device, images): &mut SystemParamItem<Self::Param>,
(render_device, images, ref mut mesh_vertex_buffer_layouts): &mut SystemParamItem<
Self::Param,
>,
) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
let vertex_buffer_data = self.get_vertex_buffer_data();
let vertex_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
Expand All @@ -1399,7 +1412,8 @@ impl RenderAsset for Mesh {
GpuBufferInfo::NonIndexed
};

let mesh_vertex_buffer_layout = self.get_mesh_vertex_buffer_layout();
let mesh_vertex_buffer_layout =
self.get_mesh_vertex_buffer_layout(mesh_vertex_buffer_layouts);

Ok(GpuMesh {
vertex_buffer,
Expand Down
Loading
Loading