diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 3ebc89bccd0e4..0ba465432476f 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::{ @@ -873,9 +873,8 @@ pub fn check_entities_needing_specialization( } pub fn specialize_material_meshes( - render_meshes: Res>, + params: SpecializeMeshParams, render_materials: Res>, - render_mesh_instances: Res, render_material_instances: Res, render_lightmaps: Res, render_visibility_ranges: Res, @@ -892,13 +891,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, ) { // Record the retained IDs of all shadow views so that we can expire old // pipeline IDs. @@ -931,22 +927,27 @@ 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; }; - 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) = 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_instance.asset_id) else { @@ -1000,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, @@ -1014,7 +1015,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 66de219a90186..75900ad4ac0f2 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,9 +816,8 @@ pub fn check_prepass_views_need_specialization( } pub fn specialize_prepass_material_meshes( - render_meshes: Res>, + params: SpecializeMeshParams, render_materials: Res>, - render_mesh_instances: Res, render_material_instances: Res, render_lightmaps: Res, render_visibility_ranges: Res, @@ -844,20 +842,14 @@ pub fn specialize_prepass_material_meshes( ), ( mut specialized_material_pipeline_cache, - ticks, prepass_pipeline, mut pipelines, - pipeline_cache, view_specialization_ticks, - entity_specialization_ticks, ): ( ResMut, - SystemChangeTick, Res, ResMut>, - Res, Res, - Res, ), ) { for (extracted_view, visible_entities, msaa, motion_vector_prepass, deferred_prepass) in &views @@ -886,17 +878,22 @@ 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; }; - 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; @@ -909,7 +906,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; }; @@ -993,7 +990,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, @@ -1007,7 +1004,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 74dc0ff15d366..0c42eaa3e3d6b 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -34,9 +34,7 @@ use bevy_render::{ }; use bevy_render::{ diagnostic::RecordDiagnostics, - mesh::RenderMesh, primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace}, - render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext}, render_phase::*, render_resource::*, @@ -1686,16 +1684,14 @@ 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): ( - Res>, - Res, + (render_materials, render_material_instances): ( Res>, Res, ), 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)>, @@ -1708,8 +1704,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, ) { // Record the retained IDs of all shadow views so that we can expire old // pipeline IDs. @@ -1774,18 +1768,22 @@ 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; }; - 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; @@ -1803,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; }; @@ -1840,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, @@ -1854,7 +1852,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/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index ad280e054f67d..a77b42cd0235a 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -730,20 +730,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. @@ -771,22 +767,27 @@ pub fn specialize_wireframes( if !render_wireframe_instances.contains_key(visible_entity) { 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 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) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; @@ -814,7 +815,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) => { @@ -824,7 +825,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)); } } diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 328c5e5600edb..f163257823e42 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -1,4 +1,6 @@ use crate::{ + mesh::RenderMesh, + render_asset::RenderAssets, render_resource::*, renderer::{RenderAdapter, RenderDevice}, Extract, @@ -8,7 +10,7 @@ use bevy_asset::{AssetEvent, AssetId, Assets}; use bevy_ecs::{ event::EventReader, resource::Resource, - system::{Res, ResMut}, + system::{Res, ResMut, SystemChangeTick, SystemParam}, }; use bevy_platform::collections::{hash_map::EntryRef, HashMap, HashSet}; use bevy_tasks::Task; @@ -1082,6 +1084,20 @@ impl PipelineCache { } } +/// Parameters shared between mesh specialization systems. +#[derive(SystemParam)] +pub struct SpecializeMeshParams< + 'w, + EntitySpecializationTicks: Resource, + 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"), diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 8d575d8be4edb..6400b19a35449 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -24,7 +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; +use bevy_render::render_resource::{CachedRenderPipelineId, SpecializeMeshParams}; use bevy_render::view::RenderVisibleEntities; use bevy_render::RenderStartup; use bevy_render::{ @@ -39,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, @@ -675,23 +675,17 @@ pub fn check_entities_needing_specialization( } pub fn specialize_material2d_meshes( + params: SpecializeMeshParams, RenderMesh2dInstances>, 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, @@ -721,16 +715,19 @@ pub fn specialize_material2d_meshes( let Some(material_asset_id) = render_material_instances.get(visible_entity) else { 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 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; @@ -738,7 +735,7 @@ pub fn specialize_material2d_meshes( 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 @@ -746,7 +743,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, @@ -764,7 +761,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)); } } } diff --git a/crates/bevy_sprite/src/mesh2d/wireframe2d.rs b/crates/bevy_sprite/src/mesh2d/wireframe2d.rs index 912c25f9bb019..4389c768d07c8 100644 --- a/crates/bevy_sprite/src/mesh2d/wireframe2d.rs +++ b/crates/bevy_sprite/src/mesh2d/wireframe2d.rs @@ -723,19 +723,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. @@ -763,21 +759,24 @@ pub fn specialize_wireframes( if !render_wireframe_instances.contains_key(visible_entity) { 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 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) = render_meshes.get(mesh_instance.mesh_asset_id) else { + let Some(mesh) = params.render_meshes.get(mesh_instance.mesh_asset_id) else { continue; }; @@ -785,7 +784,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) => { @@ -795,7 +794,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)); } }