Use RenderStartup in bevy_anti_aliasing. (#19897)

# Objective

- Progress towards #19887.

## Solution

- Rewrite the FromWorld impls to systems that create the pipeline
resources.

## Testing

- Ran the `anti_aliasing` example and it still works.
This commit is contained in:
andriyDev 2025-07-02 15:38:44 -07:00 committed by GitHub
parent e70f84536a
commit 8098cf21ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 176 additions and 196 deletions

View File

@ -1,5 +1,5 @@
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{embedded_asset, load_embedded_asset, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer, Handle};
use bevy_core_pipeline::{ use bevy_core_pipeline::{
core_2d::graph::{Core2d, Node2d}, core_2d::graph::{Core2d, Node2d},
core_3d::graph::{Core3d, Node3d}, core_3d::graph::{Core3d, Node3d},
@ -18,7 +18,7 @@ use bevy_render::{
}, },
renderer::RenderDevice, renderer::RenderDevice,
view::{ExtractedView, ViewTarget}, view::{ExtractedView, ViewTarget},
Render, RenderApp, RenderSystems, Render, RenderApp, RenderStartup, RenderSystems,
}; };
use bevy_utils::default; use bevy_utils::default;
@ -114,6 +114,7 @@ impl Plugin for CasPlugin {
}; };
render_app render_app
.init_resource::<SpecializedRenderPipelines<CasPipeline>>() .init_resource::<SpecializedRenderPipelines<CasPipeline>>()
.add_systems(RenderStartup, init_cas_pipeline)
.add_systems(Render, prepare_cas_pipelines.in_set(RenderSystems::Prepare)); .add_systems(Render, prepare_cas_pipelines.in_set(RenderSystems::Prepare));
{ {
@ -151,13 +152,6 @@ impl Plugin for CasPlugin {
); );
} }
} }
fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app.init_resource::<CasPipeline>();
}
} }
#[derive(Resource)] #[derive(Resource)]
@ -168,34 +162,36 @@ pub struct CasPipeline {
fragment_shader: Handle<Shader>, fragment_shader: Handle<Shader>,
} }
impl FromWorld for CasPipeline { pub fn init_cas_pipeline(
fn from_world(render_world: &mut World) -> Self { mut commands: Commands,
let render_device = render_world.resource::<RenderDevice>(); render_device: Res<RenderDevice>,
let texture_bind_group = render_device.create_bind_group_layout( fullscreen_shader: Res<FullscreenShader>,
"sharpening_texture_bind_group_layout", asset_server: Res<AssetServer>,
&BindGroupLayoutEntries::sequential( ) {
ShaderStages::FRAGMENT, let texture_bind_group = render_device.create_bind_group_layout(
( "sharpening_texture_bind_group_layout",
texture_2d(TextureSampleType::Float { filterable: true }), &BindGroupLayoutEntries::sequential(
sampler(SamplerBindingType::Filtering), ShaderStages::FRAGMENT,
// CAS Settings (
uniform_buffer::<CasUniform>(true), texture_2d(TextureSampleType::Float { filterable: true }),
), sampler(SamplerBindingType::Filtering),
// CAS Settings
uniform_buffer::<CasUniform>(true),
), ),
); ),
);
let sampler = render_device.create_sampler(&SamplerDescriptor::default()); let sampler = render_device.create_sampler(&SamplerDescriptor::default());
CasPipeline { commands.insert_resource(CasPipeline {
texture_bind_group, texture_bind_group,
sampler, sampler,
fullscreen_shader: render_world.resource::<FullscreenShader>().clone(), fullscreen_shader: fullscreen_shader.clone(),
fragment_shader: load_embedded_asset!( fragment_shader: load_embedded_asset!(
render_world, asset_server.as_ref(),
"robust_contrast_adaptive_sharpening.wgsl" "robust_contrast_adaptive_sharpening.wgsl"
), ),
} });
}
} }
#[derive(PartialEq, Eq, Hash, Clone, Copy)] #[derive(PartialEq, Eq, Hash, Clone, Copy)]

View File

@ -1,5 +1,5 @@
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{embedded_asset, load_embedded_asset, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer, Handle};
use bevy_core_pipeline::{ use bevy_core_pipeline::{
core_2d::graph::{Core2d, Node2d}, core_2d::graph::{Core2d, Node2d},
core_3d::graph::{Core3d, Node3d}, core_3d::graph::{Core3d, Node3d},
@ -18,7 +18,7 @@ use bevy_render::{
}, },
renderer::RenderDevice, renderer::RenderDevice,
view::{ExtractedView, ViewTarget}, view::{ExtractedView, ViewTarget},
Render, RenderApp, RenderSystems, Render, RenderApp, RenderStartup, RenderSystems,
}; };
use bevy_utils::default; use bevy_utils::default;
@ -94,6 +94,7 @@ impl Plugin for FxaaPlugin {
}; };
render_app render_app
.init_resource::<SpecializedRenderPipelines<FxaaPipeline>>() .init_resource::<SpecializedRenderPipelines<FxaaPipeline>>()
.add_systems(RenderStartup, init_fxaa_pipeline)
.add_systems( .add_systems(
Render, Render,
prepare_fxaa_pipelines.in_set(RenderSystems::Prepare), prepare_fxaa_pipelines.in_set(RenderSystems::Prepare),
@ -117,13 +118,6 @@ impl Plugin for FxaaPlugin {
), ),
); );
} }
fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app.init_resource::<FxaaPipeline>();
}
} }
#[derive(Resource)] #[derive(Resource)]
@ -134,34 +128,36 @@ pub struct FxaaPipeline {
fragment_shader: Handle<Shader>, fragment_shader: Handle<Shader>,
} }
impl FromWorld for FxaaPipeline { pub fn init_fxaa_pipeline(
fn from_world(render_world: &mut World) -> Self { mut commands: Commands,
let render_device = render_world.resource::<RenderDevice>(); render_device: Res<RenderDevice>,
let texture_bind_group = render_device.create_bind_group_layout( fullscreen_shader: Res<FullscreenShader>,
"fxaa_texture_bind_group_layout", asset_server: Res<AssetServer>,
&BindGroupLayoutEntries::sequential( ) {
ShaderStages::FRAGMENT, let texture_bind_group = render_device.create_bind_group_layout(
( "fxaa_texture_bind_group_layout",
texture_2d(TextureSampleType::Float { filterable: true }), &BindGroupLayoutEntries::sequential(
sampler(SamplerBindingType::Filtering), ShaderStages::FRAGMENT,
), (
texture_2d(TextureSampleType::Float { filterable: true }),
sampler(SamplerBindingType::Filtering),
), ),
); ),
);
let sampler = render_device.create_sampler(&SamplerDescriptor { let sampler = render_device.create_sampler(&SamplerDescriptor {
mipmap_filter: FilterMode::Linear, mipmap_filter: FilterMode::Linear,
mag_filter: FilterMode::Linear, mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear, min_filter: FilterMode::Linear,
..default() ..default()
}); });
FxaaPipeline { commands.insert_resource(FxaaPipeline {
texture_bind_group, texture_bind_group,
sampler, sampler,
fullscreen_shader: render_world.resource::<FullscreenShader>().clone(), fullscreen_shader: fullscreen_shader.clone(),
fragment_shader: load_embedded_asset!(render_world, "fxaa.wgsl"), fragment_shader: load_embedded_asset!(asset_server.as_ref(), "fxaa.wgsl"),
} });
}
} }
#[derive(Component)] #[derive(Component)]

View File

@ -32,7 +32,7 @@
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
#[cfg(feature = "smaa_luts")] #[cfg(feature = "smaa_luts")]
use bevy_asset::load_internal_binary_asset; use bevy_asset::load_internal_binary_asset;
use bevy_asset::{embedded_asset, load_embedded_asset, uuid_handle, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, uuid_handle, AssetServer, Handle};
#[cfg(not(feature = "smaa_luts"))] #[cfg(not(feature = "smaa_luts"))]
use bevy_core_pipeline::tonemapping::lut_placeholder; use bevy_core_pipeline::tonemapping::lut_placeholder;
use bevy_core_pipeline::{ use bevy_core_pipeline::{
@ -48,7 +48,7 @@ use bevy_ecs::{
resource::Resource, resource::Resource,
schedule::IntoScheduleConfigs as _, schedule::IntoScheduleConfigs as _,
system::{lifetimeless::Read, Commands, Query, Res, ResMut}, system::{lifetimeless::Read, Commands, Query, Res, ResMut},
world::{FromWorld, World}, world::World,
}; };
use bevy_image::{BevyDefault, Image, ToExtents}; use bevy_image::{BevyDefault, Image, ToExtents};
use bevy_math::{vec4, Vec4}; use bevy_math::{vec4, Vec4};
@ -75,7 +75,7 @@ use bevy_render::{
renderer::{RenderContext, RenderDevice, RenderQueue}, renderer::{RenderContext, RenderDevice, RenderQueue},
texture::{CachedTexture, GpuImage, TextureCache}, texture::{CachedTexture, GpuImage, TextureCache},
view::{ExtractedView, ViewTarget}, view::{ExtractedView, ViewTarget},
Render, RenderApp, RenderSystems, Render, RenderApp, RenderStartup, RenderSystems,
}; };
use bevy_utils::prelude::default; use bevy_utils::prelude::default;
@ -346,6 +346,7 @@ impl Plugin for SmaaPlugin {
render_app render_app
.init_resource::<SmaaSpecializedRenderPipelines>() .init_resource::<SmaaSpecializedRenderPipelines>()
.init_resource::<SmaaInfoUniformBuffer>() .init_resource::<SmaaInfoUniformBuffer>()
.add_systems(RenderStartup, init_smaa_pipelines)
.add_systems( .add_systems(
Render, Render,
( (
@ -374,86 +375,79 @@ impl Plugin for SmaaPlugin {
), ),
); );
} }
fn finish(&self, app: &mut App) {
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app.init_resource::<SmaaPipelines>();
}
}
} }
impl FromWorld for SmaaPipelines { pub fn init_smaa_pipelines(
fn from_world(world: &mut World) -> Self { mut commands: Commands,
let render_device = world.resource::<RenderDevice>(); render_device: Res<RenderDevice>,
asset_server: Res<AssetServer>,
// Create the postprocess bind group layout (all passes, bind group 0). ) {
let postprocess_bind_group_layout = render_device.create_bind_group_layout( // Create the postprocess bind group layout (all passes, bind group 0).
"SMAA postprocess bind group layout", let postprocess_bind_group_layout = render_device.create_bind_group_layout(
&BindGroupLayoutEntries::sequential( "SMAA postprocess bind group layout",
ShaderStages::FRAGMENT, &BindGroupLayoutEntries::sequential(
( ShaderStages::FRAGMENT,
texture_2d(TextureSampleType::Float { filterable: true }), (
uniform_buffer::<SmaaInfoUniform>(true) texture_2d(TextureSampleType::Float { filterable: true }),
.visibility(ShaderStages::VERTEX_FRAGMENT), uniform_buffer::<SmaaInfoUniform>(true).visibility(ShaderStages::VERTEX_FRAGMENT),
),
), ),
); ),
);
// Create the edge detection bind group layout (pass 1, bind group 1). // Create the edge detection bind group layout (pass 1, bind group 1).
let edge_detection_bind_group_layout = render_device.create_bind_group_layout( let edge_detection_bind_group_layout = render_device.create_bind_group_layout(
"SMAA edge detection bind group layout", "SMAA edge detection bind group layout",
&BindGroupLayoutEntries::sequential( &BindGroupLayoutEntries::sequential(
ShaderStages::FRAGMENT, ShaderStages::FRAGMENT,
(sampler(SamplerBindingType::Filtering),), (sampler(SamplerBindingType::Filtering),),
),
);
// Create the blending weight calculation bind group layout (pass 2, bind group 1).
let blending_weight_calculation_bind_group_layout = render_device.create_bind_group_layout(
"SMAA blending weight calculation bind group layout",
&BindGroupLayoutEntries::sequential(
ShaderStages::FRAGMENT,
(
texture_2d(TextureSampleType::Float { filterable: true }), // edges texture
sampler(SamplerBindingType::Filtering), // edges sampler
texture_2d(TextureSampleType::Float { filterable: true }), // search texture
texture_2d(TextureSampleType::Float { filterable: true }), // area texture
), ),
); ),
);
// Create the blending weight calculation bind group layout (pass 2, bind group 1). // Create the neighborhood blending bind group layout (pass 3, bind group 1).
let blending_weight_calculation_bind_group_layout = render_device.create_bind_group_layout( let neighborhood_blending_bind_group_layout = render_device.create_bind_group_layout(
"SMAA blending weight calculation bind group layout", "SMAA neighborhood blending bind group layout",
&BindGroupLayoutEntries::sequential( &BindGroupLayoutEntries::sequential(
ShaderStages::FRAGMENT, ShaderStages::FRAGMENT,
( (
texture_2d(TextureSampleType::Float { filterable: true }), // edges texture texture_2d(TextureSampleType::Float { filterable: true }),
sampler(SamplerBindingType::Filtering), // edges sampler sampler(SamplerBindingType::Filtering),
texture_2d(TextureSampleType::Float { filterable: true }), // search texture
texture_2d(TextureSampleType::Float { filterable: true }), // area texture
),
), ),
); ),
);
// Create the neighborhood blending bind group layout (pass 3, bind group 1). let shader = load_embedded_asset!(asset_server.as_ref(), "smaa.wgsl");
let neighborhood_blending_bind_group_layout = render_device.create_bind_group_layout(
"SMAA neighborhood blending bind group layout",
&BindGroupLayoutEntries::sequential(
ShaderStages::FRAGMENT,
(
texture_2d(TextureSampleType::Float { filterable: true }),
sampler(SamplerBindingType::Filtering),
),
),
);
let shader = load_embedded_asset!(world, "smaa.wgsl"); commands.insert_resource(SmaaPipelines {
edge_detection: SmaaEdgeDetectionPipeline {
SmaaPipelines { postprocess_bind_group_layout: postprocess_bind_group_layout.clone(),
edge_detection: SmaaEdgeDetectionPipeline { edge_detection_bind_group_layout,
postprocess_bind_group_layout: postprocess_bind_group_layout.clone(), shader: shader.clone(),
edge_detection_bind_group_layout, },
shader: shader.clone(), blending_weight_calculation: SmaaBlendingWeightCalculationPipeline {
}, postprocess_bind_group_layout: postprocess_bind_group_layout.clone(),
blending_weight_calculation: SmaaBlendingWeightCalculationPipeline { blending_weight_calculation_bind_group_layout,
postprocess_bind_group_layout: postprocess_bind_group_layout.clone(), shader: shader.clone(),
blending_weight_calculation_bind_group_layout, },
shader: shader.clone(), neighborhood_blending: SmaaNeighborhoodBlendingPipeline {
}, postprocess_bind_group_layout,
neighborhood_blending: SmaaNeighborhoodBlendingPipeline { neighborhood_blending_bind_group_layout,
postprocess_bind_group_layout, shader,
neighborhood_blending_bind_group_layout, },
shader, });
},
}
}
} }
// Phase 1: edge detection. // Phase 1: edge detection.

View File

@ -1,5 +1,5 @@
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{embedded_asset, load_embedded_asset, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer, Handle};
use bevy_core_pipeline::{ use bevy_core_pipeline::{
core_3d::graph::{Core3d, Node3d}, core_3d::graph::{Core3d, Node3d},
prelude::Camera3d, prelude::Camera3d,
@ -13,7 +13,7 @@ use bevy_ecs::{
resource::Resource, resource::Resource,
schedule::IntoScheduleConfigs, schedule::IntoScheduleConfigs,
system::{Commands, Query, Res, ResMut}, system::{Commands, Query, Res, ResMut},
world::{FromWorld, World}, world::World,
}; };
use bevy_image::{BevyDefault as _, ToExtents}; use bevy_image::{BevyDefault as _, ToExtents};
use bevy_math::vec2; use bevy_math::vec2;
@ -36,7 +36,7 @@ use bevy_render::{
sync_world::RenderEntity, sync_world::RenderEntity,
texture::{CachedTexture, TextureCache}, texture::{CachedTexture, TextureCache},
view::{ExtractedView, Msaa, ViewTarget}, view::{ExtractedView, Msaa, ViewTarget},
ExtractSchedule, MainWorld, Render, RenderApp, RenderSystems, ExtractSchedule, MainWorld, Render, RenderApp, RenderStartup, RenderSystems,
}; };
use bevy_utils::default; use bevy_utils::default;
use tracing::warn; use tracing::warn;
@ -59,6 +59,7 @@ impl Plugin for TemporalAntiAliasPlugin {
}; };
render_app render_app
.init_resource::<SpecializedRenderPipelines<TaaPipeline>>() .init_resource::<SpecializedRenderPipelines<TaaPipeline>>()
.add_systems(RenderStartup, init_taa_pipeline)
.add_systems(ExtractSchedule, extract_taa_settings) .add_systems(ExtractSchedule, extract_taa_settings)
.add_systems( .add_systems(
Render, Render,
@ -80,14 +81,6 @@ impl Plugin for TemporalAntiAliasPlugin {
), ),
); );
} }
fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app.init_resource::<TaaPipeline>();
}
} }
/// Component to apply temporal anti-aliasing to a 3D perspective camera. /// Component to apply temporal anti-aliasing to a 3D perspective camera.
@ -243,52 +236,53 @@ struct TaaPipeline {
fragment_shader: Handle<Shader>, fragment_shader: Handle<Shader>,
} }
impl FromWorld for TaaPipeline { fn init_taa_pipeline(
fn from_world(world: &mut World) -> Self { mut commands: Commands,
let render_device = world.resource::<RenderDevice>(); render_device: Res<RenderDevice>,
fullscreen_shader: Res<FullscreenShader>,
asset_server: Res<AssetServer>,
) {
let nearest_sampler = render_device.create_sampler(&SamplerDescriptor {
label: Some("taa_nearest_sampler"),
mag_filter: FilterMode::Nearest,
min_filter: FilterMode::Nearest,
..SamplerDescriptor::default()
});
let linear_sampler = render_device.create_sampler(&SamplerDescriptor {
label: Some("taa_linear_sampler"),
mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear,
..SamplerDescriptor::default()
});
let nearest_sampler = render_device.create_sampler(&SamplerDescriptor { let taa_bind_group_layout = render_device.create_bind_group_layout(
label: Some("taa_nearest_sampler"), "taa_bind_group_layout",
mag_filter: FilterMode::Nearest, &BindGroupLayoutEntries::sequential(
min_filter: FilterMode::Nearest, ShaderStages::FRAGMENT,
..SamplerDescriptor::default() (
}); // View target (read)
let linear_sampler = render_device.create_sampler(&SamplerDescriptor { texture_2d(TextureSampleType::Float { filterable: true }),
label: Some("taa_linear_sampler"), // TAA History (read)
mag_filter: FilterMode::Linear, texture_2d(TextureSampleType::Float { filterable: true }),
min_filter: FilterMode::Linear, // Motion Vectors
..SamplerDescriptor::default() texture_2d(TextureSampleType::Float { filterable: true }),
}); // Depth
texture_depth_2d(),
let taa_bind_group_layout = render_device.create_bind_group_layout( // Nearest sampler
"taa_bind_group_layout", sampler(SamplerBindingType::NonFiltering),
&BindGroupLayoutEntries::sequential( // Linear sampler
ShaderStages::FRAGMENT, sampler(SamplerBindingType::Filtering),
(
// View target (read)
texture_2d(TextureSampleType::Float { filterable: true }),
// TAA History (read)
texture_2d(TextureSampleType::Float { filterable: true }),
// Motion Vectors
texture_2d(TextureSampleType::Float { filterable: true }),
// Depth
texture_depth_2d(),
// Nearest sampler
sampler(SamplerBindingType::NonFiltering),
// Linear sampler
sampler(SamplerBindingType::Filtering),
),
), ),
); ),
);
TaaPipeline { commands.insert_resource(TaaPipeline {
taa_bind_group_layout, taa_bind_group_layout,
nearest_sampler, nearest_sampler,
linear_sampler, linear_sampler,
fullscreen_shader: world.resource::<FullscreenShader>().clone(), fullscreen_shader: fullscreen_shader.clone(),
fragment_shader: load_embedded_asset!(world, "taa.wgsl"), fragment_shader: load_embedded_asset!(asset_server.as_ref(), "taa.wgsl"),
} });
}
} }
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]