diff --git a/crates/bevy_gizmos_render/src/lib.rs b/crates/bevy_gizmos_render/src/lib.rs index c69977e115828..321e2d5849de9 100755 --- a/crates/bevy_gizmos_render/src/lib.rs +++ b/crates/bevy_gizmos_render/src/lib.rs @@ -30,6 +30,7 @@ use bevy_ecs::{ schedule::{IntoScheduleConfigs, SystemSet}, system::Res, }; +use bevy_pbr::MeshPipelineSet; use {bevy_gizmos::config::GizmoMeshConfig, bevy_mesh::VertexBufferLayout}; @@ -88,7 +89,10 @@ impl Plugin for GizmoRenderPlugin { .add_plugins(RenderAssetPlugin::::default()); if let Some(render_app) = app.get_sub_app_mut(RenderApp) { - render_app.add_systems(RenderStartup, init_line_gizmo_uniform_bind_group_layout); + render_app.add_systems( + RenderStartup, + init_line_gizmo_uniform_bind_group_layout.after(MeshPipelineSet), + ); render_app.add_systems( Render, diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index 41766372d9f36..f01ce90e21df2 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -5,7 +5,7 @@ use crate::{ TONEMAPPING_LUT_SAMPLER_BINDING_INDEX, TONEMAPPING_LUT_TEXTURE_BINDING_INDEX, }; use crate::{ - DistanceFog, ExtractedAtmosphere, MeshPipelineKey, ViewFogUniformOffset, + DistanceFog, ExtractedAtmosphere, MeshPipelineKey, MeshPipelineSet, ViewFogUniformOffset, ViewLightsUniformOffset, }; use bevy_app::prelude::*; @@ -109,7 +109,10 @@ impl Plugin for DeferredPbrLightingPlugin { render_app .init_resource::>() - .add_systems(RenderStartup, init_deferred_lighting_layout) + .add_systems( + RenderStartup, + init_deferred_lighting_layout.after(MeshPipelineSet), + ) .add_systems( Render, (prepare_deferred_lighting_pipelines.in_set(RenderSystems::Prepare),), diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 42717b57c40fe..3e4f7d77ca361 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -297,7 +297,7 @@ impl Plugin for MaterialsPlugin { .add_render_command::() .add_render_command::() .add_render_command::() - .add_systems(RenderStartup, init_material_pipeline) + .add_systems(RenderStartup, init_material_pipeline.after(MeshPipelineSet)) .add_systems( Render, ( diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 3e3842a23faf5..18bc4e8688531 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -3,7 +3,7 @@ use crate::{ resources::write_atmosphere_buffer, skin::skin_uniforms_from_world, }; -use bevy_asset::{embedded_asset, load_embedded_asset, AssetId}; +use bevy_asset::{embedded_asset, load_embedded_asset, AssetId, AssetServer}; use bevy_camera::{ primitives::Aabb, visibility::{NoFrustumCulling, RenderLayers, ViewVisibility, VisibilityRange}, @@ -22,7 +22,7 @@ use bevy_ecs::{ prelude::*, query::{QueryData, ROQueryItem}, relationship::RelationshipSourceCollection, - system::{lifetimeless::*, SystemParamItem, SystemState}, + system::{lifetimeless::*, SystemParamItem}, }; use bevy_image::{BevyDefault, ImageSampler, TextureFormatPixelInfo}; use bevy_light::{ @@ -127,6 +127,9 @@ impl MeshRenderPlugin { #[cfg(debug_assertions)] pub const MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES: usize = 10; +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +pub struct MeshPipelineSet; + impl Plugin for MeshRenderPlugin { fn build(&self, app: &mut App) { load_shader_library!(app, "forward_io.wgsl"); @@ -287,9 +290,12 @@ impl Plugin for MeshRenderPlugin { )); } - render_app - .init_resource::() - .init_resource::(); + render_app.add_systems( + RenderStartup, + (init_mesh_pipeline_view_layouts, init_mesh_pipeline) + .chain() + .in_set(MeshPipelineSet), + ); } // Load the mesh_bindings shader module here as it depends on runtime information about @@ -1881,35 +1887,35 @@ pub struct MeshPipeline { pub skins_use_uniform_buffers: bool, } -impl FromWorld for MeshPipeline { - fn from_world(world: &mut World) -> Self { - let shader = load_embedded_asset!(world, "mesh.wgsl"); - let mut system_state: SystemState<( - Res, - Res, - Res, - )> = SystemState::new(world); - let (render_device, render_adapter, view_layouts) = system_state.get_mut(world); - - let clustered_forward_buffer_binding_type = render_device - .get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT); - - MeshPipeline { - view_layouts: view_layouts.clone(), - clustered_forward_buffer_binding_type, - mesh_layouts: MeshLayouts::new(&render_device, &render_adapter), - shader, - per_object_buffer_batch_size: GpuArrayBuffer::::batch_size( - &render_device.limits(), - ), - binding_arrays_are_usable: binding_arrays_are_usable(&render_device, &render_adapter), - clustered_decals_are_usable: decal::clustered::clustered_decals_are_usable( - &render_device, - &render_adapter, - ), - skins_use_uniform_buffers: skins_use_uniform_buffers(&render_device.limits()), - } - } +fn init_mesh_pipeline( + mut commands: Commands, + render_device: Res, + render_adapter: Res, + view_layouts: Res, + asset_server: Res, +) { + let shader = load_embedded_asset!(asset_server.as_ref(), "mesh.wgsl"); + + let clustered_forward_buffer_binding_type = + render_device.get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT); + + let res = MeshPipeline { + view_layouts: view_layouts.clone(), + clustered_forward_buffer_binding_type, + mesh_layouts: MeshLayouts::new(&render_device, &render_adapter), + shader, + per_object_buffer_batch_size: GpuArrayBuffer::::batch_size( + &render_device.limits(), + ), + binding_arrays_are_usable: binding_arrays_are_usable(&render_device, &render_adapter), + clustered_decals_are_usable: decal::clustered::clustered_decals_are_usable( + &render_device, + &render_adapter, + ), + skins_use_uniform_buffers: skins_use_uniform_buffers(&render_device.limits()), + }; + + commands.insert_resource(res); } impl MeshPipeline { diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.rs b/crates/bevy_pbr/src/render/mesh_view_bindings.rs index 78e7f3e6d7dcb..dfedc629af234 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.rs @@ -14,7 +14,6 @@ use bevy_ecs::{ query::Has, resource::Resource, system::{Commands, Query, Res}, - world::{FromWorld, World}, }; use bevy_image::BevyDefault as _; use bevy_light::{EnvironmentMapLight, IrradianceVolume}; @@ -450,49 +449,50 @@ pub struct MeshPipelineViewLayouts( pub Arc<[MeshPipelineViewLayout; MeshPipelineViewLayoutKey::COUNT]>, ); -impl FromWorld for MeshPipelineViewLayouts { - fn from_world(world: &mut World) -> Self { - // Generates all possible view layouts for the mesh pipeline, based on all combinations of - // [`MeshPipelineViewLayoutKey`] flags. - - let render_device = world.resource::(); - let render_adapter = world.resource::(); - - let clustered_forward_buffer_binding_type = render_device - .get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT); - let visibility_ranges_buffer_binding_type = render_device - .get_supported_read_only_binding_type(VISIBILITY_RANGES_STORAGE_BUFFER_COUNT); - - Self(Arc::new(array::from_fn(|i| { - let key = MeshPipelineViewLayoutKey::from_bits_truncate(i as u32); - let entries = layout_entries( - clustered_forward_buffer_binding_type, - visibility_ranges_buffer_binding_type, - key, - render_device, - render_adapter, - ); +pub fn init_mesh_pipeline_view_layouts( + mut commands: Commands, + render_device: Res, + render_adapter: Res, +) { + // Generates all possible view layouts for the mesh pipeline, based on all combinations of + // [`MeshPipelineViewLayoutKey`] flags. + + let clustered_forward_buffer_binding_type = + render_device.get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT); + let visibility_ranges_buffer_binding_type = + render_device.get_supported_read_only_binding_type(VISIBILITY_RANGES_STORAGE_BUFFER_COUNT); + + let res = MeshPipelineViewLayouts(Arc::new(array::from_fn(|i| { + let key = MeshPipelineViewLayoutKey::from_bits_truncate(i as u32); + let entries = layout_entries( + clustered_forward_buffer_binding_type, + visibility_ranges_buffer_binding_type, + key, + &render_device, + &render_adapter, + ); + #[cfg(debug_assertions)] + let texture_count: usize = entries + .iter() + .flat_map(|e| { + e.iter() + .filter(|entry| matches!(entry.ty, BindingType::Texture { .. })) + }) + .count(); + + MeshPipelineViewLayout { + main_layout: BindGroupLayoutDescriptor::new(key.label(), &entries[0]), + binding_array_layout: BindGroupLayoutDescriptor::new( + format!("{}_binding_array", key.label()), + &entries[1], + ), + empty_layout: BindGroupLayoutDescriptor::new(format!("{}_empty", key.label()), &[]), #[cfg(debug_assertions)] - let texture_count: usize = entries - .iter() - .flat_map(|e| { - e.iter() - .filter(|entry| matches!(entry.ty, BindingType::Texture { .. })) - }) - .count(); - - MeshPipelineViewLayout { - main_layout: BindGroupLayoutDescriptor::new(key.label(), &entries[0]), - binding_array_layout: BindGroupLayoutDescriptor::new( - format!("{}_binding_array", key.label()), - &entries[1], - ), - empty_layout: BindGroupLayoutDescriptor::new(format!("{}_empty", key.label()), &[]), - #[cfg(debug_assertions)] - texture_count, - } - }))) - } + texture_count, + } + }))); + + commands.insert_resource(res); } impl MeshPipelineViewLayouts { diff --git a/crates/bevy_pbr/src/ssr/mod.rs b/crates/bevy_pbr/src/ssr/mod.rs index 7bd9d02c529de..4be8b578d8651 100644 --- a/crates/bevy_pbr/src/ssr/mod.rs +++ b/crates/bevy_pbr/src/ssr/mod.rs @@ -47,8 +47,8 @@ use bevy_utils::{once, prelude::default}; use tracing::info; use crate::{ - binding_arrays_are_usable, graph::NodePbr, ExtractedAtmosphere, MeshPipelineViewLayoutKey, - MeshPipelineViewLayouts, MeshViewBindGroup, RenderViewLightProbes, + binding_arrays_are_usable, graph::NodePbr, ExtractedAtmosphere, MeshPipelineSet, + MeshPipelineViewLayoutKey, MeshPipelineViewLayouts, MeshViewBindGroup, RenderViewLightProbes, ViewEnvironmentMapUniformOffset, ViewFogUniformOffset, ViewLightProbesUniformOffset, ViewLightsUniformOffset, }; @@ -201,7 +201,8 @@ impl Plugin for ScreenSpaceReflectionsPlugin { ( init_screen_space_reflections_pipeline, add_screen_space_reflections_render_graph_edges, - ), + ) + .after(MeshPipelineSet), ) .add_systems(Render, prepare_ssr_pipelines.in_set(RenderSystems::Prepare)) .add_systems( diff --git a/crates/bevy_pbr/src/volumetric_fog/mod.rs b/crates/bevy_pbr/src/volumetric_fog/mod.rs index 57cbd7bb1722c..a59868552fe6e 100644 --- a/crates/bevy_pbr/src/volumetric_fog/mod.rs +++ b/crates/bevy_pbr/src/volumetric_fog/mod.rs @@ -50,7 +50,9 @@ use bevy_render::{ }; use render::{VolumetricFogNode, VolumetricFogPipeline, VolumetricFogUniformBuffer}; -use crate::{graph::NodePbr, volumetric_fog::render::init_volumetric_fog_pipeline}; +use crate::{ + graph::NodePbr, volumetric_fog::render::init_volumetric_fog_pipeline, MeshPipelineSet, +}; pub mod render; @@ -84,7 +86,10 @@ impl Plugin for VolumetricFogPlugin { }) .init_resource::>() .init_resource::() - .add_systems(RenderStartup, init_volumetric_fog_pipeline) + .add_systems( + RenderStartup, + init_volumetric_fog_pipeline.after(MeshPipelineSet), + ) .add_systems(ExtractSchedule, render::extract_volumetric_fog) .add_systems( Render,