@@ -6,9 +6,11 @@ use crate::{
6
6
use bevy_app:: { App , Plugin } ;
7
7
use bevy_color:: LinearRgba ;
8
8
use bevy_ecs:: prelude:: * ;
9
+ use bevy_ecs:: query:: QueryItem ;
10
+ use bevy_render:: render_graph:: { ViewNode , ViewNodeRunner } ;
9
11
use bevy_render:: {
10
12
camera:: ExtractedCamera ,
11
- render_graph:: { Node , NodeRunError , RenderGraphApp , RenderGraphContext } ,
13
+ render_graph:: { NodeRunError , RenderGraphApp , RenderGraphContext } ,
12
14
renderer:: RenderContext ,
13
15
view:: { Msaa , ViewTarget } ,
14
16
Render , RenderSet ,
@@ -30,90 +32,87 @@ impl Plugin for MsaaWritebackPlugin {
30
32
) ;
31
33
{
32
34
render_app
33
- . add_render_graph_node :: < MsaaWritebackNode > ( Core2d , Node2d :: MsaaWriteback )
35
+ . add_render_graph_node :: < ViewNodeRunner < MsaaWritebackNode > > (
36
+ Core2d ,
37
+ Node2d :: MsaaWriteback ,
38
+ )
34
39
. add_render_graph_edge ( Core2d , Node2d :: MsaaWriteback , Node2d :: StartMainPass ) ;
35
40
}
36
41
{
37
42
render_app
38
- . add_render_graph_node :: < MsaaWritebackNode > ( Core3d , Node3d :: MsaaWriteback )
43
+ . add_render_graph_node :: < ViewNodeRunner < MsaaWritebackNode > > (
44
+ Core3d ,
45
+ Node3d :: MsaaWriteback ,
46
+ )
39
47
. add_render_graph_edge ( Core3d , Node3d :: MsaaWriteback , Node3d :: StartMainPass ) ;
40
48
}
41
49
}
42
50
}
43
51
44
- pub struct MsaaWritebackNode {
45
- cameras : QueryState < ( & ' static ViewTarget , & ' static MsaaWritebackBlitPipeline ) > ,
46
- }
52
+ #[ derive( Default ) ]
53
+ pub struct MsaaWritebackNode ;
47
54
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
+ ) ;
55
61
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 > (
62
63
& 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 ,
66
68
) -> Result < ( ) , NodeRunError > {
67
- if * world . resource :: < Msaa > ( ) == Msaa :: Off {
69
+ if * msaa == Msaa :: Off {
68
70
return Ok ( ( ) ) ;
69
71
}
70
72
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
+ } ;
83
78
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
+ } ;
102
102
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
+ ) ;
108
108
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) ;
112
112
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 ) ;
117
116
118
117
Ok ( ( ) )
119
118
}
@@ -127,10 +126,9 @@ fn prepare_msaa_writeback_pipelines(
127
126
pipeline_cache : Res < PipelineCache > ,
128
127
mut pipelines : ResMut < SpecializedRenderPipelines < BlitPipeline > > ,
129
128
blit_pipeline : Res < BlitPipeline > ,
130
- view_targets : Query < ( Entity , & ViewTarget , & ExtractedCamera ) > ,
131
- msaa : Res < Msaa > ,
129
+ view_targets : Query < ( Entity , & ViewTarget , & ExtractedCamera , & Msaa ) > ,
132
130
) {
133
- for ( entity, view_target, camera) in view_targets. iter ( ) {
131
+ for ( entity, view_target, camera, msaa ) in view_targets. iter ( ) {
134
132
// only do writeback if writeback is enabled for the camera and this isn't the first camera in the target,
135
133
// as there is nothing to write back for the first camera.
136
134
if msaa. samples ( ) > 1 && camera. msaa_writeback && camera. sorted_camera_index_for_target > 0
0 commit comments