Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep track of when a texture is first cleared #10325

Merged
merged 41 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
857b05e
Keep track of when a texture is first cleared
JMS55 Oct 31, 2023
e60f66c
Add missing import
JMS55 Oct 31, 2023
b8aad9c
Merge commit 'cbadc31d19e1d40841969ac503d49b3fff030f57' into target_i…
JMS55 Nov 10, 2023
104742e
Don't ignore depth in prepass
JMS55 Nov 10, 2023
5c0e9a6
WIP
JMS55 Nov 10, 2023
a76f74c
Add prepass support
JMS55 Nov 10, 2023
a6266e1
Add texture_attachment module
JMS55 Nov 21, 2023
e48b7b1
Switch shadow view to new API
JMS55 Nov 21, 2023
f875497
Depth target attachment
JMS55 Nov 21, 2023
52c429d
Make ColorAttachment hold CachedTexture directly
JMS55 Nov 21, 2023
66aeff0
WIP
JMS55 Nov 21, 2023
d89d118
WIP
JMS55 Nov 22, 2023
50dc55f
WIP
JMS55 Nov 22, 2023
283105a
Fixes
JMS55 Nov 22, 2023
bd36f9f
Merge commit '8067e46049f222d37ac394745805bad98979980f' into target_i…
JMS55 Dec 29, 2023
2874843
Fix rebase
JMS55 Dec 29, 2023
63e8032
Small fix
JMS55 Dec 29, 2023
4e61072
WIP MSAA fix
JMS55 Dec 29, 2023
badd572
Fixes
JMS55 Dec 29, 2023
7e7b9a7
Fix post processing
JMS55 Dec 29, 2023
dceab7a
Address PR feedback
JMS55 Dec 29, 2023
1ced9ff
Fix examples
JMS55 Dec 29, 2023
88714b2
Fix depth attachment for niche use cases
JMS55 Dec 29, 2023
6916691
Update crates/bevy_render/src/texture/texture_attachment.rs
JMS55 Dec 30, 2023
1c29415
Update crates/bevy_render/src/texture/texture_attachment.rs
JMS55 Dec 30, 2023
de5a84f
Fix webgl
JMS55 Dec 30, 2023
68e55db
Merge branch 'target_is_first_write' of https://github.com/JMS55/bevy…
JMS55 Dec 30, 2023
9753667
Fix webgl2 for deferred
JMS55 Dec 30, 2023
c7f6221
Merge commit '786abbf3f5e5be4b89c6b53d2d03162079f8e1f4' into target_i…
JMS55 Dec 30, 2023
3117ade
Fix doc links
JMS55 Dec 30, 2023
d00dd51
Clippy lint
JMS55 Dec 30, 2023
aa6169a
Fix missing import in example
JMS55 Dec 30, 2023
ec9fd69
Add clear color back to prelude
JMS55 Dec 30, 2023
a464324
Fix more examples
JMS55 Dec 30, 2023
15f8ecc
Fix more examples
JMS55 Dec 30, 2023
8c12fad
Update crates/bevy_core_pipeline/src/core_2d/camera_2d.rs
JMS55 Dec 30, 2023
bcba6f9
Appease clippy
JMS55 Dec 30, 2023
7d896c7
Merge branch 'target_is_first_write' of https://github.com/JMS55/bevy…
JMS55 Dec 30, 2023
f3f4f14
Fix broken test (the other one this time)
JMS55 Dec 31, 2023
f5c5806
More fixes
JMS55 Dec 31, 2023
c6063c5
Fix doc link
JMS55 Dec 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions crates/bevy_core_pipeline/src/bloom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,7 @@ impl ViewNode for BloomNode {
let mut upsampling_final_pass =
render_context.begin_tracked_render_pass(RenderPassDescriptor {
label: Some("bloom_upsampling_final_pass"),
color_attachments: &[Some(view_target.get_unsampled_color_attachment(
Operations {
load: LoadOp::Load,
store: StoreOp::Store,
},
))],
color_attachments: &[Some(view_target.get_unsampled_color_attachment())],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
Expand Down
9 changes: 2 additions & 7 deletions crates/bevy_core_pipeline/src/core_2d/camera_2d.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
clear_color::ClearColorConfig,
tonemapping::{DebandDither, Tonemapping},
};
use crate::tonemapping::{DebandDither, Tonemapping};
use bevy_ecs::prelude::*;
use bevy_reflect::Reflect;
use bevy_render::{
Expand All @@ -15,9 +12,7 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
#[extract_component_filter(With<Camera>)]
#[reflect(Component)]
pub struct Camera2d {
pub clear_color: ClearColorConfig,
}
pub struct Camera2d {}

JMS55 marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Bundle)]
pub struct Camera2dBundle {
Expand Down
30 changes: 6 additions & 24 deletions crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use crate::{
clear_color::{ClearColor, ClearColorConfig},
core_2d::{camera_2d::Camera2d, Transparent2d},
};
use crate::core_2d::Transparent2d;
use bevy_ecs::prelude::*;
use bevy_render::{
camera::ExtractedCamera,
render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::RenderPhase,
render_resource::{LoadOp, Operations, RenderPassDescriptor, StoreOp},
render_resource::RenderPassDescriptor,
renderer::RenderContext,
view::{ExtractedView, ViewTarget},
};
Expand All @@ -20,7 +17,6 @@ pub struct MainPass2dNode {
&'static ExtractedCamera,
&'static RenderPhase<Transparent2d>,
&'static ViewTarget,
&'static Camera2d,
),
With<ExtractedView>,
>,
Expand All @@ -46,28 +42,19 @@ impl Node for MainPass2dNode {
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.view_entity();
let Ok((camera, transparent_phase, target, camera_2d)) =
self.query.get_manual(world, view_entity)
let Ok((camera, transparent_phase, target)) = self.query.get_manual(world, view_entity)
else {
// no target
return Ok(());
};

{
#[cfg(feature = "trace")]
let _main_pass_2d = info_span!("main_pass_2d").entered();

let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
label: Some("main_pass_2d"),
color_attachments: &[Some(target.get_color_attachment(Operations {
load: match camera_2d.clear_color {
ClearColorConfig::Default => {
LoadOp::Clear(world.resource::<ClearColor>().0.into())
}
ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()),
ClearColorConfig::None => LoadOp::Load,
},
store: StoreOp::Store,
}))],
color_attachments: &[Some(target.get_color_attachment())],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
Expand All @@ -88,13 +75,8 @@ impl Node for MainPass2dNode {
let _reset_viewport_pass_2d = info_span!("reset_viewport_pass_2d").entered();
let pass_descriptor = RenderPassDescriptor {
label: Some("reset_viewport_pass_2d"),
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: StoreOp::Store,
}))],
color_attachments: &[Some(target.get_color_attachment())],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
};

render_context
Expand Down
8 changes: 1 addition & 7 deletions crates/bevy_core_pipeline/src/core_3d/camera_3d.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
clear_color::ClearColorConfig,
tonemapping::{DebandDither, Tonemapping},
};
use crate::tonemapping::{DebandDither, Tonemapping};
use bevy_ecs::prelude::*;
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::{
Expand All @@ -19,8 +16,6 @@ use serde::{Deserialize, Serialize};
#[extract_component_filter(With<Camera>)]
#[reflect(Component)]
pub struct Camera3d {
/// The clear color operation to perform for the main 3d pass.
pub clear_color: ClearColorConfig,
/// The depth clear operation to perform for the main 3d pass.
pub depth_load_op: Camera3dDepthLoadOp,
/// The texture usages for the depth texture created for the main 3d pass.
Expand Down Expand Up @@ -55,7 +50,6 @@ pub struct Camera3d {
impl Default for Camera3d {
fn default() -> Self {
Self {
clear_color: ClearColorConfig::Default,
depth_load_op: Default::default(),
depth_texture_usages: TextureUsages::RENDER_ATTACHMENT.into(),
screen_space_specular_transmission_steps: 1,
Expand Down
61 changes: 5 additions & 56 deletions crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
use crate::{
clear_color::{ClearColor, ClearColorConfig},
core_3d::{Camera3d, Opaque3d},
prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass},
core_3d::Opaque3d,
skybox::{SkyboxBindGroup, SkyboxPipelineId},
};
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_render::{
camera::ExtractedCamera,
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
render_phase::RenderPhase,
render_resource::{
LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor,
StoreOp,
},
render_resource::{PipelineCache, RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget, ViewUniformOffset},
};
#[cfg(feature = "trace")]
use bevy_utils::tracing::info_span;

use super::{AlphaMask3d, Camera3dDepthLoadOp};
use super::AlphaMask3d;

/// A [`bevy_render::render_graph::Node`] that runs the [`Opaque3d`] and [`AlphaMask3d`] [`RenderPhase`].
#[derive(Default)]
Expand All @@ -29,13 +24,8 @@ impl ViewNode for MainOpaquePass3dNode {
&'static ExtractedCamera,
&'static RenderPhase<Opaque3d>,
&'static RenderPhase<AlphaMask3d>,
&'static Camera3d,
&'static ViewTarget,
&'static ViewDepthTexture,
Option<&'static DepthPrepass>,
Option<&'static NormalPrepass>,
Option<&'static MotionVectorPrepass>,
Option<&'static DeferredPrepass>,
Option<&'static SkyboxPipelineId>,
Option<&'static SkyboxBindGroup>,
&'static ViewUniformOffset,
Expand All @@ -49,30 +39,14 @@ impl ViewNode for MainOpaquePass3dNode {
camera,
opaque_phase,
alpha_mask_phase,
camera_3d,
target,
depth,
depth_prepass,
normal_prepass,
motion_vector_prepass,
deferred_prepass,
skybox_pipeline,
skybox_bind_group,
view_uniform_offset,
): QueryItem<Self::ViewData>,
world: &World,
) -> Result<(), NodeRunError> {
let load = if deferred_prepass.is_none() {
match camera_3d.clear_color {
ClearColorConfig::Default => LoadOp::Clear(world.resource::<ClearColor>().0.into()),
ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()),
ClearColorConfig::None => LoadOp::Load,
}
} else {
// If the deferred lighting pass has run, don't clear again in this pass.
LoadOp::Load
};

// Run the opaque pass, sorted front-to-back
// NOTE: Scoped to drop the mutable borrow of render_context
#[cfg(feature = "trace")]
Expand All @@ -81,33 +55,8 @@ impl ViewNode for MainOpaquePass3dNode {
// Setup render pass
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
label: Some("main_opaque_pass_3d"),
// NOTE: The opaque pass loads the color
// buffer as well as writing to it.
color_attachments: &[Some(target.get_color_attachment(Operations {
load,
store: StoreOp::Store,
}))],
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &depth.view,
// NOTE: The opaque main pass loads the depth buffer and possibly overwrites it
depth_ops: Some(Operations {
load: if depth_prepass.is_some()
|| normal_prepass.is_some()
|| motion_vector_prepass.is_some()
|| deferred_prepass.is_some()
{
// if any prepass runs, it will generate a depth buffer so we should use it,
// even if only the normal_prepass is used.
Camera3dDepthLoadOp::Load
} else {
// NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections.
camera_3d.depth_load_op.clone()
}
.into(),
store: StoreOp::Store,
}),
stencil_ops: None,
}),
color_attachments: &[Some(target.get_color_attachment())],
depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
timestamp_writes: None,
occlusion_query_set: None,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use bevy_render::{
camera::ExtractedCamera,
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
render_phase::RenderPhase,
render_resource::{
Extent3d, LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor,
StoreOp,
},
render_resource::{Extent3d, RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget},
};
Expand Down Expand Up @@ -45,20 +42,8 @@ impl ViewNode for MainTransmissivePass3dNode {

let render_pass_descriptor = RenderPassDescriptor {
label: Some("main_transmissive_pass_3d"),
// NOTE: The transmissive pass loads the color buffer as well as overwriting it where appropriate.
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: StoreOp::Store,
}))],
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &depth.view,
// NOTE: The transmissive main pass loads the depth buffer and possibly overwrites it
depth_ops: Some(Operations {
load: LoadOp::Load,
store: StoreOp::Store,
}),
stencil_ops: None,
}),
color_attachments: &[Some(target.get_color_attachment())],
depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
timestamp_writes: None,
occlusion_query_set: None,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use bevy_render::{
camera::ExtractedCamera,
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
render_phase::RenderPhase,
render_resource::{
LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor, StoreOp,
},
render_resource::{RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget},
};
Expand Down Expand Up @@ -41,25 +39,14 @@ impl ViewNode for MainTransparentPass3dNode {

let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
label: Some("main_transparent_pass_3d"),
// NOTE: The transparent pass loads the color buffer as well as overwriting it where appropriate.
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: StoreOp::Store,
}))],
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &depth.view,
// NOTE: For the transparent pass we load the depth buffer. There should be no
// need to write to it, but store is set to `true` as a workaround for issue #3776,
// https://github.com/bevyengine/bevy/issues/3776
// so that wgpu does not clear the depth buffer.
// As the opaque and alpha mask passes run first, opaque meshes can occlude
// transparent ones.
depth_ops: Some(Operations {
load: LoadOp::Load,
store: StoreOp::Store,
}),
stencil_ops: None,
}),
color_attachments: &[Some(target.get_color_attachment())],
// NOTE: For the transparent pass we load the depth buffer. There should be no
// need to write to it, but store is set to `true` as a workaround for issue #3776,
// https://github.com/bevyengine/bevy/issues/3776
// so that wgpu does not clear the depth buffer.
// As the opaque and alpha mask passes run first, opaque meshes can occlude
// transparent ones.
depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
timestamp_writes: None,
occlusion_query_set: None,
});
Expand All @@ -79,13 +66,8 @@ impl ViewNode for MainTransparentPass3dNode {
let _reset_viewport_pass_3d = info_span!("reset_viewport_pass_3d").entered();
let pass_descriptor = RenderPassDescriptor {
label: Some("reset_viewport_pass_3d"),
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: StoreOp::Store,
}))],
color_attachments: &[Some(target.get_color_attachment())],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
};

render_context
Expand Down
28 changes: 18 additions & 10 deletions crates/bevy_core_pipeline/src/core_3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use bevy_app::{App, Plugin, PostUpdate};
use bevy_ecs::prelude::*;
use bevy_render::{
camera::{Camera, ExtractedCamera},
color::Color,
extract_component::ExtractComponentPlugin,
prelude::Msaa,
render_graph::{EmptyNode, RenderGraphApp, ViewNodeRunner},
Expand All @@ -54,7 +55,7 @@ use bevy_render::{
TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, TextureView,
},
renderer::RenderDevice,
texture::{BevyDefault, TextureCache},
texture::{BevyDefault, ColorAttachment, TextureCache},
view::{ExtractedView, ViewDepthTexture, ViewTarget},
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
};
Expand Down Expand Up @@ -526,7 +527,7 @@ pub fn prepare_core_3d_depth_textures(
}

let mut textures = HashMap::default();
for (entity, camera, _, _) in &views_3d {
for (entity, camera, _, camera_3d) in &views_3d {
let Some(physical_target_size) = camera.physical_target_size else {
continue;
};
Expand Down Expand Up @@ -560,10 +561,13 @@ pub fn prepare_core_3d_depth_textures(
})
.clone();

commands.entity(entity).insert(ViewDepthTexture {
texture: cached_texture.texture,
view: cached_texture.default_view,
});
commands.entity(entity).insert(ViewDepthTexture::new(
cached_texture,
match camera_3d.depth_load_op {
Camera3dDepthLoadOp::Clear(v) => Some(v),
Camera3dDepthLoadOp::Load => None,
},
));
}
}

Expand Down Expand Up @@ -824,10 +828,14 @@ pub fn prepare_prepass_textures(
});

commands.entity(entity).insert(ViewPrepassTextures {
depth: cached_depth_texture,
normal: cached_normals_texture,
motion_vectors: cached_motion_vectors_texture,
deferred: cached_deferred_texture,
depth: cached_depth_texture.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
normal: cached_normals_texture.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
// Red and Green channels are X and Y components of the motion vectors
// Blue channel doesn't matter, but set to 0.0 for possible faster clear
// https://gpuopen.com/performance/#clears
motion_vectors: cached_motion_vectors_texture
.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
deferred: cached_deferred_texture.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
deferred_lighting_pass_id: deferred_lighting_pass_id_texture,
size,
});
Expand Down
Loading
Loading