From 6481b1259ec3b6fef38a2c8150e2018ee0612211 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:09:58 -0800 Subject: [PATCH] Fixes --- crates/bevy_pbr/src/meshlet/asset.rs | 2 +- crates/bevy_pbr/src/meshlet/from_mesh.rs | 2 +- crates/bevy_pbr/src/meshlet/gpu_scene.rs | 38 +++++++++--------- .../src/meshlet/material_draw_nodes.rs | 11 ++++-- .../src/meshlet/material_draw_prepare.rs | 39 ++++++++++--------- crates/bevy_pbr/src/render/pbr_fragment.wgsl | 2 +- 6 files changed, 51 insertions(+), 43 deletions(-) diff --git a/crates/bevy_pbr/src/meshlet/asset.rs b/crates/bevy_pbr/src/meshlet/asset.rs index bb8564213595d..482a9cecb02cc 100644 --- a/crates/bevy_pbr/src/meshlet/asset.rs +++ b/crates/bevy_pbr/src/meshlet/asset.rs @@ -13,7 +13,7 @@ use std::sync::Arc; /// A mesh that has been pre-processed into multiple small clusters of triangles called meshlets. /// /// There are restrictions on the [`crate::Material`] functionality that can be used with this type of mesh. -/// * Materials have no control over the vertex shader, and can only have a custom fragment shader. +/// * Materials have no control over the vertex shader or vertex attributes, and can only have a custom fragment shader. /// * Materials must be opaque. Transparent, alpha masked, and transmissive materials are not supported. /// * Materials must use the [`crate::Material::meshlet_mesh_fragment_shader`] method, /// which requires certain shader patterns that differ from the regular material shaders. diff --git a/crates/bevy_pbr/src/meshlet/from_mesh.rs b/crates/bevy_pbr/src/meshlet/from_mesh.rs index 833c9e3ff0eee..3f0c555b8c94e 100644 --- a/crates/bevy_pbr/src/meshlet/from_mesh.rs +++ b/crates/bevy_pbr/src/meshlet/from_mesh.rs @@ -46,7 +46,7 @@ impl MeshletMesh { vertex_buffer_layout.layout().array_stride as usize, 0, ) - .expect("TODO"); + .unwrap(); let meshopt_meshlets = build_meshlets(&indices, &vertices, 64, 64, 0.0); diff --git a/crates/bevy_pbr/src/meshlet/gpu_scene.rs b/crates/bevy_pbr/src/meshlet/gpu_scene.rs index 8df45ad5a635a..c41dfe4205bae 100644 --- a/crates/bevy_pbr/src/meshlet/gpu_scene.rs +++ b/crates/bevy_pbr/src/meshlet/gpu_scene.rs @@ -4,6 +4,7 @@ use crate::{ PreviousGlobalTransform, RenderMaterialInstances, ShadowView, }; use bevy_asset::{AssetId, AssetServer, Assets, Handle, UntypedAssetId}; +use bevy_core_pipeline::core_3d::Camera3d; use bevy_ecs::{ component::Component, entity::Entity, @@ -108,32 +109,28 @@ pub fn perform_pending_meshlet_mesh_writes( .perform_writes(&render_queue, &render_device); } +// TODO: Ideally we could parallelize this system, both between different materials, and the loop over instances /// TODO: Documentation pub fn queue_material_meshlet_meshes( mut gpu_scene: ResMut, render_material_instances: Res>, ) { let gpu_scene = gpu_scene.deref_mut(); - for instance in &gpu_scene.instances { - let material_asset_id = render_material_instances - .get(instance) - .expect("TODO") - .untyped(); - let material_id = *gpu_scene - .material_id_lookup - .get(&material_asset_id) - .expect("TODO: Will this error ever occur?"); - - gpu_scene.material_ids_present_in_scene.insert(material_id); - gpu_scene.instance_material_ids.get_mut().push(material_id); + for (i, instance) in gpu_scene.instances.iter().enumerate() { + if let Some(material_asset_id) = render_material_instances.get(instance) { + let material_asset_id = material_asset_id.untyped(); + if let Some(material_id) = gpu_scene.material_id_lookup.get(&material_asset_id) { + gpu_scene.material_ids_present_in_scene.insert(*material_id); + gpu_scene.instance_material_ids.get_mut()[i] = *material_id; + } + } } } pub fn prepare_meshlet_per_frame_resources( mut gpu_scene: ResMut, - // TODO: Scope to 3d cameras or shadow views - views: Query<(Entity, &ExtractedView, Has)>, + views: Query<(Entity, &ExtractedView, AnyOf<(&Camera3d, &ShadowView)>)>, mut texture_cache: ResMut, render_queue: Res, render_device: Res, @@ -170,7 +167,7 @@ pub fn prepare_meshlet_per_frame_resources( mapped_at_creation: false, }); - for (view_entity, view, is_shadow_view) in &views { + for (view_entity, view, (_, shadow_view)) in &views { let previous_occlusion_buffer = gpu_scene .previous_occlusion_buffers .get(&view_entity) @@ -301,20 +298,21 @@ pub fn prepare_meshlet_per_frame_resources( view_formats: &[], }; + let not_shadow_view = shadow_view.is_none(); commands.entity(view_entity).insert(MeshletViewResources { scene_meshlet_count: gpu_scene.scene_meshlet_count, previous_occlusion_buffer, occlusion_buffer, - visibility_buffer: (!is_shadow_view) + visibility_buffer: not_shadow_view .then(|| texture_cache.get(&render_device, visibility_buffer)), visibility_buffer_draw_command_buffer_first, visibility_buffer_draw_command_buffer_second, visibility_buffer_draw_index_buffer: visibility_buffer_draw_index_buffer.clone(), depth_pyramid, depth_pyramid_mips, - material_depth_color: (!is_shadow_view) + material_depth_color: not_shadow_view .then(|| texture_cache.get(&render_device, material_depth_color)), - material_depth: (!is_shadow_view) + material_depth: not_shadow_view .then(|| texture_cache.get(&render_device, material_depth)), }); } @@ -709,6 +707,9 @@ impl MeshletGpuScene { ) }; + self.instances.push(instance); + self.instance_material_ids.get_mut().push(0); + let (meshlets_slice, index_count) = self .meshlet_mesh_slices .entry(handle.id()) @@ -719,7 +720,6 @@ impl MeshletGpuScene { self.scene_meshlet_count += meshlets_slice.end - meshlets_slice.start; self.scene_index_count += index_count; - self.instances.push(instance); let previous_thread_id_start = self .previous_thread_id_starts diff --git a/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs b/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs index e78c4247f7b47..aa6266e2c5ea5 100644 --- a/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs +++ b/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs @@ -3,7 +3,9 @@ use super::{ material_draw_prepare::MeshletViewMaterials, MeshletGpuScene, }; -use crate::{MeshViewBindGroup, ViewFogUniformOffset, ViewLightsUniformOffset}; +use crate::{ + MeshViewBindGroup, ViewFogUniformOffset, ViewLightProbesUniformOffset, ViewLightsUniformOffset, +}; use bevy_ecs::{query::QueryItem, world::World}; use bevy_render::{ camera::ExtractedCamera, @@ -32,6 +34,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode { &'static ViewUniformOffset, &'static ViewLightsUniformOffset, &'static ViewFogUniformOffset, + &'static ViewLightProbesUniformOffset, &'static MeshletViewMaterials, &'static MeshletViewBindGroups, &'static MeshletViewResources, @@ -45,9 +48,10 @@ impl ViewNode for MeshletMainOpaquePass3dNode { camera, target, mesh_view_bind_group, - view_offset, + view_uniform_offset, view_lights_offset, view_fog_offset, + view_light_probes_offset, meshlet_view_materials, meshlet_view_bind_groups, meshlet_view_resources, @@ -91,9 +95,10 @@ impl ViewNode for MeshletMainOpaquePass3dNode { 0, &mesh_view_bind_group.value, &[ - view_offset.offset, + view_uniform_offset.offset, view_lights_offset.offset, view_fog_offset.offset, + **view_light_probes_offset, ], ); render_pass.set_bind_group(1, meshlet_material_draw_bind_group, &[]); diff --git a/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs b/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs index 055633fa1ee20..28c8855e3f20a 100644 --- a/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs +++ b/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs @@ -2,6 +2,7 @@ use super::{MeshletGpuScene, MESHLET_MESH_MATERIAL_SHADER_HANDLE}; use crate::{environment_map::RenderViewEnvironmentMaps, *}; use bevy_asset::AssetServer; use bevy_core_pipeline::{ + core_3d::Camera3d, prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass}, tonemapping::{DebandDither, Tonemapping}, }; @@ -31,24 +32,26 @@ pub fn prepare_material_meshlet_meshes( render_materials: Res>, render_material_instances: Res>, asset_server: Res, - // TODO: Scope to 3d cameras - views: Query<( - Entity, - &ExtractedView, - Option<&Tonemapping>, - Option<&DebandDither>, - Option<&ShadowFilteringMethod>, - Has, + views: Query< ( - Has, - Has, - Has, - Has, + Entity, + &ExtractedView, + Option<&Tonemapping>, + Option<&DebandDither>, + Option<&ShadowFilteringMethod>, + Has, + ( + Has, + Has, + Has, + Has, + ), + Has, + Option<&Projection>, + Has, ), - Has, - Option<&Projection>, - Has, - )>, + With, + >, mut commands: Commands, ) where M::Data: PartialEq + Eq + Hash + Clone, @@ -189,8 +192,8 @@ pub fn prepare_material_meshlet_meshes( let mut shader_defs = material_pipeline_descriptor .fragment - .expect("TODO") - .shader_defs; + .map(|fragment| fragment.shader_defs) + .unwrap_or_default(); shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into()); let pipeline_descriptor = RenderPipelineDescriptor { diff --git a/crates/bevy_pbr/src/render/pbr_fragment.wgsl b/crates/bevy_pbr/src/render/pbr_fragment.wgsl index 1de325a6cdb4c..32880a043ef4d 100644 --- a/crates/bevy_pbr/src/render/pbr_fragment.wgsl +++ b/crates/bevy_pbr/src/render/pbr_fragment.wgsl @@ -235,7 +235,7 @@ fn pbr_input_from_standard_material( ); #endif -// TODO: Make this work with meshlets +// TODO: Meshlet support #ifdef LIGHTMAP pbr_input.lightmap_light = lightmap( in.uv_b,