From 0afcf9ff13534f31d1f1ca126dee7b05cfe88254 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:17:35 +0100 Subject: [PATCH 01/13] First pass at `SpecializeMeshParams`. Currently just `pipeline_cache` and `entity_specialization_ticks`. --- crates/bevy_pbr/src/material.rs | 11 +++++++---- crates/bevy_pbr/src/prepass/mod.rs | 17 ++++++++++------- crates/bevy_pbr/src/render/light.rs | 10 ++++++---- crates/bevy_pbr/src/render/mesh.rs | 9 ++++++++- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 19afa24b9d..268cd736fb 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -849,6 +849,7 @@ pub fn check_entities_needing_specialization( } pub fn specialize_material_meshes( + params: SpecializeMeshParams, render_meshes: Res>, render_materials: Res>>, render_mesh_instances: Res, @@ -870,12 +871,10 @@ pub fn specialize_material_meshes( ), views: Query<(&ExtractedView, &RenderVisibleEntities)>, view_key_cache: Res, - entity_specialization_ticks: Res>, view_specialization_ticks: Res, mut specialized_material_pipeline_cache: ResMut>, mut pipelines: ResMut>>, pipeline: Res>, - pipeline_cache: Res, ticks: SystemChangeTick, ) where M::Data: PartialEq + Eq + Hash + Clone, @@ -910,7 +909,10 @@ pub fn specialize_material_meshes( let Some(material_asset_id) = render_material_instances.get(visible_entity) else { continue; }; - let entity_tick = entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); @@ -980,7 +982,8 @@ pub fn specialize_material_meshes( .get_extra_data(material.binding.slot) .clone(), }; - let pipeline_id = pipelines.specialize(&pipeline_cache, &pipeline, key, &mesh.layout); + let pipeline_id = + pipelines.specialize(¶ms.pipeline_cache, &pipeline, key, &mesh.layout); let pipeline_id = match pipeline_id { Ok(id) => id, Err(err) => { diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index d287c37285..2e8b0736c8 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -1,13 +1,14 @@ mod prepass_bindings; +use crate::SpecializeMeshParams; use crate::{ alpha_mode_pipeline_key, binding_arrays_are_usable, buffer_layout, collect_meshes_for_gpu_building, material_bind_groups::MaterialBindGroupAllocator, queue_material_meshes, set_mesh_motion_vector_flags, setup_morph_and_skinning_defs, skin, - DrawMesh, EntitySpecializationTicks, Material, MaterialPipeline, MaterialPipelineKey, - MeshLayouts, MeshPipeline, MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial, - RenderLightmaps, RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances, - RenderPhaseType, SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial, + DrawMesh, Material, MaterialPipeline, MaterialPipelineKey, MeshLayouts, MeshPipeline, + MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial, RenderLightmaps, + RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances, RenderPhaseType, + SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial, }; use bevy_app::{App, Plugin, PreUpdate}; use bevy_render::{ @@ -869,6 +870,7 @@ pub fn check_prepass_views_need_specialization( } pub fn specialize_prepass_material_meshes( + params: SpecializeMeshParams, render_meshes: Res>, render_materials: Res>>, render_mesh_instances: Res, @@ -902,7 +904,6 @@ pub fn specialize_prepass_material_meshes( mut pipelines, pipeline_cache, view_specialization_ticks, - entity_specialization_ticks, ): ( ResMut>, SystemChangeTick, @@ -910,7 +911,6 @@ pub fn specialize_prepass_material_meshes( ResMut>>, Res, Res, - Res>, ), ) where M: Material, @@ -941,7 +941,10 @@ pub fn specialize_prepass_material_meshes( let Some(material_asset_id) = render_material_instances.get(visible_entity) else { continue; }; - let entity_tick = entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index eb549bd248..29be9a7bdf 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -1718,6 +1718,7 @@ pub fn check_views_lights_need_specialization( } pub fn specialize_shadows( + params: SpecializeMeshParams, prepass_pipeline: Res>, ( render_meshes, @@ -1734,7 +1735,6 @@ pub fn specialize_shadows( ), shadow_render_phases: Res>, mut pipelines: ResMut>>, - pipeline_cache: Res, render_lightmaps: Res, view_lights: Query<(Entity, &ViewLightEntities), With>, view_light_entities: Query<(&LightEntity, &ExtractedView)>, @@ -1747,7 +1747,6 @@ pub fn specialize_shadows( light_key_cache: Res, mut specialized_material_pipeline_cache: ResMut>, light_specialization_ticks: Res, - entity_specialization_ticks: Res>, ticks: SystemChangeTick, ) where M::Data: PartialEq + Eq + Hash + Clone, @@ -1812,7 +1811,10 @@ pub fn specialize_shadows( let Some(material_asset_id) = render_material_instances.get(&visible_entity) else { continue; }; - let entity_tick = entity_specialization_ticks.get(&visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(&visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(&visible_entity) .map(|(tick, _)| *tick); @@ -1870,7 +1872,7 @@ pub fn specialize_shadows( _ => MeshPipelineKey::NONE, }; let pipeline_id = pipelines.specialize( - &pipeline_cache, + ¶ms.pipeline_cache, &prepass_pipeline, MaterialPipelineKey { mesh_key, diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 98501955a0..e9f54ee415 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -12,7 +12,7 @@ use bevy_diagnostic::FrameCount; use bevy_ecs::{ prelude::*, query::{QueryData, ROQueryItem}, - system::{lifetimeless::*, SystemParamItem, SystemState}, + system::{lifetimeless::*, SystemParam, SystemParamItem, SystemState}, }; use bevy_image::{BevyDefault, ImageSampler, TextureFormatPixelInfo}; use bevy_math::{Affine3, Rect, UVec2, Vec3, Vec4}; @@ -324,6 +324,13 @@ pub struct ViewKeyCache(HashMap); #[derive(Resource, Deref, DerefMut, Default, Debug, Clone)] pub struct ViewSpecializationTicks(HashMap); +/// Parameters shared between mesh specialization systems. +#[derive(SystemParam)] +pub struct SpecializeMeshParams<'w, M: Material> { + pub pipeline_cache: Res<'w, PipelineCache>, + pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, +} + pub fn check_views_need_specialization( mut view_key_cache: ResMut, mut view_specialization_ticks: ResMut, From 40398c6da5625d16c3f54c851d1d061a87d70b2b Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:24:25 +0100 Subject: [PATCH 02/13] Added `render_mesh_instances` and `render_meshes`. --- crates/bevy_pbr/src/material.rs | 8 ++++---- crates/bevy_pbr/src/prepass/mod.rs | 8 ++++---- crates/bevy_pbr/src/render/light.rs | 18 +++++------------- crates/bevy_pbr/src/render/mesh.rs | 2 ++ 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 268cd736fb..0efbca350c 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -850,9 +850,7 @@ pub fn check_entities_needing_specialization( pub fn specialize_material_meshes( params: SpecializeMeshParams, - render_meshes: Res>, render_materials: Res>>, - render_mesh_instances: Res, render_material_instances: Res>, render_lightmaps: Res, render_visibility_ranges: Res, @@ -923,11 +921,13 @@ pub fn specialize_material_meshes( if !needs_specialization { continue; } - let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; }; - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; let Some(material) = render_materials.get(*material_asset_id) else { diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 2e8b0736c8..2073a2a632 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -871,9 +871,7 @@ pub fn check_prepass_views_need_specialization( pub fn specialize_prepass_material_meshes( params: SpecializeMeshParams, - render_meshes: Res>, render_materials: Res>>, - render_mesh_instances: Res, render_material_instances: Res>, render_lightmaps: Res, render_visibility_ranges: Res, @@ -955,7 +953,9 @@ pub fn specialize_prepass_material_meshes( if !needs_specialization { continue; } - let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; }; @@ -968,7 +968,7 @@ pub fn specialize_prepass_material_meshes( warn!("Couldn't get bind group for material"); continue; }; - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 29be9a7bdf..b097ccb60f 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -27,7 +27,6 @@ use bevy_render::{ }; use bevy_render::{ diagnostic::RecordDiagnostics, - mesh::RenderMesh, primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace}, render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext}, @@ -1720,15 +1719,7 @@ pub fn check_views_lights_need_specialization( pub fn specialize_shadows( params: SpecializeMeshParams, prepass_pipeline: Res>, - ( - render_meshes, - render_mesh_instances, - render_materials, - render_material_instances, - material_bind_group_allocator, - ): ( - Res>, - Res, + (render_materials, render_material_instances, material_bind_group_allocator): ( Res>>, Res>, Res>, @@ -1828,8 +1819,9 @@ pub fn specialize_shadows( let Some(material) = render_materials.get(*material_asset_id) else { continue; }; - let Some(mesh_instance) = - render_mesh_instances.render_mesh_queue_data(visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(visible_entity) else { continue; }; @@ -1844,7 +1836,7 @@ pub fn specialize_shadows( else { continue; }; - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index e9f54ee415..625e126a07 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -329,6 +329,8 @@ pub struct ViewSpecializationTicks(HashMap); pub struct SpecializeMeshParams<'w, M: Material> { pub pipeline_cache: Res<'w, PipelineCache>, pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, + pub render_mesh_instances: Res<'w, RenderMeshInstances>, + pub render_meshes: Res<'w, RenderAssets>, } pub fn check_views_need_specialization( From 375b671d0749b546c98fea7ac78c686e3bd3bacd Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:28:04 +0100 Subject: [PATCH 03/13] Added `ticks`. --- crates/bevy_pbr/src/material.rs | 7 +++---- crates/bevy_pbr/src/prepass/mod.rs | 8 +++----- crates/bevy_pbr/src/render/light.rs | 7 +++---- crates/bevy_pbr/src/render/mesh.rs | 1 + 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 0efbca350c..dd351d1907 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -873,7 +873,6 @@ pub fn specialize_material_meshes( mut specialized_material_pipeline_cache: ResMut>, mut pipelines: ResMut>>, pipeline: Res>, - ticks: SystemChangeTick, ) where M::Data: PartialEq + Eq + Hash + Clone, { @@ -915,8 +914,8 @@ pub fn specialize_material_meshes( .get(visible_entity) .map(|(tick, _)| *tick); let needs_specialization = last_specialized_tick.is_none_or(|tick| { - view_tick.is_newer_than(tick, ticks.this_run()) - || entity_tick.is_newer_than(tick, ticks.this_run()) + view_tick.is_newer_than(tick, params.ticks.this_run()) + || entity_tick.is_newer_than(tick, params.ticks.this_run()) }); if !needs_specialization { continue; @@ -993,7 +992,7 @@ pub fn specialize_material_meshes( }; view_specialized_material_pipeline_cache - .insert(*visible_entity, (ticks.this_run(), pipeline_id)); + .insert(*visible_entity, (params.ticks.this_run(), pipeline_id)); } } diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 2073a2a632..7898dfa340 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -897,14 +897,12 @@ pub fn specialize_prepass_material_meshes( ), ( mut specialized_material_pipeline_cache, - ticks, prepass_pipeline, mut pipelines, pipeline_cache, view_specialization_ticks, ): ( ResMut>, - SystemChangeTick, Res>, ResMut>>, Res, @@ -947,8 +945,8 @@ pub fn specialize_prepass_material_meshes( .get(visible_entity) .map(|(tick, _)| *tick); let needs_specialization = last_specialized_tick.is_none_or(|tick| { - view_tick.is_newer_than(tick, ticks.this_run()) - || entity_tick.is_newer_than(tick, ticks.this_run()) + view_tick.is_newer_than(tick, params.ticks.this_run()) + || entity_tick.is_newer_than(tick, params.ticks.this_run()) }); if !needs_specialization { continue; @@ -1056,7 +1054,7 @@ pub fn specialize_prepass_material_meshes( }; view_specialized_material_pipeline_cache - .insert(*visible_entity, (ticks.this_run(), pipeline_id)); + .insert(*visible_entity, (params.ticks.this_run(), pipeline_id)); } } } diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index b097ccb60f..9a9dc1bf48 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -1738,7 +1738,6 @@ pub fn specialize_shadows( light_key_cache: Res, mut specialized_material_pipeline_cache: ResMut>, light_specialization_ticks: Res, - ticks: SystemChangeTick, ) where M::Data: PartialEq + Eq + Hash + Clone, { @@ -1810,8 +1809,8 @@ pub fn specialize_shadows( .get(&visible_entity) .map(|(tick, _)| *tick); let needs_specialization = last_specialized_tick.is_none_or(|tick| { - view_tick.is_newer_than(tick, ticks.this_run()) - || entity_tick.is_newer_than(tick, ticks.this_run()) + view_tick.is_newer_than(tick, params.ticks.this_run()) + || entity_tick.is_newer_than(tick, params.ticks.this_run()) }); if !needs_specialization { continue; @@ -1884,7 +1883,7 @@ pub fn specialize_shadows( }; view_specialized_material_pipeline_cache - .insert(visible_entity, (ticks.this_run(), pipeline_id)); + .insert(visible_entity, (params.ticks.this_run(), pipeline_id)); } } } diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 625e126a07..142d1dfbe1 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -331,6 +331,7 @@ pub struct SpecializeMeshParams<'w, M: Material> { pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, pub render_mesh_instances: Res<'w, RenderMeshInstances>, pub render_meshes: Res<'w, RenderAssets>, + pub ticks: SystemChangeTick, } pub fn check_views_need_specialization( From 7e918967aa5d16b629f05e5ebd1d53e58c1f6394 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Tue, 8 Apr 2025 14:06:21 +0100 Subject: [PATCH 04/13] Tidied up imports. --- crates/bevy_pbr/src/prepass/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 7898dfa340..8685390152 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -1,6 +1,5 @@ mod prepass_bindings; -use crate::SpecializeMeshParams; use crate::{ alpha_mode_pipeline_key, binding_arrays_are_usable, buffer_layout, collect_meshes_for_gpu_building, material_bind_groups::MaterialBindGroupAllocator, @@ -8,7 +7,7 @@ use crate::{ DrawMesh, Material, MaterialPipeline, MaterialPipelineKey, MeshLayouts, MeshPipeline, MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial, RenderLightmaps, RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances, RenderPhaseType, - SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial, + SetMaterialBindGroup, SetMeshBindGroup, ShadowView, SpecializeMeshParams, StandardMaterial, }; use bevy_app::{App, Plugin, PreUpdate}; use bevy_render::{ From 23278e5cf6347ad65521a7371cde4206acbfcf54 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Tue, 8 Apr 2025 14:11:08 +0100 Subject: [PATCH 05/13] Whoops, missed one. --- crates/bevy_pbr/src/prepass/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 8685390152..bb61aef75c 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -898,13 +898,11 @@ pub fn specialize_prepass_material_meshes( mut specialized_material_pipeline_cache, prepass_pipeline, mut pipelines, - pipeline_cache, view_specialization_ticks, ): ( ResMut>, Res>, ResMut>>, - Res, Res, ), ) where @@ -1034,7 +1032,7 @@ pub fn specialize_prepass_material_meshes( } let pipeline_id = pipelines.specialize( - &pipeline_cache, + ¶ms.pipeline_cache, &prepass_pipeline, MaterialPipelineKey { mesh_key, From da5d995b2d88817a0c36422806906feb3316f824 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Thu, 10 Apr 2025 10:39:50 +0100 Subject: [PATCH 06/13] Updated `specialize_wireframes`. This includes refactoring wireframes to reuse `EntitySpecializationTicks` instead of its own type. This meant changing the bounds on `SpecializeMeshParams` since `WireframeMaterial` isn't a `Material`. --- crates/bevy_pbr/src/render/mesh.rs | 2 +- crates/bevy_pbr/src/wireframe.rs | 39 ++++++++++++++---------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index e2681701e0..d2b5d00496 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -326,7 +326,7 @@ pub struct ViewSpecializationTicks(HashMap); /// Parameters shared between mesh specialization systems. #[derive(SystemParam)] -pub struct SpecializeMeshParams<'w, M: Material> { +pub struct SpecializeMeshParams<'w, M: Send + Sync + 'static> { pub pipeline_cache: Res<'w, PipelineCache>, pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, pub render_mesh_instances: Res<'w, RenderMeshInstances>, diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index fa4e920539..242957b242 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -1,6 +1,7 @@ use crate::{ - DrawMesh, MeshPipeline, MeshPipelineKey, RenderMeshInstanceFlags, RenderMeshInstances, - SetMeshBindGroup, SetMeshViewBindGroup, ViewKeyCache, ViewSpecializationTicks, + DrawMesh, EntitySpecializationTicks, MeshPipeline, MeshPipelineKey, RenderMeshInstanceFlags, + RenderMeshInstances, SetMeshBindGroup, SetMeshViewBindGroup, SpecializeMeshParams, + ViewKeyCache, ViewSpecializationTicks, }; use bevy_app::{App, Plugin, PostUpdate, Startup, Update}; use bevy_asset::{ @@ -124,7 +125,7 @@ impl Plugin for WireframePlugin { }; render_app - .init_resource::() + .init_resource::>() .init_resource::() .init_resource::>() .add_render_command::() @@ -498,11 +499,6 @@ pub struct WireframeEntitiesNeedingSpecialization { pub entities: Vec, } -#[derive(Resource, Deref, DerefMut, Clone, Debug, Default)] -pub struct WireframeEntitySpecializationTicks { - pub entities: MainEntityHashMap, -} - /// Stores the [`SpecializedWireframeViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut, Default)] pub struct SpecializedWireframePipelineCache { @@ -698,7 +694,7 @@ fn extract_wireframe_3d_camera( pub fn extract_wireframe_entities_needing_specialization( entities_needing_specialization: Extract>, - mut entity_specialization_ticks: ResMut, + mut entity_specialization_ticks: ResMut>, views: Query<&ExtractedView>, mut specialized_wireframe_pipeline_cache: ResMut, mut removed_meshes_query: Extract>, @@ -739,20 +735,16 @@ pub fn check_wireframe_entities_needing_specialization( } pub fn specialize_wireframes( - render_meshes: Res>, - render_mesh_instances: Res, + params: SpecializeMeshParams, render_wireframe_instances: Res, render_visibility_ranges: Res, wireframe_phases: Res>, views: Query<(&ExtractedView, &RenderVisibleEntities)>, view_key_cache: Res, - entity_specialization_ticks: Res, view_specialization_ticks: Res, mut specialized_material_pipeline_cache: ResMut, mut pipelines: ResMut>, pipeline: Res, - pipeline_cache: Res, - ticks: SystemChangeTick, ) { // Record the retained IDs of all views so that we can expire old // pipeline IDs. @@ -780,22 +772,27 @@ pub fn specialize_wireframes( if !render_wireframe_instances.contains_key(visible_entity) { continue; }; - let entity_tick = entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); let needs_specialization = last_specialized_tick.is_none_or(|tick| { - view_tick.is_newer_than(tick, ticks.this_run()) - || entity_tick.is_newer_than(tick, ticks.this_run()) + view_tick.is_newer_than(tick, params.ticks.this_run()) + || entity_tick.is_newer_than(tick, params.ticks.this_run()) }); if !needs_specialization { continue; } - let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; }; - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; @@ -823,7 +820,7 @@ pub fn specialize_wireframes( } let pipeline_id = - pipelines.specialize(&pipeline_cache, &pipeline, mesh_key, &mesh.layout); + pipelines.specialize(¶ms.pipeline_cache, &pipeline, mesh_key, &mesh.layout); let pipeline_id = match pipeline_id { Ok(id) => id, Err(err) => { @@ -833,7 +830,7 @@ pub fn specialize_wireframes( }; view_specialized_material_pipeline_cache - .insert(*visible_entity, (ticks.this_run(), pipeline_id)); + .insert(*visible_entity, (params.ticks.this_run(), pipeline_id)); } } From e59f6ce273e74da52c81270010306498096b3e1d Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Thu, 10 Apr 2025 10:59:08 +0100 Subject: [PATCH 07/13] Moved `EntitySpecializationTicks` and `SpecializeMeshParams` to `bevy_render`. Also made `RenderMeshInstances` a generic parameter. This is all prep for supporting 2D. --- crates/bevy_pbr/src/material.rs | 18 +--------- crates/bevy_pbr/src/prepass/mod.rs | 4 +-- crates/bevy_pbr/src/render/light.rs | 2 +- crates/bevy_pbr/src/render/mesh.rs | 12 +------ crates/bevy_pbr/src/wireframe.rs | 7 ++-- .../src/render_resource/pipeline_cache.rs | 35 +++++++++++++++++-- 6 files changed, 41 insertions(+), 37 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 465f156565..a625d8fb7a 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -865,22 +865,6 @@ impl Default for EntitiesNeedingSpecialization { } } -#[derive(Resource, Deref, DerefMut, Clone, Debug)] -pub struct EntitySpecializationTicks { - #[deref] - pub entities: MainEntityHashMap, - _marker: PhantomData, -} - -impl Default for EntitySpecializationTicks { - fn default() -> Self { - Self { - entities: MainEntityHashMap::default(), - _marker: Default::default(), - } - } -} - /// Stores the [`SpecializedMaterialViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut)] pub struct SpecializedMaterialPipelineCache { @@ -946,7 +930,7 @@ pub fn check_entities_needing_specialization( } pub fn specialize_material_meshes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, render_materials: Res>>, render_material_instances: Res, render_lightmaps: Res, diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 8664ce0482..b73c8c2255 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -7,7 +7,7 @@ use crate::{ DrawMesh, Material, MaterialPipeline, MaterialPipelineKey, MeshLayouts, MeshPipeline, MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial, RenderLightmaps, RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances, RenderPhaseType, - SetMaterialBindGroup, SetMeshBindGroup, ShadowView, SpecializeMeshParams, StandardMaterial, + SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial, }; use bevy_app::{App, Plugin, PreUpdate}; use bevy_render::{ @@ -869,7 +869,7 @@ pub fn check_prepass_views_need_specialization( } pub fn specialize_prepass_material_meshes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, render_materials: Res>>, render_material_instances: Res, render_lightmaps: Res, diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 95e9319c9a..965e73b97c 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -1717,7 +1717,7 @@ pub fn check_views_lights_need_specialization( } pub fn specialize_shadows( - params: SpecializeMeshParams, + params: SpecializeMeshParams, prepass_pipeline: Res>, (render_materials, render_material_instances, material_bind_group_allocator): ( Res>>, diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index d2b5d00496..0136418e0f 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -12,7 +12,7 @@ use bevy_diagnostic::FrameCount; use bevy_ecs::{ prelude::*, query::{QueryData, ROQueryItem}, - system::{lifetimeless::*, SystemParam, SystemParamItem, SystemState}, + system::{lifetimeless::*, SystemParamItem, SystemState}, }; use bevy_image::{BevyDefault, ImageSampler, TextureFormatPixelInfo}; use bevy_math::{Affine3, Rect, UVec2, Vec3, Vec4}; @@ -324,16 +324,6 @@ pub struct ViewKeyCache(HashMap); #[derive(Resource, Deref, DerefMut, Default, Debug, Clone)] pub struct ViewSpecializationTicks(HashMap); -/// Parameters shared between mesh specialization systems. -#[derive(SystemParam)] -pub struct SpecializeMeshParams<'w, M: Send + Sync + 'static> { - pub pipeline_cache: Res<'w, PipelineCache>, - pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, - pub render_mesh_instances: Res<'w, RenderMeshInstances>, - pub render_meshes: Res<'w, RenderAssets>, - pub ticks: SystemChangeTick, -} - pub fn check_views_need_specialization( mut view_key_cache: ResMut, mut view_specialization_ticks: ResMut, diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index 242957b242..9c53faf646 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -1,7 +1,6 @@ use crate::{ - DrawMesh, EntitySpecializationTicks, MeshPipeline, MeshPipelineKey, RenderMeshInstanceFlags, - RenderMeshInstances, SetMeshBindGroup, SetMeshViewBindGroup, SpecializeMeshParams, - ViewKeyCache, ViewSpecializationTicks, + DrawMesh, MeshPipeline, MeshPipelineKey, RenderMeshInstanceFlags, RenderMeshInstances, + SetMeshBindGroup, SetMeshViewBindGroup, ViewKeyCache, ViewSpecializationTicks, }; use bevy_app::{App, Plugin, PostUpdate, Startup, Update}; use bevy_asset::{ @@ -735,7 +734,7 @@ pub fn check_wireframe_entities_needing_specialization( } pub fn specialize_wireframes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, render_wireframe_instances: Res, render_visibility_ranges: Res, wireframe_phases: Res>, diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 613737f3de..096a28a065 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -1,20 +1,25 @@ use crate::renderer::WgpuWrapper; use crate::{ + mesh::RenderMesh, + render_asset::RenderAssets, render_resource::*, renderer::{RenderAdapter, RenderDevice}, + sync_world::MainEntityHashMap, Extract, }; use alloc::{borrow::Cow, sync::Arc}; use bevy_asset::{AssetEvent, AssetId, Assets}; +use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ + component::Tick, event::EventReader, resource::Resource, - system::{Res, ResMut}, + system::{Res, ResMut, SystemChangeTick, SystemParam}, }; use bevy_platform_support::collections::{hash_map::EntryRef, HashMap, HashSet}; use bevy_tasks::Task; use bevy_utils::default; -use core::{future::Future, hash::Hash, mem, ops::Deref}; +use core::{future::Future, hash::Hash, marker::PhantomData, mem, ops::Deref}; use naga::valid::Capabilities; use std::sync::{Mutex, PoisonError}; use thiserror::Error; @@ -1066,6 +1071,32 @@ impl PipelineCache { } } +#[derive(Resource, Deref, DerefMut, Clone, Debug)] +pub struct EntitySpecializationTicks { + #[deref] + pub entities: MainEntityHashMap, + _marker: PhantomData, +} + +impl Default for EntitySpecializationTicks { + fn default() -> Self { + Self { + entities: MainEntityHashMap::default(), + _marker: Default::default(), + } + } +} + +/// Parameters shared between mesh specialization systems. +#[derive(SystemParam)] +pub struct SpecializeMeshParams<'w, M: Send + Sync + 'static, RenderMeshInstances: Resource> { + pub pipeline_cache: Res<'w, PipelineCache>, + pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, + pub render_mesh_instances: Res<'w, RenderMeshInstances>, + pub render_meshes: Res<'w, RenderAssets>, + pub ticks: SystemChangeTick, +} + #[cfg(all( not(target_arch = "wasm32"), not(target_os = "macos"), From 5635184b6ba7e5a1fa55ba2559932cdfdda4244e Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Thu, 10 Apr 2025 11:00:54 +0100 Subject: [PATCH 08/13] Changed `specialize_material2d_meshes` to use `SpecializeMeshParams`. --- crates/bevy_sprite/src/mesh2d/material.rs | 49 ++++++++--------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 5df02cfc7b..172cd77a3d 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -23,7 +23,9 @@ use bevy_platform_support::collections::HashMap; use bevy_reflect::{prelude::ReflectDefault, Reflect}; use bevy_render::camera::extract_cameras; use bevy_render::render_phase::{DrawFunctionId, InputUniformIndex}; -use bevy_render::render_resource::CachedRenderPipelineId; +use bevy_render::render_resource::{ + CachedRenderPipelineId, EntitySpecializationTicks, SpecializeMeshParams, +}; use bevy_render::view::RenderVisibleEntities; use bevy_render::{ mesh::{MeshVertexBufferLayoutRef, RenderMesh}, @@ -37,7 +39,7 @@ use bevy_render::{ }, render_resource::{ AsBindGroup, AsBindGroupError, BindGroup, BindGroupId, BindGroupLayout, BindingResources, - PipelineCache, RenderPipelineDescriptor, Shader, ShaderRef, SpecializedMeshPipeline, + RenderPipelineDescriptor, Shader, ShaderRef, SpecializedMeshPipeline, SpecializedMeshPipelineError, SpecializedMeshPipelines, }, renderer::RenderDevice, @@ -595,22 +597,6 @@ impl Default for EntitiesNeedingSpecialization { } } -#[derive(Clone, Resource, Deref, DerefMut, Debug)] -pub struct EntitySpecializationTicks { - #[deref] - pub entities: MainEntityHashMap, - _marker: PhantomData, -} - -impl Default for EntitySpecializationTicks { - fn default() -> Self { - Self { - entities: MainEntityHashMap::default(), - _marker: Default::default(), - } - } -} - /// Stores the [`SpecializedMaterial2dViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut)] pub struct SpecializedMaterial2dPipelineCache { @@ -676,23 +662,17 @@ pub fn check_entities_needing_specialization( } pub fn specialize_material2d_meshes( + params: SpecializeMeshParams, material2d_pipeline: Res>, mut pipelines: ResMut>>, - pipeline_cache: Res, - (render_meshes, render_materials): ( - Res>, - Res>>, - ), - mut render_mesh_instances: ResMut, + render_materials: Res>>, render_material_instances: Res>, transparent_render_phases: Res>, opaque_render_phases: Res>, alpha_mask_render_phases: Res>, views: Query<(&MainEntity, &ExtractedView, &RenderVisibleEntities)>, view_key_cache: Res, - entity_specialization_ticks: Res>, view_specialization_ticks: Res, - ticks: SystemChangeTick, mut specialized_material_pipeline_cache: ResMut>, ) where M::Data: PartialEq + Eq + Hash + Clone, @@ -722,24 +702,27 @@ pub fn specialize_material2d_meshes( let Some(material_asset_id) = render_material_instances.get(visible_entity) else { continue; }; - let entity_tick = entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); let needs_specialization = last_specialized_tick.is_none_or(|tick| { - view_tick.is_newer_than(tick, ticks.this_run()) - || entity_tick.is_newer_than(tick, ticks.this_run()) + view_tick.is_newer_than(tick, params.ticks.this_run()) + || entity_tick.is_newer_than(tick, params.ticks.this_run()) }); if !needs_specialization { continue; } - let Some(mesh_instance) = render_mesh_instances.get_mut(visible_entity) else { + let Some(mesh_instance) = params.render_mesh_instances.get(visible_entity) else { continue; }; let Some(material_2d) = render_materials.get(*material_asset_id) else { continue; }; - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; let mesh_key = *view_key @@ -747,7 +730,7 @@ pub fn specialize_material2d_meshes( | material_2d.properties.mesh_pipeline_key_bits; let pipeline_id = pipelines.specialize( - &pipeline_cache, + ¶ms.pipeline_cache, &material2d_pipeline, Material2dKey { mesh_key, @@ -765,7 +748,7 @@ pub fn specialize_material2d_meshes( }; view_specialized_material_pipeline_cache - .insert(*visible_entity, (ticks.this_run(), pipeline_id)); + .insert(*visible_entity, (params.ticks.this_run(), pipeline_id)); } } } From 2f3130706447a1836520ed772b5c6b255c98e24f Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Thu, 10 Apr 2025 11:22:21 +0100 Subject: [PATCH 09/13] Changed `bevy_2d/specialize_wireframes` to use `SpecializeMeshParams`. This meant some light refactoring to replace `WireframeEntitySpecializationTicks` with `EntitySpecializationTicks`. --- crates/bevy_sprite/src/mesh2d/wireframe2d.rs | 32 ++++++++------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/crates/bevy_sprite/src/mesh2d/wireframe2d.rs b/crates/bevy_sprite/src/mesh2d/wireframe2d.rs index 0aef177765..66bfa72168 100644 --- a/crates/bevy_sprite/src/mesh2d/wireframe2d.rs +++ b/crates/bevy_sprite/src/mesh2d/wireframe2d.rs @@ -122,7 +122,7 @@ impl Plugin for Wireframe2dPlugin { }; render_app - .init_resource::() + .init_resource::>() .init_resource::() .init_resource::>() .add_render_command::() @@ -497,11 +497,6 @@ pub struct WireframeEntitiesNeedingSpecialization { pub entities: Vec, } -#[derive(Resource, Deref, DerefMut, Clone, Debug, Default)] -pub struct WireframeEntitySpecializationTicks { - pub entities: MainEntityHashMap, -} - /// Stores the [`SpecializedWireframeViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut, Default)] pub struct SpecializedWireframePipelineCache { @@ -690,7 +685,7 @@ fn extract_wireframe_2d_camera( pub fn extract_wireframe_entities_needing_specialization( entities_needing_specialization: Extract>, - mut entity_specialization_ticks: ResMut, + mut entity_specialization_ticks: ResMut>, views: Query<&ExtractedView>, mut specialized_wireframe_pipeline_cache: ResMut, mut removed_meshes_query: Extract>, @@ -731,19 +726,15 @@ pub fn check_wireframe_entities_needing_specialization( } pub fn specialize_wireframes( - render_meshes: Res>, - render_mesh_instances: Res, + params: SpecializeMeshParams, render_wireframe_instances: Res, wireframe_phases: Res>, views: Query<(&ExtractedView, &RenderVisibleEntities)>, view_key_cache: Res, - entity_specialization_ticks: Res, view_specialization_ticks: Res, mut specialized_material_pipeline_cache: ResMut, mut pipelines: ResMut>, pipeline: Res, - pipeline_cache: Res, - ticks: SystemChangeTick, ) { // Record the retained IDs of all views so that we can expire old // pipeline IDs. @@ -771,21 +762,24 @@ pub fn specialize_wireframes( if !render_wireframe_instances.contains_key(visible_entity) { continue; }; - let entity_tick = entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); let needs_specialization = last_specialized_tick.is_none_or(|tick| { - view_tick.is_newer_than(tick, ticks.this_run()) - || entity_tick.is_newer_than(tick, ticks.this_run()) + view_tick.is_newer_than(tick, params.ticks.this_run()) + || entity_tick.is_newer_than(tick, params.ticks.this_run()) }); if !needs_specialization { continue; } - let Some(mesh_instance) = render_mesh_instances.get(visible_entity) else { + let Some(mesh_instance) = params.render_mesh_instances.get(visible_entity) else { continue; }; - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; @@ -793,7 +787,7 @@ pub fn specialize_wireframes( mesh_key |= Mesh2dPipelineKey::from_primitive_topology(mesh.primitive_topology()); let pipeline_id = - pipelines.specialize(&pipeline_cache, &pipeline, mesh_key, &mesh.layout); + pipelines.specialize(¶ms.pipeline_cache, &pipeline, mesh_key, &mesh.layout); let pipeline_id = match pipeline_id { Ok(id) => id, Err(err) => { @@ -803,7 +797,7 @@ pub fn specialize_wireframes( }; view_specialized_material_pipeline_cache - .insert(*visible_entity, (ticks.this_run(), pipeline_id)); + .insert(*visible_entity, (params.ticks.this_run(), pipeline_id)); } } From 47475f208612aab9e29fa7873a018008aeb7e2d3 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Thu, 10 Apr 2025 11:42:23 +0100 Subject: [PATCH 10/13] Restore broken comment. I thought this was a merge error, but it's present in main. --- crates/bevy_pbr/src/light/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_pbr/src/light/mod.rs b/crates/bevy_pbr/src/light/mod.rs index 91ea9cddd3..e1a28e6a6a 100644 --- a/crates/bevy_pbr/src/light/mod.rs +++ b/crates/bevy_pbr/src/light/mod.rs @@ -103,6 +103,7 @@ pub mod light_consts { #[reflect(Resource, Debug, Default, Clone)] pub struct PointLightShadowMap { /// The width and height of each of the 6 faces of the cubemap. + /// /// Defaults to `1024`. pub size: usize, From a32104feaa7e5666858c4dd8709d429b9096d5f7 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Mon, 21 Apr 2025 08:05:38 +0100 Subject: [PATCH 11/13] `cargo fmt`. --- crates/bevy_pbr/src/material.rs | 9 +++++++-- crates/bevy_pbr/src/prepass/mod.rs | 9 +++++++-- crates/bevy_pbr/src/render/light.rs | 10 +++++++--- crates/bevy_pbr/src/wireframe.rs | 9 +++++++-- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 36f135207f..645465d98e 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -996,11 +996,16 @@ pub fn specialize_material_meshes( let Ok(material_asset_id) = material_instance.asset_id.try_typed::() else { continue; }; - let Some(mesh_instance) = params.render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; }; - let entity_tick = params.entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 24adc9eee8..5ea87a397b 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -938,11 +938,16 @@ pub fn specialize_prepass_material_meshes( let Ok(material_asset_id) = material_instance.asset_id.try_typed::() else { continue; }; - let Some(mesh_instance) = params.render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; }; - let entity_tick = params.entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index c45e835d2e..24e1fb3504 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -1806,12 +1806,16 @@ pub fn specialize_shadows( let Ok(material_asset_id) = material_instances.asset_id.try_typed::() else { continue; }; - let Some(mesh_instance) = - params.render_mesh_instances.render_mesh_queue_data(visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(visible_entity) else { continue; }; - let entity_tick = params.entity_specialization_ticks.get(&visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(&visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(&visible_entity) .map(|(tick, _)| *tick); diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index 1dc5e09bfd..17679d9da2 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -771,11 +771,16 @@ pub fn specialize_wireframes( if !render_wireframe_instances.contains_key(visible_entity) { continue; }; - let Some(mesh_instance) = params.render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; }; - let entity_tick = params.entity_specialization_ticks.get(visible_entity).unwrap(); + let entity_tick = params + .entity_specialization_ticks + .get(visible_entity) + .unwrap(); let last_specialized_tick = view_specialized_material_pipeline_cache .get(visible_entity) .map(|(tick, _)| *tick); From ac1ba0010077949535fe52dfdc4a913df603d687 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Tue, 15 Jul 2025 13:13:10 +0100 Subject: [PATCH 12/13] First pass at post-merge fixup. Reverted `EntitySpecializationTicks` refactoring as it depended on the generic parameter which has been erased in #19667. --- crates/bevy_pbr/src/material.rs | 16 ++++++++--- crates/bevy_pbr/src/prepass/mod.rs | 9 +++---- crates/bevy_pbr/src/render/light.rs | 19 ++++++------- crates/bevy_pbr/src/wireframe.rs | 11 +++++--- .../src/render_resource/pipeline_cache.rs | 27 +++++-------------- crates/bevy_sprite/src/mesh2d/material.rs | 22 ++++++++++++--- crates/bevy_sprite/src/mesh2d/wireframe2d.rs | 11 +++++--- 7 files changed, 64 insertions(+), 51 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index fa1444aba7..0ba4654324 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -35,7 +35,7 @@ use bevy_render::erased_render_asset::{ ErasedRenderAsset, ErasedRenderAssetPlugin, ErasedRenderAssets, PrepareAssetError, }; use bevy_render::mesh::mark_3d_meshes_as_changed_if_their_assets_changed; -use bevy_render::render_asset::{prepare_assets, RenderAssets}; +use bevy_render::render_asset::prepare_assets; use bevy_render::renderer::RenderQueue; use bevy_render::RenderStartup; use bevy_render::{ @@ -822,6 +822,12 @@ impl Default for EntitiesNeedingSpecialization { } } +#[derive(Resource, Deref, DerefMut, Default, Clone, Debug)] +pub struct EntitySpecializationTicks { + #[deref] + pub entities: MainEntityHashMap, +} + /// Stores the [`SpecializedMaterialViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut, Default)] pub struct SpecializedMaterialPipelineCache { @@ -867,7 +873,7 @@ pub fn check_entities_needing_specialization( } pub fn specialize_material_meshes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, render_materials: Res>, render_material_instances: Res, render_lightmaps: Res, @@ -921,7 +927,9 @@ pub fn specialize_material_meshes( else { continue; }; - let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; }; @@ -993,7 +1001,7 @@ pub fn specialize_material_meshes( properties: material.properties.clone(), }; let pipeline_id = pipelines.specialize( - &pipeline_cache, + ¶ms.pipeline_cache, &material_pipeline_specializer, erased_key, &mesh.layout, diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 58fa2a2c1a..d2419709ab 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -40,7 +40,6 @@ use bevy_math::{Affine3A, Vec4}; use bevy_render::{ globals::{GlobalsBuffer, GlobalsUniform}, prelude::{Camera, Mesh}, - render_asset::RenderAssets, render_phase::*, render_resource::*, renderer::{RenderDevice, RenderQueue}, @@ -817,7 +816,7 @@ pub fn check_prepass_views_need_specialization( } pub fn specialize_prepass_material_meshes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, render_materials: Res>, render_material_instances: Res, render_lightmaps: Res, @@ -879,7 +878,7 @@ pub fn specialize_prepass_material_meshes( else { continue; }; - let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params.render_mesh_instances.render_mesh_queue_data(*visible_entity) else { continue; }; @@ -905,7 +904,7 @@ pub fn specialize_prepass_material_meshes( view_specialized_material_pipeline_cache.remove(visible_entity); continue; } - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; @@ -989,7 +988,7 @@ pub fn specialize_prepass_material_meshes( properties: material.properties.clone(), }; let pipeline_id = pipelines.specialize( - &pipeline_cache, + ¶ms.pipeline_cache, &prepass_pipeline_specializer, erased_key, &mesh.layout, diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 6b3253735b..0c42eaa3e3 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -35,7 +35,6 @@ use bevy_render::{ use bevy_render::{ diagnostic::RecordDiagnostics, primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace}, - render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext}, render_phase::*, render_resource::*, @@ -1685,10 +1684,9 @@ pub fn check_views_lights_need_specialization( } pub fn specialize_shadows( - params: SpecializeMeshParams, + params: SpecializeMeshParams, prepass_pipeline: Res, - (render_meshes, render_materials, render_material_instances): ( - Res>, + (render_materials, render_material_instances): ( Res>, Res, ), @@ -1706,9 +1704,7 @@ pub fn specialize_shadows( light_key_cache: Res, mut specialized_material_pipeline_cache: ResMut, light_specialization_ticks: Res, -) where - M::Data: PartialEq + Eq + Hash + Clone, -{ +) { // Record the retained IDs of all shadow views so that we can expire old // pipeline IDs. let mut all_shadow_views: HashSet = HashSet::default(); @@ -1772,8 +1768,9 @@ pub fn specialize_shadows( continue; }; - let Some(mesh_instance) = - render_mesh_instances.render_mesh_queue_data(visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(visible_entity) else { continue; }; @@ -1804,7 +1801,7 @@ pub fn specialize_shadows( { continue; } - let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; @@ -1841,7 +1838,7 @@ pub fn specialize_shadows( properties: material.properties.clone(), }; let pipeline_id = pipelines.specialize( - &pipeline_cache, + ¶ms.pipeline_cache, &material_pipeline_specializer, erased_key, &mesh.layout, diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index b39625be39..a77b42cd02 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -117,7 +117,7 @@ impl Plugin for WireframePlugin { }; render_app - .init_resource::>() + .init_resource::() .init_resource::() .init_resource::>() .add_render_command::() @@ -489,6 +489,11 @@ pub struct WireframeEntitiesNeedingSpecialization { pub entities: Vec, } +#[derive(Resource, Deref, DerefMut, Clone, Debug, Default)] +pub struct WireframeEntitySpecializationTicks { + pub entities: MainEntityHashMap, +} + /// Stores the [`SpecializedWireframeViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut, Default)] pub struct SpecializedWireframePipelineCache { @@ -684,7 +689,7 @@ fn extract_wireframe_3d_camera( pub fn extract_wireframe_entities_needing_specialization( entities_needing_specialization: Extract>, - mut entity_specialization_ticks: ResMut>, + mut entity_specialization_ticks: ResMut, views: Query<&ExtractedView>, mut specialized_wireframe_pipeline_cache: ResMut, mut removed_meshes_query: Extract>, @@ -725,7 +730,7 @@ pub fn check_wireframe_entities_needing_specialization( } pub fn specialize_wireframes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, render_wireframe_instances: Res, render_visibility_ranges: Res, wireframe_phases: Res>, diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 132e25e964..f163257823 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -3,14 +3,11 @@ use crate::{ render_asset::RenderAssets, render_resource::*, renderer::{RenderAdapter, RenderDevice}, - sync_world::MainEntityHashMap, Extract, }; use alloc::{borrow::Cow, sync::Arc}; use bevy_asset::{AssetEvent, AssetId, Assets}; -use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ - component::Tick, event::EventReader, resource::Resource, system::{Res, ResMut, SystemChangeTick, SystemParam}, @@ -1087,27 +1084,15 @@ impl PipelineCache { } } -#[derive(Resource, Deref, DerefMut, Clone, Debug)] -pub struct EntitySpecializationTicks { - #[deref] - pub entities: MainEntityHashMap, - _marker: PhantomData, -} - -impl Default for EntitySpecializationTicks { - fn default() -> Self { - Self { - entities: MainEntityHashMap::default(), - _marker: Default::default(), - } - } -} - /// Parameters shared between mesh specialization systems. #[derive(SystemParam)] -pub struct SpecializeMeshParams<'w, M: Send + Sync + 'static, RenderMeshInstances: Resource> { +pub struct SpecializeMeshParams< + 'w, + EntitySpecializationTicks: Resource, + RenderMeshInstances: Resource, +> { pub pipeline_cache: Res<'w, PipelineCache>, - pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, + pub entity_specialization_ticks: Res<'w, EntitySpecializationTicks>, pub render_mesh_instances: Res<'w, RenderMeshInstances>, pub render_meshes: Res<'w, RenderAssets>, pub ticks: SystemChangeTick, diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 5390fa69b4..6400b19a35 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -24,9 +24,7 @@ use bevy_platform::collections::HashMap; use bevy_reflect::{prelude::ReflectDefault, Reflect}; use bevy_render::camera::extract_cameras; use bevy_render::render_phase::{DrawFunctionId, InputUniformIndex}; -use bevy_render::render_resource::{ - CachedRenderPipelineId, EntitySpecializationTicks, SpecializeMeshParams, -}; +use bevy_render::render_resource::{CachedRenderPipelineId, SpecializeMeshParams}; use bevy_render::view::RenderVisibleEntities; use bevy_render::RenderStartup; use bevy_render::{ @@ -596,6 +594,22 @@ impl Default for EntitiesNeedingSpecialization { } } +#[derive(Clone, Resource, Deref, DerefMut, Debug)] +pub struct EntitySpecializationTicks { + #[deref] + pub entities: MainEntityHashMap, + _marker: PhantomData, +} + +impl Default for EntitySpecializationTicks { + fn default() -> Self { + Self { + entities: MainEntityHashMap::default(), + _marker: Default::default(), + } + } +} + /// Stores the [`SpecializedMaterial2dViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut)] pub struct SpecializedMaterial2dPipelineCache { @@ -661,7 +675,7 @@ pub fn check_entities_needing_specialization( } pub fn specialize_material2d_meshes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, RenderMesh2dInstances>, material2d_pipeline: Res>, mut pipelines: ResMut>>, render_materials: Res>>, diff --git a/crates/bevy_sprite/src/mesh2d/wireframe2d.rs b/crates/bevy_sprite/src/mesh2d/wireframe2d.rs index 2b25587c74..4389c768d0 100644 --- a/crates/bevy_sprite/src/mesh2d/wireframe2d.rs +++ b/crates/bevy_sprite/src/mesh2d/wireframe2d.rs @@ -114,7 +114,7 @@ impl Plugin for Wireframe2dPlugin { }; render_app - .init_resource::>() + .init_resource::() .init_resource::() .init_resource::>() .add_render_command::() @@ -489,6 +489,11 @@ pub struct WireframeEntitiesNeedingSpecialization { pub entities: Vec, } +#[derive(Resource, Deref, DerefMut, Clone, Debug, Default)] +pub struct WireframeEntitySpecializationTicks { + pub entities: MainEntityHashMap, +} + /// Stores the [`SpecializedWireframeViewPipelineCache`] for each view. #[derive(Resource, Deref, DerefMut, Default)] pub struct SpecializedWireframePipelineCache { @@ -677,7 +682,7 @@ fn extract_wireframe_2d_camera( pub fn extract_wireframe_entities_needing_specialization( entities_needing_specialization: Extract>, - mut entity_specialization_ticks: ResMut>, + mut entity_specialization_ticks: ResMut, views: Query<&ExtractedView>, mut specialized_wireframe_pipeline_cache: ResMut, mut removed_meshes_query: Extract>, @@ -718,7 +723,7 @@ pub fn check_wireframe_entities_needing_specialization( } pub fn specialize_wireframes( - params: SpecializeMeshParams, + params: SpecializeMeshParams, render_wireframe_instances: Res, wireframe_phases: Res>, views: Query<(&ExtractedView, &RenderVisibleEntities)>, From b9356a12f30962e0034ddfd47ea411774433c522 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Tue, 15 Jul 2025 13:18:25 +0100 Subject: [PATCH 13/13] Fixed formatting. --- crates/bevy_pbr/src/prepass/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index d2419709ab..75900ad4ac 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -878,7 +878,9 @@ pub fn specialize_prepass_material_meshes( else { continue; }; - let Some(mesh_instance) = params.render_mesh_instances.render_mesh_queue_data(*visible_entity) + let Some(mesh_instance) = params + .render_mesh_instances + .render_mesh_queue_data(*visible_entity) else { continue; };