This commit is contained in:
Greeble 2025-07-18 12:37:46 -04:00 committed by GitHub
commit cc5afeabea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 96 additions and 87 deletions

View File

@ -35,7 +35,7 @@ use bevy_render::erased_render_asset::{
ErasedRenderAsset, ErasedRenderAssetPlugin, ErasedRenderAssets, PrepareAssetError, ErasedRenderAsset, ErasedRenderAssetPlugin, ErasedRenderAssets, PrepareAssetError,
}; };
use bevy_render::mesh::mark_3d_meshes_as_changed_if_their_assets_changed; 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::renderer::RenderQueue;
use bevy_render::RenderStartup; use bevy_render::RenderStartup;
use bevy_render::{ use bevy_render::{
@ -873,9 +873,8 @@ pub fn check_entities_needing_specialization<M>(
} }
pub fn specialize_material_meshes( pub fn specialize_material_meshes(
render_meshes: Res<RenderAssets<RenderMesh>>, params: SpecializeMeshParams<EntitySpecializationTicks, RenderMeshInstances>,
render_materials: Res<ErasedRenderAssets<PreparedMaterial>>, render_materials: Res<ErasedRenderAssets<PreparedMaterial>>,
render_mesh_instances: Res<RenderMeshInstances>,
render_material_instances: Res<RenderMaterialInstances>, render_material_instances: Res<RenderMaterialInstances>,
render_lightmaps: Res<RenderLightmaps>, render_lightmaps: Res<RenderLightmaps>,
render_visibility_ranges: Res<RenderVisibilityRanges>, render_visibility_ranges: Res<RenderVisibilityRanges>,
@ -892,13 +891,10 @@ pub fn specialize_material_meshes(
), ),
views: Query<(&ExtractedView, &RenderVisibleEntities)>, views: Query<(&ExtractedView, &RenderVisibleEntities)>,
view_key_cache: Res<ViewKeyCache>, view_key_cache: Res<ViewKeyCache>,
entity_specialization_ticks: Res<EntitySpecializationTicks>,
view_specialization_ticks: Res<ViewSpecializationTicks>, view_specialization_ticks: Res<ViewSpecializationTicks>,
mut specialized_material_pipeline_cache: ResMut<SpecializedMaterialPipelineCache>, mut specialized_material_pipeline_cache: ResMut<SpecializedMaterialPipelineCache>,
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipelineSpecializer>>, mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipelineSpecializer>>,
pipeline: Res<MaterialPipeline>, pipeline: Res<MaterialPipeline>,
pipeline_cache: Res<PipelineCache>,
ticks: SystemChangeTick,
) { ) {
// Record the retained IDs of all shadow views so that we can expire old // Record the retained IDs of all shadow views so that we can expire old
// pipeline IDs. // pipeline IDs.
@ -931,22 +927,27 @@ pub fn specialize_material_meshes(
else { else {
continue; 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 { else {
continue; 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 let last_specialized_tick = view_specialized_material_pipeline_cache
.get(visible_entity) .get(visible_entity)
.map(|(tick, _)| *tick); .map(|(tick, _)| *tick);
let needs_specialization = last_specialized_tick.is_none_or(|tick| { let needs_specialization = last_specialized_tick.is_none_or(|tick| {
view_tick.is_newer_than(tick, ticks.this_run()) view_tick.is_newer_than(tick, params.ticks.this_run())
|| entity_tick.is_newer_than(tick, ticks.this_run()) || entity_tick.is_newer_than(tick, params.ticks.this_run())
}); });
if !needs_specialization { if !needs_specialization {
continue; 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; continue;
}; };
let Some(material) = render_materials.get(material_instance.asset_id) else { let Some(material) = render_materials.get(material_instance.asset_id) else {
@ -1000,7 +1001,7 @@ pub fn specialize_material_meshes(
properties: material.properties.clone(), properties: material.properties.clone(),
}; };
let pipeline_id = pipelines.specialize( let pipeline_id = pipelines.specialize(
&pipeline_cache, &params.pipeline_cache,
&material_pipeline_specializer, &material_pipeline_specializer,
erased_key, erased_key,
&mesh.layout, &mesh.layout,
@ -1014,7 +1015,7 @@ pub fn specialize_material_meshes(
}; };
view_specialized_material_pipeline_cache view_specialized_material_pipeline_cache
.insert(*visible_entity, (ticks.this_run(), pipeline_id)); .insert(*visible_entity, (params.ticks.this_run(), pipeline_id));
} }
} }

View File

@ -40,7 +40,6 @@ use bevy_math::{Affine3A, Vec4};
use bevy_render::{ use bevy_render::{
globals::{GlobalsBuffer, GlobalsUniform}, globals::{GlobalsBuffer, GlobalsUniform},
prelude::{Camera, Mesh}, prelude::{Camera, Mesh},
render_asset::RenderAssets,
render_phase::*, render_phase::*,
render_resource::*, render_resource::*,
renderer::{RenderDevice, RenderQueue}, renderer::{RenderDevice, RenderQueue},
@ -817,9 +816,8 @@ pub fn check_prepass_views_need_specialization(
} }
pub fn specialize_prepass_material_meshes( pub fn specialize_prepass_material_meshes(
render_meshes: Res<RenderAssets<RenderMesh>>, params: SpecializeMeshParams<EntitySpecializationTicks, RenderMeshInstances>,
render_materials: Res<ErasedRenderAssets<PreparedMaterial>>, render_materials: Res<ErasedRenderAssets<PreparedMaterial>>,
render_mesh_instances: Res<RenderMeshInstances>,
render_material_instances: Res<RenderMaterialInstances>, render_material_instances: Res<RenderMaterialInstances>,
render_lightmaps: Res<RenderLightmaps>, render_lightmaps: Res<RenderLightmaps>,
render_visibility_ranges: Res<RenderVisibilityRanges>, render_visibility_ranges: Res<RenderVisibilityRanges>,
@ -844,20 +842,14 @@ pub fn specialize_prepass_material_meshes(
), ),
( (
mut specialized_material_pipeline_cache, mut specialized_material_pipeline_cache,
ticks,
prepass_pipeline, prepass_pipeline,
mut pipelines, mut pipelines,
pipeline_cache,
view_specialization_ticks, view_specialization_ticks,
entity_specialization_ticks,
): ( ): (
ResMut<SpecializedPrepassMaterialPipelineCache>, ResMut<SpecializedPrepassMaterialPipelineCache>,
SystemChangeTick,
Res<PrepassPipeline>, Res<PrepassPipeline>,
ResMut<SpecializedMeshPipelines<PrepassPipelineSpecializer>>, ResMut<SpecializedMeshPipelines<PrepassPipelineSpecializer>>,
Res<PipelineCache>,
Res<ViewPrepassSpecializationTicks>, Res<ViewPrepassSpecializationTicks>,
Res<EntitySpecializationTicks>,
), ),
) { ) {
for (extracted_view, visible_entities, msaa, motion_vector_prepass, deferred_prepass) in &views for (extracted_view, visible_entities, msaa, motion_vector_prepass, deferred_prepass) in &views
@ -886,17 +878,22 @@ pub fn specialize_prepass_material_meshes(
else { else {
continue; 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 { else {
continue; 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 let last_specialized_tick = view_specialized_material_pipeline_cache
.get(visible_entity) .get(visible_entity)
.map(|(tick, _)| *tick); .map(|(tick, _)| *tick);
let needs_specialization = last_specialized_tick.is_none_or(|tick| { let needs_specialization = last_specialized_tick.is_none_or(|tick| {
view_tick.is_newer_than(tick, ticks.this_run()) view_tick.is_newer_than(tick, params.ticks.this_run())
|| entity_tick.is_newer_than(tick, ticks.this_run()) || entity_tick.is_newer_than(tick, params.ticks.this_run())
}); });
if !needs_specialization { if !needs_specialization {
continue; continue;
@ -909,7 +906,7 @@ pub fn specialize_prepass_material_meshes(
view_specialized_material_pipeline_cache.remove(visible_entity); view_specialized_material_pipeline_cache.remove(visible_entity);
continue; 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; continue;
}; };
@ -993,7 +990,7 @@ pub fn specialize_prepass_material_meshes(
properties: material.properties.clone(), properties: material.properties.clone(),
}; };
let pipeline_id = pipelines.specialize( let pipeline_id = pipelines.specialize(
&pipeline_cache, &params.pipeline_cache,
&prepass_pipeline_specializer, &prepass_pipeline_specializer,
erased_key, erased_key,
&mesh.layout, &mesh.layout,
@ -1007,7 +1004,7 @@ pub fn specialize_prepass_material_meshes(
}; };
view_specialized_material_pipeline_cache view_specialized_material_pipeline_cache
.insert(*visible_entity, (ticks.this_run(), pipeline_id)); .insert(*visible_entity, (params.ticks.this_run(), pipeline_id));
} }
} }
} }

View File

@ -34,9 +34,7 @@ use bevy_render::{
}; };
use bevy_render::{ use bevy_render::{
diagnostic::RecordDiagnostics, diagnostic::RecordDiagnostics,
mesh::RenderMesh,
primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace}, primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace},
render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::*, render_phase::*,
render_resource::*, render_resource::*,
@ -1686,16 +1684,14 @@ pub fn check_views_lights_need_specialization(
} }
pub fn specialize_shadows( pub fn specialize_shadows(
params: SpecializeMeshParams<EntitySpecializationTicks, RenderMeshInstances>,
prepass_pipeline: Res<PrepassPipeline>, prepass_pipeline: Res<PrepassPipeline>,
(render_meshes, render_mesh_instances, render_materials, render_material_instances): ( (render_materials, render_material_instances): (
Res<RenderAssets<RenderMesh>>,
Res<RenderMeshInstances>,
Res<ErasedRenderAssets<PreparedMaterial>>, Res<ErasedRenderAssets<PreparedMaterial>>,
Res<RenderMaterialInstances>, Res<RenderMaterialInstances>,
), ),
shadow_render_phases: Res<ViewBinnedRenderPhases<Shadow>>, shadow_render_phases: Res<ViewBinnedRenderPhases<Shadow>>,
mut pipelines: ResMut<SpecializedMeshPipelines<PrepassPipelineSpecializer>>, mut pipelines: ResMut<SpecializedMeshPipelines<PrepassPipelineSpecializer>>,
pipeline_cache: Res<PipelineCache>,
render_lightmaps: Res<RenderLightmaps>, render_lightmaps: Res<RenderLightmaps>,
view_lights: Query<(Entity, &ViewLightEntities), With<ExtractedView>>, view_lights: Query<(Entity, &ViewLightEntities), With<ExtractedView>>,
view_light_entities: Query<(&LightEntity, &ExtractedView)>, view_light_entities: Query<(&LightEntity, &ExtractedView)>,
@ -1708,8 +1704,6 @@ pub fn specialize_shadows(
light_key_cache: Res<LightKeyCache>, light_key_cache: Res<LightKeyCache>,
mut specialized_material_pipeline_cache: ResMut<SpecializedShadowMaterialPipelineCache>, mut specialized_material_pipeline_cache: ResMut<SpecializedShadowMaterialPipelineCache>,
light_specialization_ticks: Res<LightSpecializationTicks>, light_specialization_ticks: Res<LightSpecializationTicks>,
entity_specialization_ticks: Res<EntitySpecializationTicks>,
ticks: SystemChangeTick,
) { ) {
// Record the retained IDs of all shadow views so that we can expire old // Record the retained IDs of all shadow views so that we can expire old
// pipeline IDs. // pipeline IDs.
@ -1774,18 +1768,22 @@ pub fn specialize_shadows(
continue; continue;
}; };
let Some(mesh_instance) = let Some(mesh_instance) = params
render_mesh_instances.render_mesh_queue_data(visible_entity) .render_mesh_instances
.render_mesh_queue_data(visible_entity)
else { else {
continue; 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 let last_specialized_tick = view_specialized_material_pipeline_cache
.get(&visible_entity) .get(&visible_entity)
.map(|(tick, _)| *tick); .map(|(tick, _)| *tick);
let needs_specialization = last_specialized_tick.is_none_or(|tick| { let needs_specialization = last_specialized_tick.is_none_or(|tick| {
view_tick.is_newer_than(tick, ticks.this_run()) view_tick.is_newer_than(tick, params.ticks.this_run())
|| entity_tick.is_newer_than(tick, ticks.this_run()) || entity_tick.is_newer_than(tick, params.ticks.this_run())
}); });
if !needs_specialization { if !needs_specialization {
continue; continue;
@ -1803,7 +1801,7 @@ pub fn specialize_shadows(
{ {
continue; 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; continue;
}; };
@ -1840,7 +1838,7 @@ pub fn specialize_shadows(
properties: material.properties.clone(), properties: material.properties.clone(),
}; };
let pipeline_id = pipelines.specialize( let pipeline_id = pipelines.specialize(
&pipeline_cache, &params.pipeline_cache,
&material_pipeline_specializer, &material_pipeline_specializer,
erased_key, erased_key,
&mesh.layout, &mesh.layout,
@ -1854,7 +1852,7 @@ pub fn specialize_shadows(
}; };
view_specialized_material_pipeline_cache view_specialized_material_pipeline_cache
.insert(visible_entity, (ticks.this_run(), pipeline_id)); .insert(visible_entity, (params.ticks.this_run(), pipeline_id));
} }
} }
} }

View File

@ -730,20 +730,16 @@ pub fn check_wireframe_entities_needing_specialization(
} }
pub fn specialize_wireframes( pub fn specialize_wireframes(
render_meshes: Res<RenderAssets<RenderMesh>>, params: SpecializeMeshParams<WireframeEntitySpecializationTicks, RenderMeshInstances>,
render_mesh_instances: Res<RenderMeshInstances>,
render_wireframe_instances: Res<RenderWireframeInstances>, render_wireframe_instances: Res<RenderWireframeInstances>,
render_visibility_ranges: Res<RenderVisibilityRanges>, render_visibility_ranges: Res<RenderVisibilityRanges>,
wireframe_phases: Res<ViewBinnedRenderPhases<Wireframe3d>>, wireframe_phases: Res<ViewBinnedRenderPhases<Wireframe3d>>,
views: Query<(&ExtractedView, &RenderVisibleEntities)>, views: Query<(&ExtractedView, &RenderVisibleEntities)>,
view_key_cache: Res<ViewKeyCache>, view_key_cache: Res<ViewKeyCache>,
entity_specialization_ticks: Res<WireframeEntitySpecializationTicks>,
view_specialization_ticks: Res<ViewSpecializationTicks>, view_specialization_ticks: Res<ViewSpecializationTicks>,
mut specialized_material_pipeline_cache: ResMut<SpecializedWireframePipelineCache>, mut specialized_material_pipeline_cache: ResMut<SpecializedWireframePipelineCache>,
mut pipelines: ResMut<SpecializedMeshPipelines<Wireframe3dPipeline>>, mut pipelines: ResMut<SpecializedMeshPipelines<Wireframe3dPipeline>>,
pipeline: Res<Wireframe3dPipeline>, pipeline: Res<Wireframe3dPipeline>,
pipeline_cache: Res<PipelineCache>,
ticks: SystemChangeTick,
) { ) {
// Record the retained IDs of all views so that we can expire old // Record the retained IDs of all views so that we can expire old
// pipeline IDs. // pipeline IDs.
@ -771,22 +767,27 @@ pub fn specialize_wireframes(
if !render_wireframe_instances.contains_key(visible_entity) { if !render_wireframe_instances.contains_key(visible_entity) {
continue; 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 { else {
continue; 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 let last_specialized_tick = view_specialized_material_pipeline_cache
.get(visible_entity) .get(visible_entity)
.map(|(tick, _)| *tick); .map(|(tick, _)| *tick);
let needs_specialization = last_specialized_tick.is_none_or(|tick| { let needs_specialization = last_specialized_tick.is_none_or(|tick| {
view_tick.is_newer_than(tick, ticks.this_run()) view_tick.is_newer_than(tick, params.ticks.this_run())
|| entity_tick.is_newer_than(tick, ticks.this_run()) || entity_tick.is_newer_than(tick, params.ticks.this_run())
}); });
if !needs_specialization { if !needs_specialization {
continue; 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; continue;
}; };
@ -814,7 +815,7 @@ pub fn specialize_wireframes(
} }
let pipeline_id = let pipeline_id =
pipelines.specialize(&pipeline_cache, &pipeline, mesh_key, &mesh.layout); pipelines.specialize(&params.pipeline_cache, &pipeline, mesh_key, &mesh.layout);
let pipeline_id = match pipeline_id { let pipeline_id = match pipeline_id {
Ok(id) => id, Ok(id) => id,
Err(err) => { Err(err) => {
@ -824,7 +825,7 @@ pub fn specialize_wireframes(
}; };
view_specialized_material_pipeline_cache view_specialized_material_pipeline_cache
.insert(*visible_entity, (ticks.this_run(), pipeline_id)); .insert(*visible_entity, (params.ticks.this_run(), pipeline_id));
} }
} }

View File

@ -1,4 +1,6 @@
use crate::{ use crate::{
mesh::RenderMesh,
render_asset::RenderAssets,
render_resource::*, render_resource::*,
renderer::{RenderAdapter, RenderDevice}, renderer::{RenderAdapter, RenderDevice},
Extract, Extract,
@ -8,7 +10,7 @@ use bevy_asset::{AssetEvent, AssetId, Assets};
use bevy_ecs::{ use bevy_ecs::{
event::EventReader, event::EventReader,
resource::Resource, resource::Resource,
system::{Res, ResMut}, system::{Res, ResMut, SystemChangeTick, SystemParam},
}; };
use bevy_platform::collections::{hash_map::EntryRef, HashMap, HashSet}; use bevy_platform::collections::{hash_map::EntryRef, HashMap, HashSet};
use bevy_tasks::Task; 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<RenderMesh>>,
pub ticks: SystemChangeTick,
}
#[cfg(all( #[cfg(all(
not(target_arch = "wasm32"), not(target_arch = "wasm32"),
not(target_os = "macos"), not(target_os = "macos"),

View File

@ -24,7 +24,7 @@ use bevy_platform::collections::HashMap;
use bevy_reflect::{prelude::ReflectDefault, Reflect}; use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_render::camera::extract_cameras; use bevy_render::camera::extract_cameras;
use bevy_render::render_phase::{DrawFunctionId, InputUniformIndex}; 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::view::RenderVisibleEntities;
use bevy_render::RenderStartup; use bevy_render::RenderStartup;
use bevy_render::{ use bevy_render::{
@ -39,7 +39,7 @@ use bevy_render::{
}, },
render_resource::{ render_resource::{
AsBindGroup, AsBindGroupError, BindGroup, BindGroupId, BindGroupLayout, BindingResources, AsBindGroup, AsBindGroupError, BindGroup, BindGroupId, BindGroupLayout, BindingResources,
PipelineCache, RenderPipelineDescriptor, Shader, ShaderRef, SpecializedMeshPipeline, RenderPipelineDescriptor, Shader, ShaderRef, SpecializedMeshPipeline,
SpecializedMeshPipelineError, SpecializedMeshPipelines, SpecializedMeshPipelineError, SpecializedMeshPipelines,
}, },
renderer::RenderDevice, renderer::RenderDevice,
@ -675,23 +675,17 @@ pub fn check_entities_needing_specialization<M>(
} }
pub fn specialize_material2d_meshes<M: Material2d>( pub fn specialize_material2d_meshes<M: Material2d>(
params: SpecializeMeshParams<EntitySpecializationTicks<M>, RenderMesh2dInstances>,
material2d_pipeline: Res<Material2dPipeline<M>>, material2d_pipeline: Res<Material2dPipeline<M>>,
mut pipelines: ResMut<SpecializedMeshPipelines<Material2dPipeline<M>>>, mut pipelines: ResMut<SpecializedMeshPipelines<Material2dPipeline<M>>>,
pipeline_cache: Res<PipelineCache>, render_materials: Res<RenderAssets<PreparedMaterial2d<M>>>,
(render_meshes, render_materials): (
Res<RenderAssets<RenderMesh>>,
Res<RenderAssets<PreparedMaterial2d<M>>>,
),
mut render_mesh_instances: ResMut<RenderMesh2dInstances>,
render_material_instances: Res<RenderMaterial2dInstances<M>>, render_material_instances: Res<RenderMaterial2dInstances<M>>,
transparent_render_phases: Res<ViewSortedRenderPhases<Transparent2d>>, transparent_render_phases: Res<ViewSortedRenderPhases<Transparent2d>>,
opaque_render_phases: Res<ViewBinnedRenderPhases<Opaque2d>>, opaque_render_phases: Res<ViewBinnedRenderPhases<Opaque2d>>,
alpha_mask_render_phases: Res<ViewBinnedRenderPhases<AlphaMask2d>>, alpha_mask_render_phases: Res<ViewBinnedRenderPhases<AlphaMask2d>>,
views: Query<(&MainEntity, &ExtractedView, &RenderVisibleEntities)>, views: Query<(&MainEntity, &ExtractedView, &RenderVisibleEntities)>,
view_key_cache: Res<ViewKeyCache>, view_key_cache: Res<ViewKeyCache>,
entity_specialization_ticks: Res<EntitySpecializationTicks<M>>,
view_specialization_ticks: Res<ViewSpecializationTicks>, view_specialization_ticks: Res<ViewSpecializationTicks>,
ticks: SystemChangeTick,
mut specialized_material_pipeline_cache: ResMut<SpecializedMaterial2dPipelineCache<M>>, mut specialized_material_pipeline_cache: ResMut<SpecializedMaterial2dPipelineCache<M>>,
) where ) where
M::Data: PartialEq + Eq + Hash + Clone, M::Data: PartialEq + Eq + Hash + Clone,
@ -721,16 +715,19 @@ pub fn specialize_material2d_meshes<M: Material2d>(
let Some(material_asset_id) = render_material_instances.get(visible_entity) else { let Some(material_asset_id) = render_material_instances.get(visible_entity) else {
continue; 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; 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 let last_specialized_tick = view_specialized_material_pipeline_cache
.get(visible_entity) .get(visible_entity)
.map(|(tick, _)| *tick); .map(|(tick, _)| *tick);
let needs_specialization = last_specialized_tick.is_none_or(|tick| { let needs_specialization = last_specialized_tick.is_none_or(|tick| {
view_tick.is_newer_than(tick, ticks.this_run()) view_tick.is_newer_than(tick, params.ticks.this_run())
|| entity_tick.is_newer_than(tick, ticks.this_run()) || entity_tick.is_newer_than(tick, params.ticks.this_run())
}); });
if !needs_specialization { if !needs_specialization {
continue; continue;
@ -738,7 +735,7 @@ pub fn specialize_material2d_meshes<M: Material2d>(
let Some(material_2d) = render_materials.get(*material_asset_id) else { let Some(material_2d) = render_materials.get(*material_asset_id) else {
continue; 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; continue;
}; };
let mesh_key = *view_key let mesh_key = *view_key
@ -746,7 +743,7 @@ pub fn specialize_material2d_meshes<M: Material2d>(
| material_2d.properties.mesh_pipeline_key_bits; | material_2d.properties.mesh_pipeline_key_bits;
let pipeline_id = pipelines.specialize( let pipeline_id = pipelines.specialize(
&pipeline_cache, &params.pipeline_cache,
&material2d_pipeline, &material2d_pipeline,
Material2dKey { Material2dKey {
mesh_key, mesh_key,
@ -764,7 +761,7 @@ pub fn specialize_material2d_meshes<M: Material2d>(
}; };
view_specialized_material_pipeline_cache view_specialized_material_pipeline_cache
.insert(*visible_entity, (ticks.this_run(), pipeline_id)); .insert(*visible_entity, (params.ticks.this_run(), pipeline_id));
} }
} }
} }

View File

@ -723,19 +723,15 @@ pub fn check_wireframe_entities_needing_specialization(
} }
pub fn specialize_wireframes( pub fn specialize_wireframes(
render_meshes: Res<RenderAssets<RenderMesh>>, params: SpecializeMeshParams<WireframeEntitySpecializationTicks, RenderMesh2dInstances>,
render_mesh_instances: Res<RenderMesh2dInstances>,
render_wireframe_instances: Res<RenderWireframeInstances>, render_wireframe_instances: Res<RenderWireframeInstances>,
wireframe_phases: Res<ViewBinnedRenderPhases<Wireframe2dPhaseItem>>, wireframe_phases: Res<ViewBinnedRenderPhases<Wireframe2dPhaseItem>>,
views: Query<(&ExtractedView, &RenderVisibleEntities)>, views: Query<(&ExtractedView, &RenderVisibleEntities)>,
view_key_cache: Res<ViewKeyCache>, view_key_cache: Res<ViewKeyCache>,
entity_specialization_ticks: Res<WireframeEntitySpecializationTicks>,
view_specialization_ticks: Res<ViewSpecializationTicks>, view_specialization_ticks: Res<ViewSpecializationTicks>,
mut specialized_material_pipeline_cache: ResMut<SpecializedWireframePipelineCache>, mut specialized_material_pipeline_cache: ResMut<SpecializedWireframePipelineCache>,
mut pipelines: ResMut<SpecializedMeshPipelines<Wireframe2dPipeline>>, mut pipelines: ResMut<SpecializedMeshPipelines<Wireframe2dPipeline>>,
pipeline: Res<Wireframe2dPipeline>, pipeline: Res<Wireframe2dPipeline>,
pipeline_cache: Res<PipelineCache>,
ticks: SystemChangeTick,
) { ) {
// Record the retained IDs of all views so that we can expire old // Record the retained IDs of all views so that we can expire old
// pipeline IDs. // pipeline IDs.
@ -763,21 +759,24 @@ pub fn specialize_wireframes(
if !render_wireframe_instances.contains_key(visible_entity) { if !render_wireframe_instances.contains_key(visible_entity) {
continue; 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; 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 let last_specialized_tick = view_specialized_material_pipeline_cache
.get(visible_entity) .get(visible_entity)
.map(|(tick, _)| *tick); .map(|(tick, _)| *tick);
let needs_specialization = last_specialized_tick.is_none_or(|tick| { let needs_specialization = last_specialized_tick.is_none_or(|tick| {
view_tick.is_newer_than(tick, ticks.this_run()) view_tick.is_newer_than(tick, params.ticks.this_run())
|| entity_tick.is_newer_than(tick, ticks.this_run()) || entity_tick.is_newer_than(tick, params.ticks.this_run())
}); });
if !needs_specialization { if !needs_specialization {
continue; 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; continue;
}; };
@ -785,7 +784,7 @@ pub fn specialize_wireframes(
mesh_key |= Mesh2dPipelineKey::from_primitive_topology(mesh.primitive_topology()); mesh_key |= Mesh2dPipelineKey::from_primitive_topology(mesh.primitive_topology());
let pipeline_id = let pipeline_id =
pipelines.specialize(&pipeline_cache, &pipeline, mesh_key, &mesh.layout); pipelines.specialize(&params.pipeline_cache, &pipeline, mesh_key, &mesh.layout);
let pipeline_id = match pipeline_id { let pipeline_id = match pipeline_id {
Ok(id) => id, Ok(id) => id,
Err(err) => { Err(err) => {
@ -795,7 +794,7 @@ pub fn specialize_wireframes(
}; };
view_specialized_material_pipeline_cache view_specialized_material_pipeline_cache
.insert(*visible_entity, (ticks.this_run(), pipeline_id)); .insert(*visible_entity, (params.ticks.this_run(), pipeline_id));
} }
} }