@@ -6,9 +6,11 @@ use crate::{
66use bevy_app:: { App , Plugin } ;
77use bevy_color:: LinearRgba ;
88use bevy_ecs:: prelude:: * ;
9+ use bevy_ecs:: query:: QueryItem ;
10+ use bevy_render:: render_graph:: { ViewNode , ViewNodeRunner } ;
911use bevy_render:: {
1012 camera:: ExtractedCamera ,
11- render_graph:: { Node , NodeRunError , RenderGraphApp , RenderGraphContext } ,
13+ render_graph:: { NodeRunError , RenderGraphApp , RenderGraphContext } ,
1214 renderer:: RenderContext ,
1315 view:: { Msaa , ViewTarget } ,
1416 Render , RenderSet ,
@@ -30,90 +32,87 @@ impl Plugin for MsaaWritebackPlugin {
3032 ) ;
3133 {
3234 render_app
33- . add_render_graph_node :: < MsaaWritebackNode > ( Core2d , Node2d :: MsaaWriteback )
35+ . add_render_graph_node :: < ViewNodeRunner < MsaaWritebackNode > > (
36+ Core2d ,
37+ Node2d :: MsaaWriteback ,
38+ )
3439 . add_render_graph_edge ( Core2d , Node2d :: MsaaWriteback , Node2d :: StartMainPass ) ;
3540 }
3641 {
3742 render_app
38- . add_render_graph_node :: < MsaaWritebackNode > ( Core3d , Node3d :: MsaaWriteback )
43+ . add_render_graph_node :: < ViewNodeRunner < MsaaWritebackNode > > (
44+ Core3d ,
45+ Node3d :: MsaaWriteback ,
46+ )
3947 . add_render_graph_edge ( Core3d , Node3d :: MsaaWriteback , Node3d :: StartMainPass ) ;
4048 }
4149 }
4250}
4351
44- pub struct MsaaWritebackNode {
45- cameras : QueryState < ( & ' static ViewTarget , & ' static MsaaWritebackBlitPipeline ) > ,
46- }
52+ #[ derive( Default ) ]
53+ pub struct MsaaWritebackNode ;
4754
48- impl FromWorld for MsaaWritebackNode {
49- fn from_world ( world : & mut World ) -> Self {
50- Self {
51- cameras : world. query ( ) ,
52- }
53- }
54- }
55+ impl ViewNode for MsaaWritebackNode {
56+ type ViewQuery = (
57+ & ' static ViewTarget ,
58+ & ' static MsaaWritebackBlitPipeline ,
59+ & ' static Msaa ,
60+ ) ;
5561
56- impl Node for MsaaWritebackNode {
57- fn update ( & mut self , world : & mut World ) {
58- self . cameras . update_archetypes ( world) ;
59- }
60-
61- fn run (
62+ fn run < ' w > (
6263 & self ,
63- graph : & mut RenderGraphContext ,
64- render_context : & mut RenderContext ,
65- world : & World ,
64+ _graph : & mut RenderGraphContext ,
65+ render_context : & mut RenderContext < ' w > ,
66+ ( target, blit_pipeline_id, msaa) : QueryItem < ' w , Self :: ViewQuery > ,
67+ world : & ' w World ,
6668 ) -> Result < ( ) , NodeRunError > {
67- if * world . resource :: < Msaa > ( ) == Msaa :: Off {
69+ if * msaa == Msaa :: Off {
6870 return Ok ( ( ) ) ;
6971 }
7072
71- let view_entity = graph. view_entity ( ) ;
72- if let Ok ( ( target, blit_pipeline_id) ) = self . cameras . get_manual ( world, view_entity) {
73- let blit_pipeline = world. resource :: < BlitPipeline > ( ) ;
74- let pipeline_cache = world. resource :: < PipelineCache > ( ) ;
75- let Some ( pipeline) = pipeline_cache. get_render_pipeline ( blit_pipeline_id. 0 ) else {
76- return Ok ( ( ) ) ;
77- } ;
78-
79- // The current "main texture" needs to be bound as an input resource, and we need the "other"
80- // unused target to be the "resolve target" for the MSAA write. Therefore this is the same
81- // as a post process write!
82- let post_process = target. post_process_write ( ) ;
73+ let blit_pipeline = world. resource :: < BlitPipeline > ( ) ;
74+ let pipeline_cache = world. resource :: < PipelineCache > ( ) ;
75+ let Some ( pipeline) = pipeline_cache. get_render_pipeline ( blit_pipeline_id. 0 ) else {
76+ return Ok ( ( ) ) ;
77+ } ;
8378
84- let pass_descriptor = RenderPassDescriptor {
85- label : Some ( "msaa_writeback" ) ,
86- // The target's "resolve target" is the "destination" in post_process.
87- // We will indirectly write the results to the "destination" using
88- // the MSAA resolve step.
89- color_attachments : & [ Some ( RenderPassColorAttachment {
90- // If MSAA is enabled, then the sampled texture will always exist
91- view : target. sampled_main_texture_view ( ) . unwrap ( ) ,
92- resolve_target : Some ( post_process. destination ) ,
93- ops : Operations {
94- load : LoadOp :: Clear ( LinearRgba :: BLACK . into ( ) ) ,
95- store : StoreOp :: Store ,
96- } ,
97- } ) ] ,
98- depth_stencil_attachment : None ,
99- timestamp_writes : None ,
100- occlusion_query_set : None ,
101- } ;
79+ // The current "main texture" needs to be bound as an input resource, and we need the "other"
80+ // unused target to be the "resolve target" for the MSAA write. Therefore this is the same
81+ // as a post process write!
82+ let post_process = target. post_process_write ( ) ;
83+
84+ let pass_descriptor = RenderPassDescriptor {
85+ label : Some ( "msaa_writeback" ) ,
86+ // The target's "resolve target" is the "destination" in post_process.
87+ // We will indirectly write the results to the "destination" using
88+ // the MSAA resolve step.
89+ color_attachments : & [ Some ( RenderPassColorAttachment {
90+ // If MSAA is enabled, then the sampled texture will always exist
91+ view : target. sampled_main_texture_view ( ) . unwrap ( ) ,
92+ resolve_target : Some ( post_process. destination ) ,
93+ ops : Operations {
94+ load : LoadOp :: Clear ( LinearRgba :: BLACK . into ( ) ) ,
95+ store : StoreOp :: Store ,
96+ } ,
97+ } ) ] ,
98+ depth_stencil_attachment : None ,
99+ timestamp_writes : None ,
100+ occlusion_query_set : None ,
101+ } ;
102102
103- let bind_group = render_context. render_device ( ) . create_bind_group (
104- None ,
105- & blit_pipeline. texture_bind_group ,
106- & BindGroupEntries :: sequential ( ( post_process. source , & blit_pipeline. sampler ) ) ,
107- ) ;
103+ let bind_group = render_context. render_device ( ) . create_bind_group (
104+ None ,
105+ & blit_pipeline. texture_bind_group ,
106+ & BindGroupEntries :: sequential ( ( post_process. source , & blit_pipeline. sampler ) ) ,
107+ ) ;
108108
109- let mut render_pass = render_context
110- . command_encoder ( )
111- . begin_render_pass ( & pass_descriptor) ;
109+ let mut render_pass = render_context
110+ . command_encoder ( )
111+ . begin_render_pass ( & pass_descriptor) ;
112112
113- render_pass. set_pipeline ( pipeline) ;
114- render_pass. set_bind_group ( 0 , & bind_group, & [ ] ) ;
115- render_pass. draw ( 0 ..3 , 0 ..1 ) ;
116- }
113+ render_pass. set_pipeline ( pipeline) ;
114+ render_pass. set_bind_group ( 0 , & bind_group, & [ ] ) ;
115+ render_pass. draw ( 0 ..3 , 0 ..1 ) ;
117116
118117 Ok ( ( ) )
119118 }
@@ -127,10 +126,9 @@ fn prepare_msaa_writeback_pipelines(
127126 pipeline_cache : Res < PipelineCache > ,
128127 mut pipelines : ResMut < SpecializedRenderPipelines < BlitPipeline > > ,
129128 blit_pipeline : Res < BlitPipeline > ,
130- view_targets : Query < ( Entity , & ViewTarget , & ExtractedCamera ) > ,
131- msaa : Res < Msaa > ,
129+ view_targets : Query < ( Entity , & ViewTarget , & ExtractedCamera , & Msaa ) > ,
132130) {
133- for ( entity, view_target, camera) in view_targets. iter ( ) {
131+ for ( entity, view_target, camera, msaa ) in view_targets. iter ( ) {
134132 // only do writeback if writeback is enabled for the camera and this isn't the first camera in the target,
135133 // as there is nothing to write back for the first camera.
136134 if msaa. samples ( ) > 1 && camera. msaa_writeback && camera. sorted_camera_index_for_target > 0
0 commit comments