diff --git a/crates/bevy_core_pipeline/src/blit/mod.rs b/crates/bevy_core_pipeline/src/blit/mod.rs index 69897d333d..398f91056b 100644 --- a/crates/bevy_core_pipeline/src/blit/mod.rs +++ b/crates/bevy_core_pipeline/src/blit/mod.rs @@ -1,6 +1,8 @@ +use core::{ops::Deref, result::Result}; + use crate::FullscreenShader; use bevy_app::{App, Plugin}; -use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer, Handle}; +use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer}; use bevy_ecs::prelude::*; use bevy_render::{ render_resource::{ @@ -24,8 +26,7 @@ impl Plugin for BlitPlugin { }; render_app - .allow_ambiguous_resource::>() - .init_resource::>() + .allow_ambiguous_resource::() .add_systems(RenderStartup, init_blit_pipeline); } } @@ -34,8 +35,7 @@ impl Plugin for BlitPlugin { pub struct BlitPipeline { pub layout: BindGroupLayout, pub sampler: Sampler, - pub fullscreen_shader: FullscreenShader, - pub fragment_shader: Handle, + pub specialized_cache: SpecializedCache, } pub fn init_blit_pipeline( @@ -57,11 +57,23 @@ pub fn init_blit_pipeline( let sampler = render_device.create_sampler(&SamplerDescriptor::default()); + let base_descriptor = RenderPipelineDescriptor { + label: Some("blit pipeline".into()), + layout: vec![layout.clone()], + vertex: fullscreen_shader.to_vertex_state(), + fragment: Some(FragmentState { + shader: load_embedded_asset!(asset_server.deref(), "blit.wgsl"), + ..default() + }), + ..default() + }; + + let specialized_cache = SpecializedCache::new(BlitSpecializer, base_descriptor); + commands.insert_resource(BlitPipeline { layout, sampler, - fullscreen_shader: fullscreen_shader.clone(), - fragment_shader: load_embedded_asset!(asset_server.as_ref(), "blit.wgsl"), + specialized_cache, }); } @@ -79,35 +91,34 @@ impl BlitPipeline { } } -#[derive(PartialEq, Eq, Hash, Clone, Copy)] -pub struct BlitPipelineKey { +pub struct BlitSpecializer; + +impl Specializer for BlitSpecializer { + type Key = BlitKey; + + fn specialize( + &self, + key: Self::Key, + descriptor: &mut ::Descriptor, + ) -> Result, BevyError> { + descriptor.multisample.count = key.samples; + + descriptor.fragment_mut()?.set_target( + 0, + ColorTargetState { + format: key.texture_format, + blend: key.blend_state, + write_mask: ColorWrites::ALL, + }, + ); + + Ok(key) + } +} + +#[derive(PartialEq, Eq, Hash, Clone, Copy, SpecializerKey)] +pub struct BlitKey { pub texture_format: TextureFormat, pub blend_state: Option, pub samples: u32, } - -impl SpecializedRenderPipeline for BlitPipeline { - type Key = BlitPipelineKey; - - fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - RenderPipelineDescriptor { - label: Some("blit pipeline".into()), - layout: vec![self.layout.clone()], - vertex: self.fullscreen_shader.to_vertex_state(), - fragment: Some(FragmentState { - shader: self.fragment_shader.clone(), - targets: vec![Some(ColorTargetState { - format: key.texture_format, - blend: key.blend_state, - write_mask: ColorWrites::ALL, - })], - ..default() - }), - multisample: MultisampleState { - count: key.samples, - ..default() - }, - ..default() - } - } -} diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index 151660876a..78e868bb62 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -1,5 +1,5 @@ use crate::{ - blit::{BlitPipeline, BlitPipelineKey}, + blit::{BlitKey, BlitPipeline}, core_2d::graph::{Core2d, Node2d}, core_3d::graph::{Core3d, Node3d}, }; @@ -119,22 +119,23 @@ pub struct MsaaWritebackBlitPipeline(CachedRenderPipelineId); fn prepare_msaa_writeback_pipelines( mut commands: Commands, pipeline_cache: Res, - mut pipelines: ResMut>, - blit_pipeline: Res, + mut blit_pipeline: ResMut, view_targets: Query<(Entity, &ViewTarget, &ExtractedCamera, &Msaa)>, -) { +) -> Result<(), BevyError> { for (entity, view_target, camera, msaa) in view_targets.iter() { // only do writeback if writeback is enabled for the camera and this isn't the first camera in the target, // as there is nothing to write back for the first camera. if msaa.samples() > 1 && camera.msaa_writeback && camera.sorted_camera_index_for_target > 0 { - let key = BlitPipelineKey { + let key = BlitKey { texture_format: view_target.main_texture_format(), samples: msaa.samples(), blend_state: None, }; - let pipeline = pipelines.specialize(&pipeline_cache, &blit_pipeline, key); + let pipeline = blit_pipeline + .specialized_cache + .specialize(&pipeline_cache, key)?; commands .entity(entity) .insert(MsaaWritebackBlitPipeline(pipeline)); @@ -146,4 +147,5 @@ fn prepare_msaa_writeback_pipelines( .remove::(); } } + Ok(()) } diff --git a/crates/bevy_core_pipeline/src/upscaling/mod.rs b/crates/bevy_core_pipeline/src/upscaling/mod.rs index 4ce91de393..b8dc18946d 100644 --- a/crates/bevy_core_pipeline/src/upscaling/mod.rs +++ b/crates/bevy_core_pipeline/src/upscaling/mod.rs @@ -1,4 +1,4 @@ -use crate::blit::{BlitPipeline, BlitPipelineKey}; +use crate::blit::{BlitKey, BlitPipeline}; use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_platform::collections::HashSet; @@ -39,10 +39,9 @@ pub struct ViewUpscalingPipeline(CachedRenderPipelineId); fn prepare_view_upscaling_pipelines( mut commands: Commands, mut pipeline_cache: ResMut, - mut pipelines: ResMut>, - blit_pipeline: Res, + mut blit_pipeline: ResMut, view_targets: Query<(Entity, &ViewTarget, Option<&ExtractedCamera>)>, -) { +) -> Result<(), BevyError> { let mut output_textures = >::default(); for (entity, view_target, camera) in view_targets.iter() { let out_texture_id = view_target.out_texture().id(); @@ -73,12 +72,14 @@ fn prepare_view_upscaling_pipelines( None }; - let key = BlitPipelineKey { + let key = BlitKey { texture_format: view_target.out_texture_format(), blend_state, samples: 1, }; - let pipeline = pipelines.specialize(&pipeline_cache, &blit_pipeline, key); + let pipeline = blit_pipeline + .specialized_cache + .specialize(&pipeline_cache, key)?; // Ensure the pipeline is loaded before continuing the frame to prevent frames without any GPU work submitted pipeline_cache.block_on_render_pipeline(pipeline); @@ -87,4 +88,6 @@ fn prepare_view_upscaling_pipelines( .entity(entity) .insert(ViewUpscalingPipeline(pipeline)); } + + Ok(()) }