Skip to content

Commit 70b0eac

Browse files
JMS55atlv24alice-i-cecile
authored
Keep track of when a texture is first cleared (#10325)
# Objective - Custom render passes, or future passes in the engine (such as #10164) need a better way to know and indicate to the core passes whether the view color/depth/prepass attachments have been cleared or not yet this frame, to know if they should clear it themselves or load it. ## Solution - For all render targets (depth textures, shadow textures, prepass textures, main textures) use an atomic bool to track whether or not each texture has been cleared this frame. Abstracted away in the new ColorAttachment and DepthAttachment wrappers. --- ## Changelog - Changed `ViewTarget::get_color_attachment()`, removed arguments. - Changed `ViewTarget::get_unsampled_color_attachment()`, removed arguments. - Removed `Camera3d::clear_color`. - Removed `Camera2d::clear_color`. - Added `Camera::clear_color`. - Added `ExtractedCamera::clear_color`. - Added `ColorAttachment` and `DepthAttachment` wrappers. - Moved `ClearColor` and `ClearColorConfig` from `bevy::core_pipeline::clear_color` to `bevy::render::camera`. - Core render passes now track when a texture is first bound as an attachment in order to decide whether to clear or load it. ## Migration Guide - Remove arguments to `ViewTarget::get_color_attachment()` and `ViewTarget::get_unsampled_color_attachment()`. - Configure clear color on `Camera` instead of on `Camera3d` and `Camera2d`. - Moved `ClearColor` and `ClearColorConfig` from `bevy::core_pipeline::clear_color` to `bevy::render::camera`. - `ViewDepthTexture` must now be created via the `new()` method --------- Co-authored-by: vero <[email protected]> Co-authored-by: Alice Cecile <[email protected]>
1 parent 3d3a065 commit 70b0eac

File tree

32 files changed

+374
-413
lines changed

32 files changed

+374
-413
lines changed

crates/bevy_core_pipeline/src/bloom/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,7 @@ impl ViewNode for BloomNode {
265265
let mut upsampling_final_pass =
266266
render_context.begin_tracked_render_pass(RenderPassDescriptor {
267267
label: Some("bloom_upsampling_final_pass"),
268-
color_attachments: &[Some(view_target.get_unsampled_color_attachment(
269-
Operations {
270-
load: LoadOp::Load,
271-
store: StoreOp::Store,
272-
},
273-
))],
268+
color_attachments: &[Some(view_target.get_unsampled_color_attachment())],
274269
depth_stencil_attachment: None,
275270
timestamp_writes: None,
276271
occlusion_query_set: None,

crates/bevy_core_pipeline/src/core_2d/camera_2d.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::{
2-
clear_color::ClearColorConfig,
3-
tonemapping::{DebandDither, Tonemapping},
4-
};
1+
use crate::tonemapping::{DebandDither, Tonemapping};
52
use bevy_ecs::prelude::*;
63
use bevy_reflect::Reflect;
74
use bevy_render::{
@@ -15,9 +12,7 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
1512
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
1613
#[extract_component_filter(With<Camera>)]
1714
#[reflect(Component)]
18-
pub struct Camera2d {
19-
pub clear_color: ClearColorConfig,
20-
}
15+
pub struct Camera2d;
2116

2217
#[derive(Bundle)]
2318
pub struct Camera2dBundle {
@@ -57,7 +52,7 @@ impl Default for Camera2dBundle {
5752
transform,
5853
global_transform: Default::default(),
5954
camera: Camera::default(),
60-
camera_2d: Camera2d::default(),
55+
camera_2d: Camera2d,
6156
tonemapping: Tonemapping::None,
6257
deband_dither: DebandDither::Disabled,
6358
}
@@ -95,7 +90,7 @@ impl Camera2dBundle {
9590
transform,
9691
global_transform: Default::default(),
9792
camera: Camera::default(),
98-
camera_2d: Camera2d::default(),
93+
camera_2d: Camera2d,
9994
tonemapping: Tonemapping::None,
10095
deband_dither: DebandDither::Disabled,
10196
}

crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
use crate::{
2-
clear_color::{ClearColor, ClearColorConfig},
3-
core_2d::{camera_2d::Camera2d, Transparent2d},
4-
};
1+
use crate::core_2d::Transparent2d;
52
use bevy_ecs::prelude::*;
63
use bevy_render::{
74
camera::ExtractedCamera,
85
render_graph::{Node, NodeRunError, RenderGraphContext},
96
render_phase::RenderPhase,
10-
render_resource::{LoadOp, Operations, RenderPassDescriptor, StoreOp},
7+
render_resource::RenderPassDescriptor,
118
renderer::RenderContext,
129
view::{ExtractedView, ViewTarget},
1310
};
@@ -20,7 +17,6 @@ pub struct MainPass2dNode {
2017
&'static ExtractedCamera,
2118
&'static RenderPhase<Transparent2d>,
2219
&'static ViewTarget,
23-
&'static Camera2d,
2420
),
2521
With<ExtractedView>,
2622
>,
@@ -46,28 +42,19 @@ impl Node for MainPass2dNode {
4642
world: &World,
4743
) -> Result<(), NodeRunError> {
4844
let view_entity = graph.view_entity();
49-
let Ok((camera, transparent_phase, target, camera_2d)) =
50-
self.query.get_manual(world, view_entity)
45+
let Ok((camera, transparent_phase, target)) = self.query.get_manual(world, view_entity)
5146
else {
5247
// no target
5348
return Ok(());
5449
};
50+
5551
{
5652
#[cfg(feature = "trace")]
5753
let _main_pass_2d = info_span!("main_pass_2d").entered();
5854

5955
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
6056
label: Some("main_pass_2d"),
61-
color_attachments: &[Some(target.get_color_attachment(Operations {
62-
load: match camera_2d.clear_color {
63-
ClearColorConfig::Default => {
64-
LoadOp::Clear(world.resource::<ClearColor>().0.into())
65-
}
66-
ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()),
67-
ClearColorConfig::None => LoadOp::Load,
68-
},
69-
store: StoreOp::Store,
70-
}))],
57+
color_attachments: &[Some(target.get_color_attachment())],
7158
depth_stencil_attachment: None,
7259
timestamp_writes: None,
7360
occlusion_query_set: None,
@@ -88,10 +75,7 @@ impl Node for MainPass2dNode {
8875
let _reset_viewport_pass_2d = info_span!("reset_viewport_pass_2d").entered();
8976
let pass_descriptor = RenderPassDescriptor {
9077
label: Some("reset_viewport_pass_2d"),
91-
color_attachments: &[Some(target.get_color_attachment(Operations {
92-
load: LoadOp::Load,
93-
store: StoreOp::Store,
94-
}))],
78+
color_attachments: &[Some(target.get_color_attachment())],
9579
depth_stencil_attachment: None,
9680
timestamp_writes: None,
9781
occlusion_query_set: None,

crates/bevy_core_pipeline/src/core_3d/camera_3d.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::{
2-
clear_color::ClearColorConfig,
3-
tonemapping::{DebandDither, Tonemapping},
4-
};
1+
use crate::tonemapping::{DebandDither, Tonemapping};
52
use bevy_ecs::prelude::*;
63
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
74
use bevy_render::{
@@ -19,8 +16,6 @@ use serde::{Deserialize, Serialize};
1916
#[extract_component_filter(With<Camera>)]
2017
#[reflect(Component)]
2118
pub struct Camera3d {
22-
/// The clear color operation to perform for the main 3d pass.
23-
pub clear_color: ClearColorConfig,
2419
/// The depth clear operation to perform for the main 3d pass.
2520
pub depth_load_op: Camera3dDepthLoadOp,
2621
/// The texture usages for the depth texture created for the main 3d pass.
@@ -37,7 +32,7 @@ pub struct Camera3d {
3732
/// regardless of this setting.
3833
/// - Setting this to `0` disables the screen-space refraction effect entirely, and falls
3934
/// back to refracting only the environment map light's texture.
40-
/// - If set to more than `0`, any opaque [`clear_color`](Camera3d::clear_color) will obscure the environment
35+
/// - If set to more than `0`, any opaque [`clear_color`](Camera::clear_color) will obscure the environment
4136
/// map light's texture, preventing it from being visible “through” transmissive materials. If you'd like
4237
/// to still have the environment map show up in your refractions, you can set the clear color's alpha to `0.0`.
4338
/// Keep in mind that depending on the platform and your window settings, this may cause the window to become
@@ -55,7 +50,6 @@ pub struct Camera3d {
5550
impl Default for Camera3d {
5651
fn default() -> Self {
5752
Self {
58-
clear_color: ClearColorConfig::Default,
5953
depth_load_op: Default::default(),
6054
depth_texture_usages: TextureUsages::RENDER_ATTACHMENT.into(),
6155
screen_space_specular_transmission_steps: 1,

crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
11
use crate::{
2-
clear_color::{ClearColor, ClearColorConfig},
3-
core_3d::{Camera3d, Opaque3d},
4-
prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass},
2+
core_3d::Opaque3d,
53
skybox::{SkyboxBindGroup, SkyboxPipelineId},
64
};
75
use bevy_ecs::{prelude::World, query::QueryItem};
86
use bevy_render::{
97
camera::ExtractedCamera,
108
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
119
render_phase::RenderPhase,
12-
render_resource::{
13-
LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor,
14-
StoreOp,
15-
},
10+
render_resource::{PipelineCache, RenderPassDescriptor, StoreOp},
1611
renderer::RenderContext,
1712
view::{ViewDepthTexture, ViewTarget, ViewUniformOffset},
1813
};
1914
#[cfg(feature = "trace")]
2015
use bevy_utils::tracing::info_span;
2116

22-
use super::{AlphaMask3d, Camera3dDepthLoadOp};
17+
use super::AlphaMask3d;
2318

2419
/// A [`bevy_render::render_graph::Node`] that runs the [`Opaque3d`] and [`AlphaMask3d`] [`RenderPhase`].
2520
#[derive(Default)]
@@ -29,13 +24,8 @@ impl ViewNode for MainOpaquePass3dNode {
2924
&'static ExtractedCamera,
3025
&'static RenderPhase<Opaque3d>,
3126
&'static RenderPhase<AlphaMask3d>,
32-
&'static Camera3d,
3327
&'static ViewTarget,
3428
&'static ViewDepthTexture,
35-
Option<&'static DepthPrepass>,
36-
Option<&'static NormalPrepass>,
37-
Option<&'static MotionVectorPrepass>,
38-
Option<&'static DeferredPrepass>,
3929
Option<&'static SkyboxPipelineId>,
4030
Option<&'static SkyboxBindGroup>,
4131
&'static ViewUniformOffset,
@@ -49,30 +39,14 @@ impl ViewNode for MainOpaquePass3dNode {
4939
camera,
5040
opaque_phase,
5141
alpha_mask_phase,
52-
camera_3d,
5342
target,
5443
depth,
55-
depth_prepass,
56-
normal_prepass,
57-
motion_vector_prepass,
58-
deferred_prepass,
5944
skybox_pipeline,
6045
skybox_bind_group,
6146
view_uniform_offset,
6247
): QueryItem<Self::ViewData>,
6348
world: &World,
6449
) -> Result<(), NodeRunError> {
65-
let load = if deferred_prepass.is_none() {
66-
match camera_3d.clear_color {
67-
ClearColorConfig::Default => LoadOp::Clear(world.resource::<ClearColor>().0.into()),
68-
ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()),
69-
ClearColorConfig::None => LoadOp::Load,
70-
}
71-
} else {
72-
// If the deferred lighting pass has run, don't clear again in this pass.
73-
LoadOp::Load
74-
};
75-
7650
// Run the opaque pass, sorted front-to-back
7751
// NOTE: Scoped to drop the mutable borrow of render_context
7852
#[cfg(feature = "trace")]
@@ -81,33 +55,8 @@ impl ViewNode for MainOpaquePass3dNode {
8155
// Setup render pass
8256
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
8357
label: Some("main_opaque_pass_3d"),
84-
// NOTE: The opaque pass loads the color
85-
// buffer as well as writing to it.
86-
color_attachments: &[Some(target.get_color_attachment(Operations {
87-
load,
88-
store: StoreOp::Store,
89-
}))],
90-
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
91-
view: &depth.view,
92-
// NOTE: The opaque main pass loads the depth buffer and possibly overwrites it
93-
depth_ops: Some(Operations {
94-
load: if depth_prepass.is_some()
95-
|| normal_prepass.is_some()
96-
|| motion_vector_prepass.is_some()
97-
|| deferred_prepass.is_some()
98-
{
99-
// if any prepass runs, it will generate a depth buffer so we should use it,
100-
// even if only the normal_prepass is used.
101-
Camera3dDepthLoadOp::Load
102-
} else {
103-
// NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections.
104-
camera_3d.depth_load_op.clone()
105-
}
106-
.into(),
107-
store: StoreOp::Store,
108-
}),
109-
stencil_ops: None,
110-
}),
58+
color_attachments: &[Some(target.get_color_attachment())],
59+
depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
11160
timestamp_writes: None,
11261
occlusion_query_set: None,
11362
});

crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ use bevy_render::{
55
camera::ExtractedCamera,
66
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
77
render_phase::RenderPhase,
8-
render_resource::{
9-
Extent3d, LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor,
10-
StoreOp,
11-
},
8+
render_resource::{Extent3d, RenderPassDescriptor, StoreOp},
129
renderer::RenderContext,
1310
view::{ViewDepthTexture, ViewTarget},
1411
};
@@ -45,20 +42,8 @@ impl ViewNode for MainTransmissivePass3dNode {
4542

4643
let render_pass_descriptor = RenderPassDescriptor {
4744
label: Some("main_transmissive_pass_3d"),
48-
// NOTE: The transmissive pass loads the color buffer as well as overwriting it where appropriate.
49-
color_attachments: &[Some(target.get_color_attachment(Operations {
50-
load: LoadOp::Load,
51-
store: StoreOp::Store,
52-
}))],
53-
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
54-
view: &depth.view,
55-
// NOTE: The transmissive main pass loads the depth buffer and possibly overwrites it
56-
depth_ops: Some(Operations {
57-
load: LoadOp::Load,
58-
store: StoreOp::Store,
59-
}),
60-
stencil_ops: None,
61-
}),
45+
color_attachments: &[Some(target.get_color_attachment())],
46+
depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
6247
timestamp_writes: None,
6348
occlusion_query_set: None,
6449
};

crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ use bevy_render::{
44
camera::ExtractedCamera,
55
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
66
render_phase::RenderPhase,
7-
render_resource::{
8-
LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor, StoreOp,
9-
},
7+
render_resource::{RenderPassDescriptor, StoreOp},
108
renderer::RenderContext,
119
view::{ViewDepthTexture, ViewTarget},
1210
};
@@ -41,25 +39,14 @@ impl ViewNode for MainTransparentPass3dNode {
4139

4240
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
4341
label: Some("main_transparent_pass_3d"),
44-
// NOTE: The transparent pass loads the color buffer as well as overwriting it where appropriate.
45-
color_attachments: &[Some(target.get_color_attachment(Operations {
46-
load: LoadOp::Load,
47-
store: StoreOp::Store,
48-
}))],
49-
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
50-
view: &depth.view,
51-
// NOTE: For the transparent pass we load the depth buffer. There should be no
52-
// need to write to it, but store is set to `true` as a workaround for issue #3776,
53-
// https://github.com/bevyengine/bevy/issues/3776
54-
// so that wgpu does not clear the depth buffer.
55-
// As the opaque and alpha mask passes run first, opaque meshes can occlude
56-
// transparent ones.
57-
depth_ops: Some(Operations {
58-
load: LoadOp::Load,
59-
store: StoreOp::Store,
60-
}),
61-
stencil_ops: None,
62-
}),
42+
color_attachments: &[Some(target.get_color_attachment())],
43+
// NOTE: For the transparent pass we load the depth buffer. There should be no
44+
// need to write to it, but store is set to `true` as a workaround for issue #3776,
45+
// https://github.com/bevyengine/bevy/issues/3776
46+
// so that wgpu does not clear the depth buffer.
47+
// As the opaque and alpha mask passes run first, opaque meshes can occlude
48+
// transparent ones.
49+
depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
6350
timestamp_writes: None,
6451
occlusion_query_set: None,
6552
});
@@ -79,10 +66,7 @@ impl ViewNode for MainTransparentPass3dNode {
7966
let _reset_viewport_pass_3d = info_span!("reset_viewport_pass_3d").entered();
8067
let pass_descriptor = RenderPassDescriptor {
8168
label: Some("reset_viewport_pass_3d"),
82-
color_attachments: &[Some(target.get_color_attachment(Operations {
83-
load: LoadOp::Load,
84-
store: StoreOp::Store,
85-
}))],
69+
color_attachments: &[Some(target.get_color_attachment())],
8670
depth_stencil_attachment: None,
8771
timestamp_writes: None,
8872
occlusion_query_set: None,

0 commit comments

Comments
 (0)