From 857b05e0935f5e9db40e4e52141df0e1511c8fde Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 30 Oct 2023 19:33:51 -0700 Subject: [PATCH 01/36] Keep track of when a texture is first cleared --- .../src/core_3d/main_opaque_pass_3d_node.rs | 23 ++++--------------- crates/bevy_core_pipeline/src/core_3d/mod.rs | 8 +++---- .../bevy_core_pipeline/src/deferred/node.rs | 12 +++------- crates/bevy_core_pipeline/src/prepass/node.rs | 2 ++ crates/bevy_pbr/src/deferred/mod.rs | 23 +++++++++++-------- crates/bevy_render/src/view/mod.rs | 21 +++++++++++++++++ 6 files changed, 47 insertions(+), 42 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index a64ed8f4c8bef..8b99e036fddea 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -31,10 +31,6 @@ impl ViewNode for MainOpaquePass3dNode { &'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, @@ -51,24 +47,19 @@ impl ViewNode for MainOpaquePass3dNode { camera_3d, target, depth, - depth_prepass, - normal_prepass, - motion_vector_prepass, - deferred_prepass, skybox_pipeline, skybox_bind_group, view_uniform_offset, ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { - let load = if deferred_prepass.is_none() { + let load = if target.is_first_write() { match camera_3d.clear_color { ClearColorConfig::Default => LoadOp::Clear(world.resource::().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 }; @@ -89,17 +80,11 @@ impl ViewNode for MainOpaquePass3dNode { 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 { + load: if depth.is_first_write() { // NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections. camera_3d.depth_load_op.clone() + } else { + Camera3dDepthLoadOp::Load } .into(), store: true, diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index b0bee381cc275..1cbec64f62e9d 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -477,10 +477,10 @@ 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.texture, + cached_texture.default_view, + )); } } diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index f598e8393ea70..324b407553478 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -36,7 +36,6 @@ impl ViewNode for DeferredGBufferPrepassNode { &'static ViewDepthTexture, &'static ViewPrepassTextures, &'static Camera3d, - Option<&'static DepthPrepass>, Option<&'static NormalPrepass>, Option<&'static MotionVectorPrepass>, ); @@ -52,7 +51,6 @@ impl ViewNode for DeferredGBufferPrepassNode { view_depth_texture, view_prepass_textures, camera_3d, - depth_prepass, normal_prepass, motion_vector_prepass, ): QueryItem, @@ -154,15 +152,11 @@ impl ViewNode for DeferredGBufferPrepassNode { depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { view: &view_depth_texture.view, depth_ops: Some(Operations { - load: if depth_prepass.is_some() - || normal_prepass.is_some() - || motion_vector_prepass.is_some() - { - // If any prepass runs, it will generate a depth buffer so we should use it. - Camera3dDepthLoadOp::Load - } else { + load: if view_depth_texture.is_first_write() { // NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections. camera_3d.depth_load_op.clone() + } else { + Camera3dDepthLoadOp::Load } .into(), store: true, diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index 5b64ad7bf4284..5e7df11048916 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -50,6 +50,8 @@ impl ViewNode for PrepassNode { ) -> Result<(), NodeRunError> { let view_entity = graph.view_entity(); + let _ = view_depth_texture.is_first_write(); + let mut color_attachments = vec![ view_prepass_textures .normal diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index f679f638d42ac..cf542608f80b2 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -197,18 +197,21 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { &BindGroupEntries::single(deferred_lighting_pass_id_binding), ); + let load = if target.is_first_write() { + match camera_3d.clear_color { + ClearColorConfig::Default => LoadOp::Clear(world.resource::().0.into()), + ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()), + ClearColorConfig::None => LoadOp::Load, + } + } else { + LoadOp::Load + }; + let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("deferred_lighting_pass"), - color_attachments: &[Some(target.get_color_attachment(Operations { - load: match camera_3d.clear_color { - ClearColorConfig::Default => { - LoadOp::Clear(world.resource::().0.into()) - } - ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()), - ClearColorConfig::None => LoadOp::Load, - }, - store: true, - }))], + color_attachments: &[Some( + target.get_color_attachment(Operations { load, store: true }), + )], depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { view: &deferred_lighting_id_depth_texture.texture.default_view, depth_ops: Some(Operations { diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 9759684148324..4974af3ec4e83 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -191,6 +191,7 @@ pub struct ViewTarget { main_texture: Arc, out_texture: TextureView, out_texture_format: TextureFormat, + first_write: Arc, } pub struct PostProcessWrite<'a> { @@ -201,6 +202,10 @@ pub struct PostProcessWrite<'a> { impl ViewTarget { pub const TEXTURE_FORMAT_HDR: TextureFormat = TextureFormat::Rgba16Float; + pub fn is_first_write(&self) -> bool { + self.first_write.fetch_and(false, Ordering::SeqCst) + } + /// Retrieve this target's color attachment. This will use [`Self::sampled_main_texture_view`] and resolve to [`Self::main_texture`] if /// the target has sampling enabled. Otherwise it will use [`Self::main_texture`] directly. pub fn get_color_attachment(&self, ops: Operations) -> RenderPassColorAttachment { @@ -342,6 +347,21 @@ impl ViewTarget { pub struct ViewDepthTexture { pub texture: Texture, pub view: TextureView, + first_write: Arc, +} + +impl ViewDepthTexture { + pub fn new(texture: Texture, view: TextureView) -> Self { + Self { + texture, + view, + first_write: Arc::new(AtomicBool::new(true)), + } + } + + pub fn is_first_write(&self) -> bool { + self.first_write.fetch_and(false, Ordering::SeqCst) + } } pub fn prepare_view_uniforms( @@ -511,6 +531,7 @@ fn prepare_view_targets( main_texture: main_textures.main_texture.clone(), out_texture: out_texture_view.clone(), out_texture_format: out_texture_format.add_srgb_suffix(), + first_write: Arc::new(AtomicBool::new(true)), }); } } From e60f66cc6074c97a12a2f09de2949ea1370c4d24 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 30 Oct 2023 19:47:53 -0700 Subject: [PATCH 02/36] Add missing import --- crates/bevy_render/src/view/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 4974af3ec4e83..d8ace7d20e7e5 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -23,7 +23,7 @@ use bevy_reflect::Reflect; use bevy_transform::components::GlobalTransform; use bevy_utils::HashMap; use std::sync::{ - atomic::{AtomicUsize, Ordering}, + atomic::{AtomicBool, AtomicUsize, Ordering}, Arc, }; use wgpu::{ From 104742e254a6bc918c148a1d5ff299dcbddc9394 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 9 Nov 2023 16:43:33 -0800 Subject: [PATCH 03/36] Don't ignore depth in prepass --- crates/bevy_core_pipeline/src/deferred/node.rs | 2 +- crates/bevy_core_pipeline/src/prepass/node.rs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 324b407553478..2a3770a15c674 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -18,7 +18,7 @@ use bevy_render::{ use bevy_utils::tracing::info_span; use crate::core_3d::{Camera3d, Camera3dDepthLoadOp}; -use crate::prepass::{DepthPrepass, MotionVectorPrepass, NormalPrepass, ViewPrepassTextures}; +use crate::prepass::{MotionVectorPrepass, NormalPrepass, ViewPrepassTextures}; use super::{AlphaMask3dDeferred, Opaque3dDeferred}; diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index 5e7df11048916..df5afceb80dad 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -16,6 +16,8 @@ use bevy_render::{ #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; +use crate::core_3d::{Camera3d, Camera3dDepthLoadOp}; + use super::{AlphaMask3dPrepass, DeferredPrepass, Opaque3dPrepass, ViewPrepassTextures}; /// Render node used by the prepass. @@ -27,6 +29,7 @@ pub struct PrepassNode; impl ViewNode for PrepassNode { type ViewQuery = ( &'static ExtractedCamera, + &'static Camera3d, &'static RenderPhase, &'static RenderPhase, &'static ViewDepthTexture, @@ -40,6 +43,7 @@ impl ViewNode for PrepassNode { render_context: &mut RenderContext, ( camera, + camera_3d, opaque_prepass_phase, alpha_mask_prepass_phase, view_depth_texture, @@ -50,8 +54,6 @@ impl ViewNode for PrepassNode { ) -> Result<(), NodeRunError> { let view_entity = graph.view_entity(); - let _ = view_depth_texture.is_first_write(); - let mut color_attachments = vec![ view_prepass_textures .normal @@ -96,7 +98,13 @@ impl ViewNode for PrepassNode { depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { view: &view_depth_texture.view, depth_ops: Some(Operations { - load: LoadOp::Clear(0.0), + load: if view_depth_texture.is_first_write() { + // NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections. + camera_3d.depth_load_op.clone() + } else { + Camera3dDepthLoadOp::Load + } + .into(), store: true, }), stencil_ops: None, From 5c0e9a65dd9aecffd389e6e21a36aa2cce66f3c0 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 9 Nov 2023 16:55:01 -0800 Subject: [PATCH 04/36] WIP --- .../src/core_3d/main_opaque_pass_3d_node.rs | 1 - crates/bevy_core_pipeline/src/core_3d/mod.rs | 14 ++++++---- crates/bevy_core_pipeline/src/prepass/mod.rs | 16 +++++++++++- crates/bevy_pbr/src/render/light.rs | 26 +++++++++++++++++-- crates/bevy_render/src/view/mod.rs | 6 ++--- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index 8b99e036fddea..916d69ca63018 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -1,7 +1,6 @@ use crate::{ clear_color::{ClearColor, ClearColorConfig}, core_3d::{Camera3d, Opaque3d}, - prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass}, skybox::{SkyboxBindGroup, SkyboxPipelineId}, }; use bevy_ecs::{prelude::*, query::QueryItem}; diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 04a5c91997ae0..2cfc4c4e4faa2 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -32,7 +32,11 @@ pub const CORE_3D: &str = graph::NAME; // PERF: vulkan docs recommend using 24 bit depth for better performance pub const CORE_3D_DEPTH_FORMAT: TextureFormat = TextureFormat::Depth32Float; -use std::{cmp::Reverse, ops::Range}; +use std::{ + cmp::Reverse, + ops::Range, + sync::{atomic::AtomicBool, Arc}, +}; pub use camera_3d::*; pub use main_opaque_pass_3d_node::*; @@ -559,10 +563,9 @@ pub fn prepare_core_3d_depth_textures( }) .clone(); - commands.entity(entity).insert(ViewDepthTexture::new( - cached_texture.texture, - cached_texture.default_view, - )); + commands + .entity(entity) + .insert(ViewDepthTexture::new(cached_texture)); } } @@ -829,6 +832,7 @@ pub fn prepare_prepass_textures( deferred: cached_deferred_texture, deferred_lighting_pass_id: deferred_lighting_pass_id_texture, size, + first_write: Arc::new(AtomicBool::new(true)), }); } } diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index 63b8c764af5ff..d56c465225a06 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -27,7 +27,14 @@ pub mod node; -use std::{cmp::Reverse, ops::Range}; +use std::{ + cmp::Reverse, + ops::Range, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; use bevy_ecs::prelude::*; use bevy_reflect::Reflect; @@ -81,6 +88,13 @@ pub struct ViewPrepassTextures { pub deferred_lighting_pass_id: Option, /// The size of the textures. pub size: Extent3d, + pub(crate) first_write: Arc, +} + +impl ViewPrepassTextures { + pub fn is_first_write(&self) -> bool { + self.first_write.fetch_and(false, Ordering::SeqCst) + } } /// Opaque phase of the 3D prepass. diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 62a7367520756..e81726d165500 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -20,7 +20,15 @@ use bevy_utils::{ tracing::{error, warn}, HashMap, }; -use std::{hash::Hash, num::NonZeroU64, ops::Range}; +use std::{ + hash::Hash, + num::NonZeroU64, + ops::Range, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; use crate::*; @@ -514,6 +522,13 @@ fn face_index_to_name(face_index: usize) -> &'static str { pub struct ShadowView { pub depth_texture_view: TextureView, pub pass_name: String, + first_write: Arc, +} + +impl ShadowView { + pub fn is_first_write(&self) -> bool { + self.first_write.fetch_and(false, Ordering::SeqCst) + } } #[derive(Component)] @@ -1004,6 +1019,7 @@ pub fn prepare_lights( light_index, face_index_to_name(face_index) ), + first_write: Arc::new(AtomicBool::new(true)), }, ExtractedView { viewport: UVec4::new( @@ -1062,6 +1078,7 @@ pub fn prepare_lights( ShadowView { depth_texture_view, pass_name: format!("shadow pass spot light {light_index}"), + first_write: Arc::new(AtomicBool::new(true)), }, ExtractedView { viewport: UVec4::new( @@ -1128,6 +1145,7 @@ pub fn prepare_lights( depth_texture_view, pass_name: format!( "shadow pass directional light {light_index} cascade {cascade_index}"), + first_write: Arc::new(AtomicBool::new(true)), }, ExtractedView { viewport: UVec4::new( @@ -1760,7 +1778,11 @@ impl Node for ShadowPassNode { depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { view: &view_light.depth_texture_view, depth_ops: Some(Operations { - load: LoadOp::Clear(0.0), + load: if view_light.is_first_write() { + LoadOp::Clear(0.0) + } else { + LoadOp::Load + }, store: true, }), stencil_ops: None, diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 90d7045612e3e..5bfd647da4562 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -353,10 +353,10 @@ pub struct ViewDepthTexture { } impl ViewDepthTexture { - pub fn new(texture: Texture, view: TextureView) -> Self { + pub fn new(texture: CachedTexture) -> Self { Self { - texture, - view, + texture: texture.texture, + view: texture.default_view, first_write: Arc::new(AtomicBool::new(true)), } } From a76f74c70a747169abdac9ee87f327e41afff60f Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 9 Nov 2023 22:08:42 -0800 Subject: [PATCH 05/36] Add prepass support --- crates/bevy_core_pipeline/src/core_3d/mod.rs | 4 +- .../bevy_core_pipeline/src/deferred/node.rs | 37 ++++++++++--------- crates/bevy_core_pipeline/src/prepass/mod.rs | 17 +++++++-- crates/bevy_core_pipeline/src/prepass/node.rs | 18 ++++++--- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 2cfc4c4e4faa2..0a7102c5aeb2a 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -832,7 +832,9 @@ pub fn prepare_prepass_textures( deferred: cached_deferred_texture, deferred_lighting_pass_id: deferred_lighting_pass_id_texture, size, - first_write: Arc::new(AtomicBool::new(true)), + first_normal_write: Arc::new(AtomicBool::new(true)), + first_motion_vectors_write: Arc::new(AtomicBool::new(true)), + first_deferred_write: Arc::new(AtomicBool::new(true)), }); } } diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 2a3770a15c674..eedacd569ee48 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -18,7 +18,7 @@ use bevy_render::{ use bevy_utils::tracing::info_span; use crate::core_3d::{Camera3d, Camera3dDepthLoadOp}; -use crate::prepass::{MotionVectorPrepass, NormalPrepass, ViewPrepassTextures}; +use crate::prepass::ViewPrepassTextures; use super::{AlphaMask3dDeferred, Opaque3dDeferred}; @@ -36,8 +36,6 @@ impl ViewNode for DeferredGBufferPrepassNode { &'static ViewDepthTexture, &'static ViewPrepassTextures, &'static Camera3d, - Option<&'static NormalPrepass>, - Option<&'static MotionVectorPrepass>, ); fn run( @@ -51,8 +49,6 @@ impl ViewNode for DeferredGBufferPrepassNode { view_depth_texture, view_prepass_textures, camera_3d, - normal_prepass, - motion_vector_prepass, ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { @@ -67,12 +63,10 @@ impl ViewNode for DeferredGBufferPrepassNode { view: &view_normals_texture.default_view, resolve_target: None, ops: Operations { - load: if normal_prepass.is_some() { - // Load if the normal_prepass has already run. - // The prepass will have already cleared this for the current frame. - LoadOp::Load - } else { + load: if view_prepass_textures.is_first_normal_write() { LoadOp::Clear(Color::BLACK.into()) + } else { + LoadOp::Load }, store: true, }, @@ -83,12 +77,13 @@ impl ViewNode for DeferredGBufferPrepassNode { view: &view_motion_vectors_texture.default_view, resolve_target: None, ops: Operations { - load: if motion_vector_prepass.is_some() { - // Load if the motion_vector_prepass has already run. - // The prepass will have already cleared this for the current frame. - LoadOp::Load - } else { + load: if view_prepass_textures.is_first_motion_vectors_write() { + // 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 LoadOp::Clear(Color::BLACK.into()) + } else { + LoadOp::Load }, store: true, }, @@ -119,7 +114,11 @@ impl ViewNode for DeferredGBufferPrepassNode { #[cfg(all(feature = "webgl", target_arch = "wasm32"))] load: LoadOp::Load, #[cfg(not(all(feature = "webgl", target_arch = "wasm32")))] - load: LoadOp::Clear(Default::default()), + load: if view_prepass_textures.is_first_deferred_write() { + LoadOp::Clear(Color::BLACK.into()) + } else { + LoadOp::Load + }, store: true, }, }), @@ -133,7 +132,11 @@ impl ViewNode for DeferredGBufferPrepassNode { view: &deferred_lighting_pass_id.default_view, resolve_target: None, ops: Operations { - load: LoadOp::Clear(Default::default()), + load: if view_prepass_textures.is_first_deferred_write() { + LoadOp::Clear(Color::BLACK.into()) + } else { + LoadOp::Load + }, store: true, }, }), diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index d56c465225a06..dfdeb1cc86f6a 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -88,12 +88,23 @@ pub struct ViewPrepassTextures { pub deferred_lighting_pass_id: Option, /// The size of the textures. pub size: Extent3d, - pub(crate) first_write: Arc, + pub(crate) first_normal_write: Arc, + pub(crate) first_motion_vectors_write: Arc, + pub(crate) first_deferred_write: Arc, } impl ViewPrepassTextures { - pub fn is_first_write(&self) -> bool { - self.first_write.fetch_and(false, Ordering::SeqCst) + pub fn is_first_normal_write(&self) -> bool { + self.first_normal_write.fetch_and(false, Ordering::SeqCst) + } + + pub fn is_first_motion_vectors_write(&self) -> bool { + self.first_motion_vectors_write + .fetch_and(false, Ordering::SeqCst) + } + + pub fn is_first_deferred_write(&self) -> bool { + self.first_deferred_write.fetch_and(false, Ordering::SeqCst) } } diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index df5afceb80dad..66dd55f012e3f 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -62,7 +62,11 @@ impl ViewNode for PrepassNode { view: &view_normals_texture.default_view, resolve_target: None, ops: Operations { - load: LoadOp::Clear(Color::BLACK.into()), + load: if view_prepass_textures.is_first_normal_write() { + LoadOp::Clear(Color::BLACK.into()) + } else { + LoadOp::Load + }, store: true, }, }), @@ -73,10 +77,14 @@ impl ViewNode for PrepassNode { view: &view_motion_vectors_texture.default_view, resolve_target: None, ops: Operations { - // 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 - load: LoadOp::Clear(Color::BLACK.into()), + load: if view_prepass_textures.is_first_motion_vectors_write() { + // 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 + LoadOp::Clear(Color::BLACK.into()) + } else { + LoadOp::Load + }, store: true, }, }), From a6266e1f77c8d64facf72f066d3125264fcc40d7 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:06:31 -0500 Subject: [PATCH 06/36] Add texture_attachment module --- crates/bevy_render/src/texture/mod.rs | 2 + .../src/texture/texture_attachment.rs | 84 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 crates/bevy_render/src/texture/texture_attachment.rs diff --git a/crates/bevy_render/src/texture/mod.rs b/crates/bevy_render/src/texture/mod.rs index d7a31a2bebf27..866cbc928c68e 100644 --- a/crates/bevy_render/src/texture/mod.rs +++ b/crates/bevy_render/src/texture/mod.rs @@ -14,6 +14,7 @@ mod image; mod image_loader; #[cfg(feature = "ktx2")] mod ktx2; +mod texture_attachment; mod texture_cache; pub(crate) mod image_texture_conversion; @@ -32,6 +33,7 @@ pub use hdr_texture_loader::*; pub use compressed_image_saver::*; pub use fallback_image::*; pub use image_loader::*; +pub use texture_attachment::*; pub use texture_cache::*; use crate::{ diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs new file mode 100644 index 0000000000000..a1144ba2a72ab --- /dev/null +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -0,0 +1,84 @@ +use crate::prelude::Color; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; +use wgpu::{ + LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, TextureView, +}; + +/// A wrapper for a [TextureView] that is used as a [RenderPassColorAttachment]. +pub struct ColorAttachment { + pub view: TextureView, + pub resolve_target: Option, + clear_color: Color, + is_first_call: Arc, +} + +impl ColorAttachment { + pub fn new(view: TextureView, resolve_target: Option, clear_color: Color) -> Self { + Self { + view, + resolve_target, + clear_color, + is_first_call: Arc::new(AtomicBool::new(true)), + } + } + + /// Get this texture view as an attachment. The attachment will be cleared with a value of + /// `clear_color` if this is the first time calling this function, otherwise the it will be loaded. + /// + /// The returned attachment will always have writing enabled (`store: true`). + pub fn get_attachment(&self) -> RenderPassColorAttachment { + let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); + + RenderPassColorAttachment { + view: &self.view, + resolve_target: self.resolve_target.as_ref(), + ops: Operations { + load: if first_call { + LoadOp::Clear(self.clear_color.into()) + } else { + LoadOp::Load + }, + store: true, + }, + } + } +} + +/// A wrapper for a [TextureView] that is used as a depth-only [RenderPassDepthStencilAttachment]. +pub struct DepthAttachment { + pub view: TextureView, + clear_value: f32, + is_first_call: Arc, +} + +impl DepthAttachment { + pub fn new(view: TextureView, clear_value: f32) -> Self { + Self { + view, + clear_value, + is_first_call: Arc::new(AtomicBool::new(true)), + } + } + + /// Get this texture view as an attachment. The attachment will be cleared with a value of + /// `clear_value` if this is the first time calling this function, otherwise the it will be loaded. + pub fn get_attachment(&self, store: bool) -> RenderPassDepthStencilAttachment { + let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); + + RenderPassDepthStencilAttachment { + view: &self.view, + depth_ops: Some(Operations { + load: if first_call { + LoadOp::Clear(self.clear_value) + } else { + LoadOp::Load + }, + store, + }), + stencil_ops: None, + } + } +} From e48b7b18600ad4125394e6e6f6a6986418296358 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:13:33 -0500 Subject: [PATCH 07/36] Switch shadow view to new API --- crates/bevy_pbr/src/render/light.rs | 33 ++++++----------------------- crates/bevy_render/src/view/mod.rs | 9 -------- 2 files changed, 7 insertions(+), 35 deletions(-) diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index e81726d165500..58b07a6e3e337 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -520,15 +520,8 @@ fn face_index_to_name(face_index: usize) -> &'static str { #[derive(Component)] pub struct ShadowView { - pub depth_texture_view: TextureView, + pub depth_attachment: DepthAttachment, pub pass_name: String, - first_write: Arc, -} - -impl ShadowView { - pub fn is_first_write(&self) -> bool { - self.first_write.fetch_and(false, Ordering::SeqCst) - } } #[derive(Component)] @@ -1013,13 +1006,12 @@ pub fn prepare_lights( let view_light_entity = commands .spawn(( ShadowView { - depth_texture_view, + depth_attachment: DepthAttachment::new(depth_texture_view, 0.0), pass_name: format!( "shadow pass point light {} {}", light_index, face_index_to_name(face_index) ), - first_write: Arc::new(AtomicBool::new(true)), }, ExtractedView { viewport: UVec4::new( @@ -1076,9 +1068,8 @@ pub fn prepare_lights( let view_light_entity = commands .spawn(( ShadowView { - depth_texture_view, + depth_attachment: DepthAttachment::new(depth_texture_view, 0.0), pass_name: format!("shadow pass spot light {light_index}"), - first_write: Arc::new(AtomicBool::new(true)), }, ExtractedView { viewport: UVec4::new( @@ -1142,10 +1133,9 @@ pub fn prepare_lights( let view_light_entity = commands .spawn(( ShadowView { - depth_texture_view, + depth_attachment: DepthAttachment::new(depth_texture_view, 0.0), pass_name: format!( "shadow pass directional light {light_index} cascade {cascade_index}"), - first_write: Arc::new(AtomicBool::new(true)), }, ExtractedView { viewport: UVec4::new( @@ -1775,18 +1765,9 @@ impl Node for ShadowPassNode { render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some(&view_light.pass_name), color_attachments: &[], - depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { - view: &view_light.depth_texture_view, - depth_ops: Some(Operations { - load: if view_light.is_first_write() { - LoadOp::Clear(0.0) - } else { - LoadOp::Load - }, - store: true, - }), - stencil_ops: None, - }), + depth_stencil_attachment: Some( + view_light.depth_attachment.get_attachment(true), + ), }); shadow_phase.render(&mut render_pass, world, view_light_entity); diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 5bfd647da4562..efc8077dc3bba 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -193,7 +193,6 @@ pub struct ViewTarget { main_texture: Arc, out_texture: TextureView, out_texture_format: TextureFormat, - first_write: Arc, } pub struct PostProcessWrite<'a> { @@ -204,10 +203,6 @@ pub struct PostProcessWrite<'a> { impl ViewTarget { pub const TEXTURE_FORMAT_HDR: TextureFormat = TextureFormat::Rgba16Float; - pub fn is_first_write(&self) -> bool { - self.first_write.fetch_and(false, Ordering::SeqCst) - } - /// Retrieve this target's color attachment. This will use [`Self::sampled_main_texture_view`] and resolve to [`Self::main_texture`] if /// the target has sampling enabled. Otherwise it will use [`Self::main_texture`] directly. pub fn get_color_attachment(&self, ops: Operations) -> RenderPassColorAttachment { @@ -360,10 +355,6 @@ impl ViewDepthTexture { first_write: Arc::new(AtomicBool::new(true)), } } - - pub fn is_first_write(&self) -> bool { - self.first_write.fetch_and(false, Ordering::SeqCst) - } } pub fn prepare_view_uniforms( From f875497f97a4370893555922979b891286f64af3 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 20 Nov 2023 23:20:06 -0500 Subject: [PATCH 08/36] Depth target attachment --- .../src/core_3d/main_opaque_pass_3d_node.rs | 16 +--------------- crates/bevy_core_pipeline/src/core_3d/mod.rs | 12 ++++++++---- crates/bevy_core_pipeline/src/deferred/node.rs | 15 +-------------- crates/bevy_core_pipeline/src/prepass/mod.rs | 18 ------------------ crates/bevy_core_pipeline/src/prepass/node.rs | 16 ++-------------- .../src/texture/texture_attachment.rs | 9 +++++---- crates/bevy_render/src/view/mod.rs | 11 ++++------- 7 files changed, 21 insertions(+), 76 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index 916d69ca63018..bf807879c5b59 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -75,21 +75,7 @@ impl ViewNode for MainOpaquePass3dNode { color_attachments: &[Some( target.get_color_attachment(Operations { load, store: true }), )], - 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.is_first_write() { - // NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections. - camera_3d.depth_load_op.clone() - } else { - Camera3dDepthLoadOp::Load - } - .into(), - store: true, - }), - stencil_ops: None, - }), + depth_stencil_attachment: Some(depth.attachment.get_attachment(true)), }); if let Some(viewport) = camera.viewport.as_ref() { diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 0a7102c5aeb2a..a585dfcd7c65e 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -529,7 +529,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; }; @@ -563,9 +563,13 @@ pub fn prepare_core_3d_depth_textures( }) .clone(); - commands - .entity(entity) - .insert(ViewDepthTexture::new(cached_texture)); + commands.entity(entity).insert(ViewDepthTexture::new( + cached_texture, + match camera_3d.depth_load_op { + Camera3dDepthLoadOp::Clear(v) => Some(v), + Camera3dDepthLoadOp::Load => None, + }, + )); } } diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index eedacd569ee48..10f3e613cf393 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -152,20 +152,7 @@ impl ViewNode for DeferredGBufferPrepassNode { let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("deferred"), color_attachments: &color_attachments, - depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { - view: &view_depth_texture.view, - depth_ops: Some(Operations { - load: if view_depth_texture.is_first_write() { - // NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections. - camera_3d.depth_load_op.clone() - } else { - Camera3dDepthLoadOp::Load - } - .into(), - store: true, - }), - stencil_ops: None, - }), + depth_stencil_attachment: Some(view_depth_texture.attachment.get_attachment(true)), }); if let Some(viewport) = camera.viewport.as_ref() { diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index dfdeb1cc86f6a..f87c64038e4ab 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -88,24 +88,6 @@ pub struct ViewPrepassTextures { pub deferred_lighting_pass_id: Option, /// The size of the textures. pub size: Extent3d, - pub(crate) first_normal_write: Arc, - pub(crate) first_motion_vectors_write: Arc, - pub(crate) first_deferred_write: Arc, -} - -impl ViewPrepassTextures { - pub fn is_first_normal_write(&self) -> bool { - self.first_normal_write.fetch_and(false, Ordering::SeqCst) - } - - pub fn is_first_motion_vectors_write(&self) -> bool { - self.first_motion_vectors_write - .fetch_and(false, Ordering::SeqCst) - } - - pub fn is_first_deferred_write(&self) -> bool { - self.first_deferred_write.fetch_and(false, Ordering::SeqCst) - } } /// Opaque phase of the 3D prepass. diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index 66dd55f012e3f..7c3b6cf0b8edd 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -1,6 +1,7 @@ use bevy_ecs::prelude::*; use bevy_ecs::query::QueryItem; use bevy_render::render_graph::ViewNode; +use bevy_render::view; use bevy_render::{ camera::ExtractedCamera, prelude::Color, @@ -103,20 +104,7 @@ impl ViewNode for PrepassNode { let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("prepass"), color_attachments: &color_attachments, - depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { - view: &view_depth_texture.view, - depth_ops: Some(Operations { - load: if view_depth_texture.is_first_write() { - // NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections. - camera_3d.depth_load_op.clone() - } else { - Camera3dDepthLoadOp::Load - } - .into(), - store: true, - }), - stencil_ops: None, - }), + depth_stencil_attachment: Some(view_depth_texture.attachment.get_attachment(true)), }); if let Some(viewport) = camera.viewport.as_ref() { render_pass.set_camera_viewport(viewport); diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index a1144ba2a72ab..1dada9d994224 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -55,16 +55,17 @@ pub struct DepthAttachment { } impl DepthAttachment { - pub fn new(view: TextureView, clear_value: f32) -> Self { + pub fn new(view: TextureView, clear_value: Option) -> Self { Self { view, - clear_value, - is_first_call: Arc::new(AtomicBool::new(true)), + clear_value: clear_value.unwrap(), + is_first_call: Arc::new(AtomicBool::new(clear_value.is_some())), } } /// Get this texture view as an attachment. The attachment will be cleared with a value of - /// `clear_value` if this is the first time calling this function, otherwise the it will be loaded. + /// `clear_value` if this is the first time calling this function, and a clear value was provided, + /// otherwise the it will be loaded. pub fn get_attachment(&self, store: bool) -> RenderPassDepthStencilAttachment { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index efc8077dc3bba..0b49779b7f0fc 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -14,7 +14,7 @@ use crate::{ render_phase::ViewRangefinder3d, render_resource::{DynamicUniformBuffer, ShaderType, Texture, TextureView}, renderer::{RenderDevice, RenderQueue}, - texture::{BevyDefault, CachedTexture, TextureCache}, + texture::{BevyDefault, CachedTexture, DepthAttachment, TextureCache}, Render, RenderApp, RenderSet, }; use bevy_app::{App, Plugin}; @@ -343,16 +343,14 @@ impl ViewTarget { #[derive(Component)] pub struct ViewDepthTexture { pub texture: Texture, - pub view: TextureView, - first_write: Arc, + pub attachment: DepthAttachment, } impl ViewDepthTexture { - pub fn new(texture: CachedTexture) -> Self { + pub fn new(texture: CachedTexture, clear_value: Option) -> Self { Self { texture: texture.texture, - view: texture.default_view, - first_write: Arc::new(AtomicBool::new(true)), + attachment: DepthAttachment::new(texture.default_view, clear_value), } } } @@ -531,7 +529,6 @@ fn prepare_view_targets( main_texture: main_textures.main_texture.clone(), out_texture: out_texture_view.clone(), out_texture_format: out_texture_format.add_srgb_suffix(), - first_write: Arc::new(AtomicBool::new(true)), }); } } From 52c429daa2d7470a4460216c1dd030afa1b66689 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 20 Nov 2023 23:26:02 -0500 Subject: [PATCH 09/36] Make ColorAttachment hold CachedTexture directly --- .../bevy_render/src/texture/texture_attachment.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 1dada9d994224..392b3b76df561 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -7,18 +7,22 @@ use wgpu::{ LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, TextureView, }; -/// A wrapper for a [TextureView] that is used as a [RenderPassColorAttachment]. +/// A wrapper for a [CachedTexture] that is used as a [RenderPassColorAttachment]. pub struct ColorAttachment { - pub view: TextureView, + pub texture: CachedTexture, pub resolve_target: Option, clear_color: Color, is_first_call: Arc, } impl ColorAttachment { - pub fn new(view: TextureView, resolve_target: Option, clear_color: Color) -> Self { + pub fn new( + texture: CachedTexture, + resolve_target: Option, + clear_color: Color, + ) -> Self { Self { - view, + texture, resolve_target, clear_color, is_first_call: Arc::new(AtomicBool::new(true)), @@ -33,7 +37,7 @@ impl ColorAttachment { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); RenderPassColorAttachment { - view: &self.view, + view: &self.texture.default_view, resolve_target: self.resolve_target.as_ref(), ops: Operations { load: if first_call { From 66aeff0050a0248b422c64daa7511df6f7ab4318 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Mon, 20 Nov 2023 23:27:36 -0500 Subject: [PATCH 10/36] WIP --- crates/bevy_render/src/view/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 0b49779b7f0fc..8bcdf5ea596e7 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -426,8 +426,8 @@ pub fn prepare_view_uniforms( #[derive(Clone)] struct MainTargetTextures { - a: CachedTexture, - b: CachedTexture, + a: ColorAttachment, + b: ColorAttachment, sampled: Option, /// 0 represents `main_textures.a`, 1 represents `main_textures.b` /// This is shared across view targets with the same render target From d89d118aefc9d02bf303810b9d09711739266b4e Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Wed, 22 Nov 2023 11:48:53 -0500 Subject: [PATCH 11/36] WIP --- crates/bevy_core_pipeline/src/core_2d/camera_2d.rs | 4 +--- crates/bevy_core_pipeline/src/core_3d/camera_3d.rs | 3 --- crates/bevy_core_pipeline/src/lib.rs | 12 +++++------- crates/bevy_render/src/camera/camera.rs | 7 ++++++- .../src => bevy_render/src/camera}/clear_color.rs | 2 +- crates/bevy_render/src/camera/mod.rs | 6 ++++++ crates/bevy_render/src/texture/texture_attachment.rs | 10 +++++----- crates/bevy_render/src/view/mod.rs | 4 ++-- 8 files changed, 26 insertions(+), 22 deletions(-) rename crates/{bevy_core_pipeline/src => bevy_render/src/camera}/clear_color.rs (95%) diff --git a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs index fcd794029b04f..4f9bcd7c9a55e 100644 --- a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs +++ b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs @@ -15,9 +15,7 @@ use bevy_transform::prelude::{GlobalTransform, Transform}; #[derive(Component, Default, Reflect, Clone, ExtractComponent)] #[extract_component_filter(With)] #[reflect(Component)] -pub struct Camera2d { - pub clear_color: ClearColorConfig, -} +pub struct Camera2d {} #[derive(Bundle)] pub struct Camera2dBundle { diff --git a/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs b/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs index 33579994c9aca..b3aee03e32a86 100644 --- a/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs +++ b/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs @@ -19,8 +19,6 @@ use serde::{Deserialize, Serialize}; #[extract_component_filter(With)] #[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. @@ -55,7 +53,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, diff --git a/crates/bevy_core_pipeline/src/lib.rs b/crates/bevy_core_pipeline/src/lib.rs index ec119ad5ae551..02eb322991ddd 100644 --- a/crates/bevy_core_pipeline/src/lib.rs +++ b/crates/bevy_core_pipeline/src/lib.rs @@ -48,13 +48,13 @@ use crate::{ fullscreen_vertex_shader::FULLSCREEN_SHADER_HANDLE, fxaa::FxaaPlugin, msaa_writeback::MsaaWritebackPlugin, - prepass::{DepthPrepass, NormalPrepass}, + prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass}, tonemapping::TonemappingPlugin, upscaling::UpscalingPlugin, }; use bevy_app::{App, Plugin}; use bevy_asset::load_internal_asset; -use bevy_render::{extract_resource::ExtractResourcePlugin, prelude::Shader}; +use bevy_render::prelude::Shader; #[derive(Default)] pub struct CorePipelinePlugin; @@ -68,13 +68,11 @@ impl Plugin for CorePipelinePlugin { Shader::from_wgsl ); - app.register_type::() - .register_type::() - .register_type::() + app.register_type::() .register_type::() - .init_resource::() + .register_type::() + .register_type::() .add_plugins(( - ExtractResourcePlugin::::default(), Core2dPlugin, Core3dPlugin, CopyDeferredLightingIdPlugin, diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index be6349689b7cb..72f74abb26cc4 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -30,7 +30,7 @@ use bevy_window::{ use std::{borrow::Cow, ops::Range}; use wgpu::{BlendState, LoadOp, TextureFormat}; -use super::Projection; +use super::{ClearColorConfig, Projection}; /// Render viewport configuration for the [`Camera`] component. /// @@ -116,6 +116,8 @@ pub struct Camera { /// "write their results on top" of previous camera results, and include them as a part of their render results. This is enabled by default to ensure /// cameras with MSAA enabled layer their results in the same way as cameras without MSAA enabled by default. pub msaa_writeback: bool, + /// The clear color operation to perform on the render target. + pub clear_color: ClearColorConfig, } impl Default for Camera { @@ -129,6 +131,7 @@ impl Default for Camera { output_mode: Default::default(), hdr: false, msaa_writeback: true, + clear_color: Default::default(), } } } @@ -631,6 +634,7 @@ pub struct ExtractedCamera { pub order: isize, pub output_mode: CameraOutputMode, pub msaa_writeback: bool, + pub clear_color: ClearColorConfig, pub sorted_camera_index_for_target: usize, } @@ -700,6 +704,7 @@ pub fn extract_cameras( order: camera.order, output_mode: camera.output_mode, msaa_writeback: camera.msaa_writeback, + clear_color: camera.clear_color, // this will be set in sort_cameras sorted_camera_index_for_target: 0, }, diff --git a/crates/bevy_core_pipeline/src/clear_color.rs b/crates/bevy_render/src/camera/clear_color.rs similarity index 95% rename from crates/bevy_core_pipeline/src/clear_color.rs rename to crates/bevy_render/src/camera/clear_color.rs index 9d1ce4c5dc787..aaa39972ef37c 100644 --- a/crates/bevy_core_pipeline/src/clear_color.rs +++ b/crates/bevy_render/src/camera/clear_color.rs @@ -1,7 +1,7 @@ +use crate::{color::Color, extract_resource::ExtractResource}; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::prelude::*; use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; -use bevy_render::{color::Color, extract_resource::ExtractResource}; use serde::{Deserialize, Serialize}; /// For a camera, specifies the color used to clear the viewport before rendering. diff --git a/crates/bevy_render/src/camera/mod.rs b/crates/bevy_render/src/camera/mod.rs index 2a92ff159692c..2796fb36e5f53 100644 --- a/crates/bevy_render/src/camera/mod.rs +++ b/crates/bevy_render/src/camera/mod.rs @@ -1,11 +1,13 @@ #[allow(clippy::module_inception)] mod camera; mod camera_driver_node; +mod clear_color; mod manual_texture_view; mod projection; pub use camera::*; pub use camera_driver_node::*; +pub use clear_color::*; pub use manual_texture_view::*; pub use projection::*; @@ -27,12 +29,16 @@ impl Plugin for CameraPlugin { .register_type::() .register_type::() .register_type::() + .register_type::() + .register_type::() .init_resource::() + .init_resource::() .add_plugins(( CameraProjectionPlugin::::default(), CameraProjectionPlugin::::default(), CameraProjectionPlugin::::default(), ExtractResourcePlugin::::default(), + ExtractResourcePlugin::::default(), )); if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 392b3b76df561..2fb260b943cb6 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -1,13 +1,13 @@ -use crate::prelude::Color; +use super::CachedTexture; +use crate::{prelude::Color, render_resource::TextureView}; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; -use wgpu::{ - LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, TextureView, -}; +use wgpu::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment}; /// A wrapper for a [CachedTexture] that is used as a [RenderPassColorAttachment]. +#[derive(Clone)] pub struct ColorAttachment { pub texture: CachedTexture, pub resolve_target: Option, @@ -38,7 +38,7 @@ impl ColorAttachment { RenderPassColorAttachment { view: &self.texture.default_view, - resolve_target: self.resolve_target.as_ref(), + resolve_target: self.resolve_target.as_deref(), ops: Operations { load: if first_call { LoadOp::Clear(self.clear_color.into()) diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 8bcdf5ea596e7..470a22c139dc1 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -14,7 +14,7 @@ use crate::{ render_phase::ViewRangefinder3d, render_resource::{DynamicUniformBuffer, ShaderType, Texture, TextureView}, renderer::{RenderDevice, RenderQueue}, - texture::{BevyDefault, CachedTexture, DepthAttachment, TextureCache}, + texture::{BevyDefault, CachedTexture, ColorAttachment, DepthAttachment, TextureCache}, Render, RenderApp, RenderSet, }; use bevy_app::{App, Plugin}; @@ -24,7 +24,7 @@ use bevy_reflect::Reflect; use bevy_transform::components::GlobalTransform; use bevy_utils::HashMap; use std::sync::{ - atomic::{AtomicBool, AtomicUsize, Ordering}, + atomic::{AtomicUsize, Ordering}, Arc, }; use wgpu::{ From 50dc55fea8d6ff33b6ca9899bc310ec702056e75 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Wed, 22 Nov 2023 12:45:53 -0500 Subject: [PATCH 12/36] WIP --- crates/bevy_core_pipeline/src/bloom/mod.rs | 7 +- .../src/core_2d/camera_2d.rs | 5 +- .../src/core_2d/main_pass_2d_node.rs | 26 ++---- .../src/core_3d/camera_3d.rs | 5 +- .../src/core_3d/main_opaque_pass_3d_node.rs | 29 ++---- .../core_3d/main_transmissive_pass_3d_node.rs | 20 +---- .../core_3d/main_transparent_pass_3d_node.rs | 29 ++---- crates/bevy_core_pipeline/src/core_3d/mod.rs | 24 +++-- .../bevy_core_pipeline/src/deferred/node.rs | 84 ++++++----------- crates/bevy_core_pipeline/src/lib.rs | 3 - .../bevy_core_pipeline/src/msaa_writeback.rs | 13 ++- crates/bevy_core_pipeline/src/prepass/mod.rs | 19 ++-- crates/bevy_core_pipeline/src/prepass/node.rs | 44 ++------- crates/bevy_core_pipeline/src/taa/mod.rs | 4 +- crates/bevy_render/src/camera/camera.rs | 2 +- .../src/texture/texture_attachment.rs | 27 +++++- crates/bevy_render/src/view/mod.rs | 90 ++++++++++--------- 17 files changed, 156 insertions(+), 275 deletions(-) diff --git a/crates/bevy_core_pipeline/src/bloom/mod.rs b/crates/bevy_core_pipeline/src/bloom/mod.rs index 4c0d8ebf8f9cd..1d839ceabccb9 100644 --- a/crates/bevy_core_pipeline/src/bloom/mod.rs +++ b/crates/bevy_core_pipeline/src/bloom/mod.rs @@ -261,12 +261,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: true, - }, - ))], + color_attachments: &[Some(view_target.get_unsampled_color_attachment())], depth_stencil_attachment: None, }); upsampling_final_pass.set_render_pipeline(upsampling_final_pipeline); diff --git a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs index 4f9bcd7c9a55e..1971f31b55a33 100644 --- a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs +++ b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs @@ -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::{ diff --git a/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs index 708193524b70a..65d27946c5e3a 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs @@ -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}, + render_resource::RenderPassDescriptor, renderer::RenderContext, view::{ExtractedView, ViewTarget}, }; @@ -20,7 +17,6 @@ pub struct MainPass2dNode { &'static ExtractedCamera, &'static RenderPhase, &'static ViewTarget, - &'static Camera2d, ), With, >, @@ -46,7 +42,7 @@ impl Node for MainPass2dNode { world: &World, ) -> Result<(), NodeRunError> { let view_entity = graph.view_entity(); - let (camera, transparent_phase, target, camera_2d) = + let (camera, transparent_phase, target) = if let Ok(result) = self.query.get_manual(world, view_entity) { result } else { @@ -59,16 +55,7 @@ impl Node for MainPass2dNode { 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::().0.into()) - } - ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()), - ClearColorConfig::None => LoadOp::Load, - }, - store: true, - }))], + color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: None, }); @@ -87,10 +74,7 @@ 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: true, - }))], + color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: None, }; diff --git a/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs b/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs index b3aee03e32a86..999aaa4d4f777 100644 --- a/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs +++ b/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs @@ -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::{ diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index bf807879c5b59..bfc3aee9ad923 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -1,6 +1,5 @@ use crate::{ - clear_color::{ClearColor, ClearColorConfig}, - core_3d::{Camera3d, Opaque3d}, + core_3d::Opaque3d, skybox::{SkyboxBindGroup, SkyboxPipelineId}, }; use bevy_ecs::{prelude::*, query::QueryItem}; @@ -8,16 +7,14 @@ use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_phase::RenderPhase, - render_resource::{ - LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor, - }, + render_resource::{PipelineCache, RenderPassDescriptor}, 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)] @@ -27,7 +24,6 @@ impl ViewNode for MainOpaquePass3dNode { &'static ExtractedCamera, &'static RenderPhase, &'static RenderPhase, - &'static Camera3d, &'static ViewTarget, &'static ViewDepthTexture, Option<&'static SkyboxPipelineId>, @@ -43,7 +39,6 @@ impl ViewNode for MainOpaquePass3dNode { camera, opaque_phase, alpha_mask_phase, - camera_3d, target, depth, skybox_pipeline, @@ -52,16 +47,6 @@ impl ViewNode for MainOpaquePass3dNode { ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { - let load = if target.is_first_write() { - match camera_3d.clear_color { - ClearColorConfig::Default => LoadOp::Clear(world.resource::().0.into()), - ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()), - ClearColorConfig::None => LoadOp::Load, - } - } else { - LoadOp::Load - }; - // Run the opaque pass, sorted front-to-back // NOTE: Scoped to drop the mutable borrow of render_context #[cfg(feature = "trace")] @@ -70,12 +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: true }), - )], - depth_stencil_attachment: Some(depth.attachment.get_attachment(true)), + color_attachments: &[Some(target.get_color_attachment())], + depth_stencil_attachment: Some(depth.get_attachment(true)), }); if let Some(viewport) = camera.viewport.as_ref() { diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs index 18c04e0d5a828..47035af76bc73 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs @@ -5,9 +5,7 @@ use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_phase::RenderPhase, - render_resource::{ - Extent3d, LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor, - }, + render_resource::{Extent3d, RenderPassDescriptor}, renderer::RenderContext, view::{ViewDepthTexture, ViewTarget}, }; @@ -44,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: true, - }))], - 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: true, - }), - stencil_ops: None, - }), + color_attachments: &[Some(target.get_color_attachment())], + depth_stencil_attachment: Some(depth.get_attachment(true)), }; // Run the transmissive pass, sorted back-to-front diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs index ce5a2127f1d44..1dde1e94601a9 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs @@ -4,7 +4,7 @@ use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_phase::RenderPhase, - render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor}, + render_resource::RenderPassDescriptor, renderer::RenderContext, view::{ViewDepthTexture, ViewTarget}, }; @@ -39,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: true, - }))], - 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: true, - }), - 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(true)), }); if let Some(viewport) = camera.viewport.as_ref() { diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index a585dfcd7c65e..132b5c9313ac2 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -32,11 +32,7 @@ pub const CORE_3D: &str = graph::NAME; // PERF: vulkan docs recommend using 24 bit depth for better performance pub const CORE_3D_DEPTH_FORMAT: TextureFormat = TextureFormat::Depth32Float; -use std::{ - cmp::Reverse, - ops::Range, - sync::{atomic::AtomicBool, Arc}, -}; +use std::{cmp::Reverse, ops::Range}; pub use camera_3d::*; pub use main_opaque_pass_3d_node::*; @@ -46,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}, @@ -58,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, }; @@ -830,15 +827,16 @@ 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, - first_normal_write: Arc::new(AtomicBool::new(true)), - first_motion_vectors_write: Arc::new(AtomicBool::new(true)), - first_deferred_write: Arc::new(AtomicBool::new(true)), }); } } diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 10f3e613cf393..fefb1b1375bfa 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -2,22 +2,19 @@ use bevy_ecs::prelude::*; use bevy_ecs::query::QueryItem; use bevy_render::render_graph::ViewNode; +use bevy_render::texture::ColorAttachment; use bevy_render::{ camera::ExtractedCamera, prelude::Color, render_graph::{NodeRunError, RenderGraphContext}, render_phase::RenderPhase, - render_resource::{ - LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, - RenderPassDescriptor, - }, + render_resource::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor}, renderer::RenderContext, view::ViewDepthTexture, }; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; -use crate::core_3d::{Camera3d, Camera3dDepthLoadOp}; use crate::prepass::ViewPrepassTextures; use super::{AlphaMask3dDeferred, Opaque3dDeferred}; @@ -35,7 +32,6 @@ impl ViewNode for DeferredGBufferPrepassNode { &'static RenderPhase, &'static ViewDepthTexture, &'static ViewPrepassTextures, - &'static Camera3d, ); fn run( @@ -48,7 +44,6 @@ impl ViewNode for DeferredGBufferPrepassNode { alpha_mask_deferred_phase, view_depth_texture, view_prepass_textures, - camera_3d, ): QueryItem, world: &World, ) -> Result<(), NodeRunError> { @@ -59,36 +54,14 @@ impl ViewNode for DeferredGBufferPrepassNode { view_prepass_textures .normal .as_ref() - .map(|view_normals_texture| RenderPassColorAttachment { - view: &view_normals_texture.default_view, - resolve_target: None, - ops: Operations { - load: if view_prepass_textures.is_first_normal_write() { - LoadOp::Clear(Color::BLACK.into()) - } else { - LoadOp::Load - }, - store: true, - }, - }), + .map(|normals_texture| normals_texture.get_attachment()), + ); + color_attachments.push( + view_prepass_textures + .motion_vectors + .as_ref() + .map(|motion_vectors_texture| motion_vectors_texture.get_attachment()), ); - color_attachments.push(view_prepass_textures.motion_vectors.as_ref().map( - |view_motion_vectors_texture| RenderPassColorAttachment { - view: &view_motion_vectors_texture.default_view, - resolve_target: None, - ops: Operations { - load: if view_prepass_textures.is_first_motion_vectors_write() { - // 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 - LoadOp::Clear(Color::BLACK.into()) - } else { - LoadOp::Load - }, - store: true, - }, - }, - )); // If we clear the deferred texture with LoadOp::Clear(Default::default()) we get these errors: // Chrome: GL_INVALID_OPERATION: No defined conversion between clear value and attachment format. @@ -103,25 +76,26 @@ impl ViewNode for DeferredGBufferPrepassNode { ); } - color_attachments.push( - view_prepass_textures - .deferred - .as_ref() - .map(|deferred_texture| RenderPassColorAttachment { - view: &deferred_texture.default_view, + let deferred_attachment = |deferred_texture: &ColorAttachment| { + #[cfg(all(feature = "webgl", target_arch = "wasm32"))] + { + RenderPassColorAttachment { + view: &deferred_texture.texture.default_view, resolve_target: None, ops: Operations { - #[cfg(all(feature = "webgl", target_arch = "wasm32"))] load: LoadOp::Load, - #[cfg(not(all(feature = "webgl", target_arch = "wasm32")))] - load: if view_prepass_textures.is_first_deferred_write() { - LoadOp::Clear(Color::BLACK.into()) - } else { - LoadOp::Load - }, store: true, }, - }), + } + } + #[cfg(not(all(feature = "webgl", target_arch = "wasm32")))] + deferred_texture.get_attachment() + }; + color_attachments.push( + view_prepass_textures + .deferred + .as_ref() + .map(deferred_attachment), ); color_attachments.push( @@ -132,11 +106,7 @@ impl ViewNode for DeferredGBufferPrepassNode { view: &deferred_lighting_pass_id.default_view, resolve_target: None, ops: Operations { - load: if view_prepass_textures.is_first_deferred_write() { - LoadOp::Clear(Color::BLACK.into()) - } else { - LoadOp::Load - }, + load: LoadOp::Clear(Color::BLACK.into()), store: true, }, }), @@ -152,7 +122,7 @@ impl ViewNode for DeferredGBufferPrepassNode { let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("deferred"), color_attachments: &color_attachments, - depth_stencil_attachment: Some(view_depth_texture.attachment.get_attachment(true)), + depth_stencil_attachment: Some(view_depth_texture.get_attachment(true)), }); if let Some(viewport) = camera.viewport.as_ref() { @@ -179,7 +149,7 @@ impl ViewNode for DeferredGBufferPrepassNode { // Copy depth buffer to texture. render_context.command_encoder().copy_texture_to_texture( view_depth_texture.texture.as_image_copy(), - prepass_depth_texture.texture.as_image_copy(), + prepass_depth_texture.texture.texture.as_image_copy(), view_prepass_textures.size, ); } diff --git a/crates/bevy_core_pipeline/src/lib.rs b/crates/bevy_core_pipeline/src/lib.rs index 02eb322991ddd..fe85d078ff212 100644 --- a/crates/bevy_core_pipeline/src/lib.rs +++ b/crates/bevy_core_pipeline/src/lib.rs @@ -2,7 +2,6 @@ pub mod blit; pub mod bloom; -pub mod clear_color; pub mod contrast_adaptive_sharpening; pub mod core_2d; pub mod core_3d; @@ -31,7 +30,6 @@ pub mod experimental { pub mod prelude { #[doc(hidden)] pub use crate::{ - clear_color::ClearColor, core_2d::{Camera2d, Camera2dBundle}, core_3d::{Camera3d, Camera3dBundle}, }; @@ -40,7 +38,6 @@ pub mod prelude { use crate::{ blit::BlitPlugin, bloom::BloomPlugin, - clear_color::{ClearColor, ClearColorConfig}, contrast_adaptive_sharpening::CASPlugin, core_2d::Core2dPlugin, core_3d::Core3dPlugin, diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index d80bc0fce7bc9..5ef509e17ba8a 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -7,6 +7,7 @@ use bevy_app::{App, Plugin}; use bevy_ecs::prelude::*; use bevy_render::{ camera::ExtractedCamera, + color::Color, render_graph::{Node, NodeRunError, RenderGraphApp, RenderGraphContext}, render_resource::BindGroupEntries, renderer::RenderContext, @@ -84,10 +85,14 @@ impl Node for MsaaWritebackNode { // The target's "resolve target" is the "destination" in post_process // We will indirectly write the results to the "destination" using // the MSAA resolve step. - color_attachments: &[Some(target.get_color_attachment(Operations { - load: LoadOp::Clear(Default::default()), - store: true, - }))], + color_attachments: &[Some(RenderPassColorAttachment { + view: todo!("What goes here?"), + resolve_target: Some(&post_process.destination), + ops: Operations { + load: LoadOp::Clear(Color::BLACK.into()), + store: true, + }, + })], depth_stencil_attachment: None, }; diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index f87c64038e4ab..f4d11d0d4c9e4 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -27,21 +27,14 @@ pub mod node; -use std::{ - cmp::Reverse, - ops::Range, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, -}; +use std::{cmp::Reverse, ops::Range}; use bevy_ecs::prelude::*; use bevy_reflect::Reflect; use bevy_render::{ render_phase::{CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem}, render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat}, - texture::CachedTexture, + texture::{CachedTexture, ColorAttachment}, }; use bevy_utils::{nonmax::NonMaxU32, FloatOrd}; @@ -73,16 +66,16 @@ pub struct DeferredPrepass; pub struct ViewPrepassTextures { /// The depth texture generated by the prepass. /// Exists only if [`DepthPrepass`] is added to the [`ViewTarget`](bevy_render::view::ViewTarget) - pub depth: Option, + pub depth: Option, /// The normals texture generated by the prepass. /// Exists only if [`NormalPrepass`] is added to the [`ViewTarget`](bevy_render::view::ViewTarget) - pub normal: Option, + pub normal: Option, /// The motion vectors texture generated by the prepass. /// Exists only if [`MotionVectorPrepass`] is added to the `ViewTarget` - pub motion_vectors: Option, + pub motion_vectors: Option, /// The deferred gbuffer generated by the deferred pass. /// Exists only if [`DeferredPrepass`] is added to the `ViewTarget` - pub deferred: Option, + pub deferred: Option, /// A texture that specifies the deferred lighting pass id for a material. /// Exists only if [`DeferredPrepass`] is added to the `ViewTarget` pub deferred_lighting_pass_id: Option, diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index 7c3b6cf0b8edd..903c4c4a76c38 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -1,24 +1,17 @@ use bevy_ecs::prelude::*; use bevy_ecs::query::QueryItem; use bevy_render::render_graph::ViewNode; -use bevy_render::view; use bevy_render::{ camera::ExtractedCamera, - prelude::Color, render_graph::{NodeRunError, RenderGraphContext}, render_phase::RenderPhase, - render_resource::{ - LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, - RenderPassDescriptor, - }, + render_resource::RenderPassDescriptor, renderer::RenderContext, view::ViewDepthTexture, }; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; -use crate::core_3d::{Camera3d, Camera3dDepthLoadOp}; - use super::{AlphaMask3dPrepass, DeferredPrepass, Opaque3dPrepass, ViewPrepassTextures}; /// Render node used by the prepass. @@ -30,7 +23,6 @@ pub struct PrepassNode; impl ViewNode for PrepassNode { type ViewQuery = ( &'static ExtractedCamera, - &'static Camera3d, &'static RenderPhase, &'static RenderPhase, &'static ViewDepthTexture, @@ -44,7 +36,6 @@ impl ViewNode for PrepassNode { render_context: &mut RenderContext, ( camera, - camera_3d, opaque_prepass_phase, alpha_mask_prepass_phase, view_depth_texture, @@ -59,36 +50,11 @@ impl ViewNode for PrepassNode { view_prepass_textures .normal .as_ref() - .map(|view_normals_texture| RenderPassColorAttachment { - view: &view_normals_texture.default_view, - resolve_target: None, - ops: Operations { - load: if view_prepass_textures.is_first_normal_write() { - LoadOp::Clear(Color::BLACK.into()) - } else { - LoadOp::Load - }, - store: true, - }, - }), + .map(|normals_texture| normals_texture.get_attachment()), view_prepass_textures .motion_vectors .as_ref() - .map(|view_motion_vectors_texture| RenderPassColorAttachment { - view: &view_motion_vectors_texture.default_view, - resolve_target: None, - ops: Operations { - load: if view_prepass_textures.is_first_motion_vectors_write() { - // 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 - LoadOp::Clear(Color::BLACK.into()) - } else { - LoadOp::Load - }, - store: true, - }, - }), + .map(|motion_vectors_texture| motion_vectors_texture.get_attachment()), // Use None in place of Deferred attachments None, None, @@ -104,7 +70,7 @@ impl ViewNode for PrepassNode { let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("prepass"), color_attachments: &color_attachments, - depth_stencil_attachment: Some(view_depth_texture.attachment.get_attachment(true)), + depth_stencil_attachment: Some(view_depth_texture.get_attachment(true)), }); if let Some(viewport) = camera.viewport.as_ref() { render_pass.set_camera_viewport(viewport); @@ -131,7 +97,7 @@ impl ViewNode for PrepassNode { // Copy depth buffer to texture render_context.command_encoder().copy_texture_to_texture( view_depth_texture.texture.as_image_copy(), - prepass_depth_texture.texture.as_image_copy(), + prepass_depth_texture.texture.texture.as_image_copy(), view_prepass_textures.size, ); } diff --git a/crates/bevy_core_pipeline/src/taa/mod.rs b/crates/bevy_core_pipeline/src/taa/mod.rs index de4069c9abe7d..455b42b987831 100644 --- a/crates/bevy_core_pipeline/src/taa/mod.rs +++ b/crates/bevy_core_pipeline/src/taa/mod.rs @@ -206,8 +206,8 @@ impl ViewNode for TemporalAntiAliasNode { &BindGroupEntries::sequential(( view_target.source, &taa_history_textures.read.default_view, - &prepass_motion_vectors_texture.default_view, - &prepass_depth_texture.default_view, + &prepass_motion_vectors_texture.texture.default_view, + &prepass_depth_texture.texture.default_view, &pipelines.nearest_sampler, &pipelines.linear_sampler, )), diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 72f74abb26cc4..b6048de20310b 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -704,7 +704,7 @@ pub fn extract_cameras( order: camera.order, output_mode: camera.output_mode, msaa_writeback: camera.msaa_writeback, - clear_color: camera.clear_color, + clear_color: camera.clear_color.clone(), // this will be set in sort_cameras sorted_camera_index_for_target: 0, }, diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 2fb260b943cb6..a52440c5538a2 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -10,7 +10,7 @@ use wgpu::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencil #[derive(Clone)] pub struct ColorAttachment { pub texture: CachedTexture, - pub resolve_target: Option, + pub resolve_target: Option, clear_color: Color, is_first_call: Arc, } @@ -18,7 +18,7 @@ pub struct ColorAttachment { impl ColorAttachment { pub fn new( texture: CachedTexture, - resolve_target: Option, + resolve_target: Option, clear_color: Color, ) -> Self { Self { @@ -38,7 +38,28 @@ impl ColorAttachment { RenderPassColorAttachment { view: &self.texture.default_view, - resolve_target: self.resolve_target.as_deref(), + resolve_target: self.resolve_target.as_ref().map(|t| &*t.default_view), + ops: Operations { + load: if first_call { + LoadOp::Clear(self.clear_color.into()) + } else { + LoadOp::Load + }, + store: true, + }, + } + } + + /// Get this texture view as an attachment, without the resolve target. The attachment will be cleared with + /// a value of `clear_color` if this is the first time calling this function, otherwise the it will be loaded. + /// + /// The returned attachment will always have writing enabled (`store: true`). + pub fn get_unsampled_attachment(&self) -> RenderPassColorAttachment { + let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); + + RenderPassColorAttachment { + view: &self.texture.default_view, + resolve_target: None, ops: Operations { load: if first_call { LoadOp::Clear(self.clear_color.into()) diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 470a22c139dc1..1bb4c06906346 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -6,7 +6,9 @@ pub use visibility::*; pub use window::*; use crate::{ - camera::{ExtractedCamera, ManualTextureViews, MipBias, TemporalJitter}, + camera::{ + ClearColor, ClearColorConfig, ExtractedCamera, ManualTextureViews, MipBias, TemporalJitter, + }, extract_resource::{ExtractResource, ExtractResourcePlugin}, prelude::{Image, Shader}, primitives::Frustum, @@ -28,8 +30,8 @@ use std::sync::{ Arc, }; use wgpu::{ - Color, Extent3d, Operations, RenderPassColorAttachment, TextureDescriptor, TextureDimension, - TextureFormat, TextureUsages, + Extent3d, RenderPassColorAttachment, RenderPassDepthStencilAttachment, TextureDescriptor, + TextureDimension, TextureFormat, TextureUsages, }; pub const VIEW_TYPE_HANDLE: Handle = Handle::weak_from_u128(15421373904451797197); @@ -203,40 +205,30 @@ pub struct PostProcessWrite<'a> { impl ViewTarget { pub const TEXTURE_FORMAT_HDR: TextureFormat = TextureFormat::Rgba16Float; - /// Retrieve this target's color attachment. This will use [`Self::sampled_main_texture_view`] and resolve to [`Self::main_texture`] if - /// the target has sampling enabled. Otherwise it will use [`Self::main_texture`] directly. - pub fn get_color_attachment(&self, ops: Operations) -> RenderPassColorAttachment { - match &self.main_textures.sampled { - Some(CachedTexture { - default_view: sampled_texture_view, - .. - }) => RenderPassColorAttachment { - view: sampled_texture_view, - resolve_target: Some(self.main_texture_view()), - ops, - }, - None => self.get_unsampled_color_attachment(ops), + /// Retrieve this target's main texture's color attachment. + pub fn get_color_attachment(&self) -> RenderPassColorAttachment { + if self.main_texture.load(Ordering::SeqCst) == 0 { + self.main_textures.b.get_attachment() + } else { + self.main_textures.a.get_attachment() } } - /// Retrieve an "unsampled" color attachment using [`Self::main_texture`]. - pub fn get_unsampled_color_attachment( - &self, - ops: Operations, - ) -> RenderPassColorAttachment { - RenderPassColorAttachment { - view: self.main_texture_view(), - resolve_target: None, - ops, + /// Retrieve this target's "unsampled" main texture's color attachment. + pub fn get_unsampled_color_attachment(&self) -> RenderPassColorAttachment { + if self.main_texture.load(Ordering::SeqCst) == 0 { + self.main_textures.b.get_unsampled_attachment() + } else { + self.main_textures.a.get_unsampled_attachment() } } /// The "main" unsampled texture. pub fn main_texture(&self) -> &Texture { if self.main_texture.load(Ordering::SeqCst) == 0 { - &self.main_textures.a.texture + &self.main_textures.a.texture.texture } else { - &self.main_textures.b.texture + &self.main_textures.b.texture.texture } } @@ -248,18 +240,18 @@ impl ViewTarget { /// ahead of time. pub fn main_texture_other(&self) -> &Texture { if self.main_texture.load(Ordering::SeqCst) == 0 { - &self.main_textures.b.texture + &self.main_textures.b.texture.texture } else { - &self.main_textures.a.texture + &self.main_textures.a.texture.texture } } /// The "main" unsampled texture. pub fn main_texture_view(&self) -> &TextureView { if self.main_texture.load(Ordering::SeqCst) == 0 { - &self.main_textures.a.default_view + &self.main_textures.a.texture.default_view } else { - &self.main_textures.b.default_view + &self.main_textures.b.texture.default_view } } @@ -271,16 +263,17 @@ impl ViewTarget { /// ahead of time. pub fn main_texture_other_view(&self) -> &TextureView { if self.main_texture.load(Ordering::SeqCst) == 0 { - &self.main_textures.b.default_view + &self.main_textures.b.texture.default_view } else { - &self.main_textures.a.default_view + &self.main_textures.a.texture.default_view } } /// The "main" sampled texture. pub fn sampled_main_texture(&self) -> Option<&Texture> { self.main_textures - .sampled + .a + .resolve_target .as_ref() .map(|sampled| &sampled.texture) } @@ -288,7 +281,8 @@ impl ViewTarget { /// The "main" sampled texture view. pub fn sampled_main_texture_view(&self) -> Option<&TextureView> { self.main_textures - .sampled + .a + .resolve_target .as_ref() .map(|sampled| &sampled.default_view) } @@ -328,13 +322,13 @@ impl ViewTarget { // if the old main texture is a, then the post processing must write from a to b if old_is_a_main_texture == 0 { PostProcessWrite { - source: &self.main_textures.a.default_view, - destination: &self.main_textures.b.default_view, + source: &self.main_textures.a.texture.default_view, + destination: &self.main_textures.b.texture.default_view, } } else { PostProcessWrite { - source: &self.main_textures.b.default_view, - destination: &self.main_textures.a.default_view, + source: &self.main_textures.b.texture.default_view, + destination: &self.main_textures.a.texture.default_view, } } } @@ -343,7 +337,7 @@ impl ViewTarget { #[derive(Component)] pub struct ViewDepthTexture { pub texture: Texture, - pub attachment: DepthAttachment, + attachment: DepthAttachment, } impl ViewDepthTexture { @@ -353,6 +347,10 @@ impl ViewDepthTexture { attachment: DepthAttachment::new(texture.default_view, clear_value), } } + + pub fn get_attachment(&self, store: bool) -> RenderPassDepthStencilAttachment { + self.attachment.get_attachment(store) + } } pub fn prepare_view_uniforms( @@ -428,7 +426,6 @@ pub fn prepare_view_uniforms( struct MainTargetTextures { a: ColorAttachment, b: ColorAttachment, - sampled: Option, /// 0 represents `main_textures.a`, 1 represents `main_textures.b` /// This is shared across view targets with the same render target main_texture: Arc, @@ -440,6 +437,7 @@ fn prepare_view_targets( windows: Res, images: Res>, msaa: Res, + clear_color_global: Res, render_device: Res, mut texture_cache: ResMut, cameras: Query<(Entity, &ExtractedCamera, &ExtractedView)>, @@ -464,6 +462,11 @@ fn prepare_view_targets( TextureFormat::bevy_default() }; + let clear_color = match camera.clear_color { + ClearColorConfig::Custom(color) => color, + _ => clear_color_global.0, + }; + let main_textures = textures .entry((camera.target.clone(), view.hdr)) .or_insert_with(|| { @@ -516,9 +519,8 @@ fn prepare_view_targets( None }; MainTargetTextures { - a, - b, - sampled, + a: ColorAttachment::new(a, sampled.clone(), clear_color), + b: ColorAttachment::new(b, sampled, clear_color), main_texture: Arc::new(AtomicUsize::new(0)), } }); From 283105a2d352ce8bdc8ae5ac1d075d57c16be293 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:04:24 -0500 Subject: [PATCH 13/36] Fixes --- .../bevy_core_pipeline/src/deferred/node.rs | 32 +++++++++---------- crates/bevy_core_pipeline/src/prepass/mod.rs | 22 ++++++++++++- crates/bevy_pbr/src/deferred/mod.rs | 18 +---------- .../bevy_pbr/src/prepass/prepass_bindings.rs | 21 ++++-------- crates/bevy_pbr/src/render/light.rs | 16 +++------- crates/bevy_pbr/src/ssao/mod.rs | 4 +-- crates/bevy_ui/src/render/render_pass.rs | 7 ++-- 7 files changed, 52 insertions(+), 68 deletions(-) diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index fefb1b1375bfa..227dc628aa770 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -2,7 +2,6 @@ use bevy_ecs::prelude::*; use bevy_ecs::query::QueryItem; use bevy_render::render_graph::ViewNode; -use bevy_render::texture::ColorAttachment; use bevy_render::{ camera::ExtractedCamera, prelude::Color, @@ -76,26 +75,25 @@ impl ViewNode for DeferredGBufferPrepassNode { ); } - let deferred_attachment = |deferred_texture: &ColorAttachment| { - #[cfg(all(feature = "webgl", target_arch = "wasm32"))] - { - RenderPassColorAttachment { - view: &deferred_texture.texture.default_view, - resolve_target: None, - ops: Operations { - load: LoadOp::Load, - store: true, - }, - } - } - #[cfg(not(all(feature = "webgl", target_arch = "wasm32")))] - deferred_texture.get_attachment() - }; color_attachments.push( view_prepass_textures .deferred .as_ref() - .map(deferred_attachment), + .map(|deferred_texture| { + #[cfg(all(feature = "webgl", target_arch = "wasm32"))] + { + RenderPassColorAttachment { + view: &deferred_texture.texture.default_view, + resolve_target: None, + ops: Operations { + load: LoadOp::Load, + store: true, + }, + } + } + #[cfg(not(all(feature = "webgl", target_arch = "wasm32")))] + deferred_texture.get_attachment() + }), ); color_attachments.push( diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index f4d11d0d4c9e4..5006c2a3055c9 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -33,7 +33,7 @@ use bevy_ecs::prelude::*; use bevy_reflect::Reflect; use bevy_render::{ render_phase::{CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem}, - render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat}, + render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat, TextureView}, texture::{CachedTexture, ColorAttachment}, }; use bevy_utils::{nonmax::NonMaxU32, FloatOrd}; @@ -83,6 +83,26 @@ pub struct ViewPrepassTextures { pub size: Extent3d, } +impl ViewPrepassTextures { + pub fn depth_view(&self) -> Option<&TextureView> { + self.depth.as_ref().map(|t| &t.texture.default_view) + } + + pub fn normal_view(&self) -> Option<&TextureView> { + self.normal.as_ref().map(|t| &t.texture.default_view) + } + + pub fn motion_vectors_view(&self) -> Option<&TextureView> { + self.motion_vectors + .as_ref() + .map(|t| &t.texture.default_view) + } + + pub fn deferred_view(&self) -> Option<&TextureView> { + self.deferred.as_ref().map(|t| &t.texture.default_view) + } +} + /// Opaque phase of the 3D prepass. /// /// Sorted front-to-back by the z-distance in front of the camera. diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index cf542608f80b2..efb634ba70fe0 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -2,12 +2,10 @@ use crate::{MeshPipeline, MeshViewBindGroup, ScreenSpaceAmbientOcclusionSettings use bevy_app::prelude::*; use bevy_asset::{load_internal_asset, Handle}; use bevy_core_pipeline::{ - clear_color::ClearColorConfig, core_3d, deferred::{ copy_lighting_id::DeferredLightingIdDepthTexture, DEFERRED_LIGHTING_PASS_ID_DEPTH_FORMAT, }, - prelude::{Camera3d, ClearColor}, prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass}, tonemapping::{DebandDither, Tonemapping}, }; @@ -154,7 +152,6 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { &'static MeshViewBindGroup, &'static ViewTarget, &'static DeferredLightingIdDepthTexture, - &'static Camera3d, &'static DeferredLightingPipeline, ); @@ -169,7 +166,6 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { mesh_view_bind_group, target, deferred_lighting_id_depth_texture, - camera_3d, deferred_lighting_pipeline, ): QueryItem, world: &World, @@ -197,21 +193,9 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { &BindGroupEntries::single(deferred_lighting_pass_id_binding), ); - let load = if target.is_first_write() { - match camera_3d.clear_color { - ClearColorConfig::Default => LoadOp::Clear(world.resource::().0.into()), - ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()), - ClearColorConfig::None => LoadOp::Load, - } - } else { - LoadOp::Load - }; - let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("deferred_lighting_pass"), - color_attachments: &[Some( - target.get_color_attachment(Operations { load, store: true }), - )], + color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { view: &deferred_lighting_id_depth_texture.texture.default_view, depth_ops: Some(Operations { diff --git a/crates/bevy_pbr/src/prepass/prepass_bindings.rs b/crates/bevy_pbr/src/prepass/prepass_bindings.rs index b72ddd1e318cd..608c0a5a0fab4 100644 --- a/crates/bevy_pbr/src/prepass/prepass_bindings.rs +++ b/crates/bevy_pbr/src/prepass/prepass_bindings.rs @@ -91,19 +91,12 @@ pub fn get_bindings(prepass_textures: Option<&ViewPrepassTextures>) -> [Option Date: Thu, 28 Dec 2023 20:13:24 -0800 Subject: [PATCH 14/36] Fix rebase --- crates/bevy_ui/src/render/render_pass.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ui/src/render/render_pass.rs b/crates/bevy_ui/src/render/render_pass.rs index bf1562295976d..7c58278d00c6b 100644 --- a/crates/bevy_ui/src/render/render_pass.rs +++ b/crates/bevy_ui/src/render/render_pass.rs @@ -9,7 +9,7 @@ use bevy_ecs::{ use bevy_render::{ render_graph::*, render_phase::*, - render_resource::{CachedRenderPipelineId, LoadOp, Operations, RenderPassDescriptor, StoreOp}, + render_resource::{CachedRenderPipelineId, RenderPassDescriptor}, renderer::*, view::*, }; @@ -74,10 +74,7 @@ impl Node for UiPassNode { }; let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("ui_pass"), - color_attachments: &[Some(target.get_unsampled_color_attachment(Operations { - load: LoadOp::Load, - store: true, - }))], + color_attachments: &[Some(target.get_unsampled_color_attachment())], depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, From 63e8032234111d98070878674aa6131a40568086 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 28 Dec 2023 20:24:42 -0800 Subject: [PATCH 15/36] Small fix --- crates/bevy_render/src/view/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 83a3a1b682022..a7701bdeb58a1 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -209,18 +209,18 @@ impl ViewTarget { /// Retrieve this target's main texture's color attachment. pub fn get_color_attachment(&self) -> RenderPassColorAttachment { if self.main_texture.load(Ordering::SeqCst) == 0 { - self.main_textures.b.get_attachment() - } else { self.main_textures.a.get_attachment() + } else { + self.main_textures.b.get_attachment() } } /// Retrieve this target's "unsampled" main texture's color attachment. pub fn get_unsampled_color_attachment(&self) -> RenderPassColorAttachment { if self.main_texture.load(Ordering::SeqCst) == 0 { - self.main_textures.b.get_unsampled_attachment() - } else { self.main_textures.a.get_unsampled_attachment() + } else { + self.main_textures.b.get_unsampled_attachment() } } From 4e61072f2e5b01807d0c1d936bf2bd315f6c817f Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 28 Dec 2023 20:47:04 -0800 Subject: [PATCH 16/36] WIP MSAA fix --- .../bevy_core_pipeline/src/msaa_writeback.rs | 8 +++++-- .../src/texture/texture_attachment.rs | 24 +++++++++++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index 01fb40e1c80f6..1faec82d0aab8 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -67,6 +67,10 @@ impl Node for MsaaWritebackNode { render_context: &mut RenderContext, world: &World, ) -> Result<(), NodeRunError> { + if *world.resource::() == Msaa::Off { + return Ok(()); + } + let view_entity = graph.view_entity(); if let Ok((target, blit_pipeline_id)) = self.cameras.get_manual(world, view_entity) { let blit_pipeline = world.resource::(); @@ -82,11 +86,11 @@ impl Node for MsaaWritebackNode { let pass_descriptor = RenderPassDescriptor { label: Some("msaa_writeback"), - // The target's "resolve target" is the "destination" in post_process + // The target's "resolve target" is the "destination" in post_process. // We will indirectly write the results to the "destination" using // the MSAA resolve step. color_attachments: &[Some(RenderPassColorAttachment { - view: todo!("What goes here?"), + view: target.sampled_main_texture_view().unwrap(), resolve_target: Some(&post_process.destination), ops: Operations { load: LoadOp::Clear(Color::BLACK.into()), diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 80352050fe2c3..60c925c954518 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -38,17 +38,21 @@ impl ColorAttachment { pub fn get_attachment(&self) -> RenderPassColorAttachment { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); - RenderPassColorAttachment { - view: &self.texture.default_view, - resolve_target: self.resolve_target.as_ref().map(|t| &*t.default_view), - ops: Operations { - load: if first_call { - LoadOp::Clear(self.clear_color.into()) - } else { - LoadOp::Load + if let Some(resolve_target) = self.resolve_target.as_ref() { + RenderPassColorAttachment { + view: &resolve_target.default_view, + resolve_target: Some(&self.texture.default_view), + ops: Operations { + load: if first_call { + LoadOp::Clear(self.clear_color.into()) + } else { + LoadOp::Load + }, + store: StoreOp::Store, }, - store: StoreOp::Store, - }, + } + } else { + self.get_unsampled_attachment() } } From badd57241eb293db0a4bd103f6c846bd76ebdf98 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 28 Dec 2023 21:08:05 -0800 Subject: [PATCH 17/36] Fixes --- .../bevy_core_pipeline/src/msaa_writeback.rs | 2 ++ .../src/texture/texture_attachment.rs | 14 +++++++------- crates/bevy_render/src/view/mod.rs | 18 ++++++++++-------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index 1faec82d0aab8..77c9bcf2de979 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -61,6 +61,7 @@ impl Node for MsaaWritebackNode { fn update(&mut self, world: &mut World) { self.cameras.update_archetypes(world); } + fn run( &self, graph: &mut RenderGraphContext, @@ -116,6 +117,7 @@ impl Node for MsaaWritebackNode { render_pass.set_bind_group(0, &bind_group, &[]); render_pass.draw(0..3, 0..1); } + Ok(()) } } diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 60c925c954518..72384b8e80949 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -32,13 +32,13 @@ impl ColorAttachment { } /// Get this texture view as an attachment. The attachment will be cleared with a value of - /// `clear_color` if this is the first time calling this function, otherwise the it will be loaded. + /// `clear_color` if this is the first time calling this function, otherwise it will be loaded. /// - /// The returned attachment will always have writing enabled (`store: true`). + /// The returned attachment will always have writing enabled (`store: StopOp::Load`). pub fn get_attachment(&self) -> RenderPassColorAttachment { - let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); - if let Some(resolve_target) = self.resolve_target.as_ref() { + let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); + RenderPassColorAttachment { view: &resolve_target.default_view, resolve_target: Some(&self.texture.default_view), @@ -57,9 +57,9 @@ impl ColorAttachment { } /// Get this texture view as an attachment, without the resolve target. The attachment will be cleared with - /// a value of `clear_color` if this is the first time calling this function, otherwise the it will be loaded. + /// a value of `clear_color` if this is the first time calling this function, otherwise it will be loaded. /// - /// The returned attachment will always have writing enabled (`store: true`). + /// The returned attachment will always have writing enabled (`store: StopOp::Load`). pub fn get_unsampled_attachment(&self) -> RenderPassColorAttachment { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); @@ -96,7 +96,7 @@ impl DepthAttachment { /// Get this texture view as an attachment. The attachment will be cleared with a value of /// `clear_value` if this is the first time calling this function, and a clear value was provided, - /// otherwise the it will be loaded. + /// otherwise it will be loaded. pub fn get_attachment(&self, store: bool) -> RenderPassDepthStencilAttachment { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index a7701bdeb58a1..e32d70117d2c5 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -470,7 +470,7 @@ fn prepare_view_targets( _ => clear_color_global.0, }; - let main_textures = textures + let (a, b, sampled) = textures .entry((camera.target.clone(), view.hdr)) .or_insert_with(|| { let descriptor = TextureDescriptor { @@ -521,17 +521,19 @@ fn prepare_view_targets( } else { None }; - MainTargetTextures { - a: ColorAttachment::new(a, sampled.clone(), clear_color), - b: ColorAttachment::new(b, sampled, clear_color), - main_texture: Arc::new(AtomicUsize::new(0)), - } + (a, b, sampled) }); + let main_textures = MainTargetTextures { + a: ColorAttachment::new(a.clone(), sampled.clone(), clear_color), + b: ColorAttachment::new(b.clone(), sampled.clone(), clear_color), + main_texture: Arc::new(AtomicUsize::new(0)), + }; + commands.entity(entity).insert(ViewTarget { - main_textures: main_textures.clone(), - main_texture_format, main_texture: main_textures.main_texture.clone(), + main_textures, + main_texture_format, out_texture: out_texture_view.clone(), out_texture_format: out_texture_format.add_srgb_suffix(), }); From 7e7b9a7f529b75d2fba56e3b7120d559136ac0ee Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 28 Dec 2023 21:18:15 -0800 Subject: [PATCH 18/36] Fix post processing --- crates/bevy_render/src/texture/texture_attachment.rs | 4 ++++ crates/bevy_render/src/view/mod.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 72384b8e80949..baa6fc05a8eed 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -76,6 +76,10 @@ impl ColorAttachment { }, } } + + pub(crate) fn mark_as_cleared(&self) { + self.is_first_call.store(false, Ordering::SeqCst); + } } /// A wrapper for a [TextureView] that is used as a depth-only [RenderPassDepthStencilAttachment]. diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index e32d70117d2c5..cf95e928f8af9 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -322,11 +322,13 @@ impl ViewTarget { let old_is_a_main_texture = self.main_texture.fetch_xor(1, Ordering::SeqCst); // if the old main texture is a, then the post processing must write from a to b if old_is_a_main_texture == 0 { + self.main_textures.b.mark_as_cleared(); PostProcessWrite { source: &self.main_textures.a.texture.default_view, destination: &self.main_textures.b.texture.default_view, } } else { + self.main_textures.a.mark_as_cleared(); PostProcessWrite { source: &self.main_textures.b.texture.default_view, destination: &self.main_textures.a.texture.default_view, From dceab7a939a6875c9848670883dcc9757db81977 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Fri, 29 Dec 2023 10:38:57 -0800 Subject: [PATCH 19/36] Address PR feedback --- .../src/core_2d/main_pass_2d_node.rs | 13 ++++++------- .../src/core_3d/main_opaque_pass_3d_node.rs | 4 ++-- .../src/core_3d/main_transmissive_pass_3d_node.rs | 4 ++-- .../src/core_3d/main_transparent_pass_3d_node.rs | 4 ++-- crates/bevy_core_pipeline/src/deferred/node.rs | 2 +- crates/bevy_core_pipeline/src/msaa_writeback.rs | 1 + crates/bevy_core_pipeline/src/prepass/node.rs | 3 ++- crates/bevy_pbr/src/render/light.rs | 2 +- .../bevy_render/src/texture/texture_attachment.rs | 15 ++++++--------- crates/bevy_render/src/view/mod.rs | 6 +++--- 10 files changed, 26 insertions(+), 28 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs index 21cf3461f2520..7b926dee296bf 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs @@ -42,13 +42,12 @@ impl Node for MainPass2dNode { world: &World, ) -> Result<(), NodeRunError> { let view_entity = graph.view_entity(); - let (camera, transparent_phase, target) = - if let Ok(result) = self.query.get_manual(world, view_entity) { - result - } else { - // no target - return Ok(()); - }; + 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(); diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index ebabde0c051a9..dc0e969d3b2e9 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -7,7 +7,7 @@ use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_phase::RenderPhase, - render_resource::{PipelineCache, RenderPassDescriptor}, + render_resource::{PipelineCache, RenderPassDescriptor, StoreOp}, renderer::RenderContext, view::{ViewDepthTexture, ViewTarget, ViewUniformOffset}, }; @@ -56,7 +56,7 @@ impl ViewNode for MainOpaquePass3dNode { let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("main_opaque_pass_3d"), color_attachments: &[Some(target.get_color_attachment())], - depth_stencil_attachment: Some(depth.get_attachment(true)), + depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)), timestamp_writes: None, occlusion_query_set: None, }); diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs index 51998d5d16038..99ed34397e9cc 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs @@ -5,7 +5,7 @@ use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_phase::RenderPhase, - render_resource::{Extent3d, RenderPassDescriptor}, + render_resource::{Extent3d, RenderPassDescriptor, StoreOp}, renderer::RenderContext, view::{ViewDepthTexture, ViewTarget}, }; @@ -43,7 +43,7 @@ impl ViewNode for MainTransmissivePass3dNode { let render_pass_descriptor = RenderPassDescriptor { label: Some("main_transmissive_pass_3d"), color_attachments: &[Some(target.get_color_attachment())], - depth_stencil_attachment: Some(depth.get_attachment(true)), + depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)), timestamp_writes: None, occlusion_query_set: None, }; diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs index 9e924249daae2..7c86d0de44016 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs @@ -4,7 +4,7 @@ use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_phase::RenderPhase, - render_resource::RenderPassDescriptor, + render_resource::{RenderPassDescriptor, StoreOp}, renderer::RenderContext, view::{ViewDepthTexture, ViewTarget}, }; @@ -46,7 +46,7 @@ impl ViewNode for MainTransparentPass3dNode { // 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(true)), + depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)), timestamp_writes: None, occlusion_query_set: None, }); diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 0f19b018922dc..a3e23e59307a1 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -121,7 +121,7 @@ impl ViewNode for DeferredGBufferPrepassNode { let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("deferred"), color_attachments: &color_attachments, - depth_stencil_attachment: Some(view_depth_texture.get_attachment(true)), + depth_stencil_attachment: Some(view_depth_texture.get_attachment(StoreOp::Store)), timestamp_writes: None, occlusion_query_set: None, }); diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index 77c9bcf2de979..8aa2a659d6e70 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -91,6 +91,7 @@ impl Node for MsaaWritebackNode { // We will indirectly write the results to the "destination" using // the MSAA resolve step. color_attachments: &[Some(RenderPassColorAttachment { + // If MSAA is enabled, then the sampled texture will always exist view: target.sampled_main_texture_view().unwrap(), resolve_target: Some(&post_process.destination), ops: Operations { diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index f4a97a08d6d69..c37af2110a360 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -1,6 +1,7 @@ use bevy_ecs::prelude::*; use bevy_ecs::query::QueryItem; use bevy_render::render_graph::ViewNode; +use bevy_render::render_resource::StoreOp; use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext}, @@ -70,7 +71,7 @@ impl ViewNode for PrepassNode { let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("prepass"), color_attachments: &color_attachments, - depth_stencil_attachment: Some(view_depth_texture.get_attachment(true)), + depth_stencil_attachment: Some(view_depth_texture.get_attachment(StoreOp::Store)), timestamp_writes: None, occlusion_query_set: None, }); diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 29dc851e42a72..f7666f1205321 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -1768,7 +1768,7 @@ impl Node for ShadowPassNode { label: Some(&view_light.pass_name), color_attachments: &[], depth_stencil_attachment: Some( - view_light.depth_attachment.get_attachment(true), + view_light.depth_attachment.get_attachment(StoreOp::Store), ), timestamp_writes: None, occlusion_query_set: None, diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index baa6fc05a8eed..f5f2670cd19ef 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -85,7 +85,7 @@ impl ColorAttachment { /// A wrapper for a [TextureView] that is used as a depth-only [RenderPassDepthStencilAttachment]. pub struct DepthAttachment { pub view: TextureView, - clear_value: f32, + clear_value: Option, is_first_call: Arc, } @@ -93,7 +93,7 @@ impl DepthAttachment { pub fn new(view: TextureView, clear_value: Option) -> Self { Self { view, - clear_value: clear_value.unwrap(), + clear_value, is_first_call: Arc::new(AtomicBool::new(clear_value.is_some())), } } @@ -101,22 +101,19 @@ impl DepthAttachment { /// Get this texture view as an attachment. The attachment will be cleared with a value of /// `clear_value` if this is the first time calling this function, and a clear value was provided, /// otherwise it will be loaded. - pub fn get_attachment(&self, store: bool) -> RenderPassDepthStencilAttachment { + pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); RenderPassDepthStencilAttachment { view: &self.view, depth_ops: Some(Operations { load: if first_call { - LoadOp::Clear(self.clear_value) + // If first_call is true, then a clear value will always have been provided in the constructor + LoadOp::Clear(self.clear_value.unwrap()) } else { LoadOp::Load }, - store: if store { - StoreOp::Store - } else { - StoreOp::Discard - }, + store, }), stencil_ops: None, } diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index cf95e928f8af9..c37b4c3396b1d 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -30,8 +30,8 @@ use std::sync::{ Arc, }; use wgpu::{ - Extent3d, RenderPassColorAttachment, RenderPassDepthStencilAttachment, TextureDescriptor, - TextureDimension, TextureFormat, TextureUsages, + Extent3d, RenderPassColorAttachment, RenderPassDepthStencilAttachment, StoreOp, + TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, }; pub const VIEW_TYPE_HANDLE: Handle = Handle::weak_from_u128(15421373904451797197); @@ -351,7 +351,7 @@ impl ViewDepthTexture { } } - pub fn get_attachment(&self, store: bool) -> RenderPassDepthStencilAttachment { + pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment { self.attachment.get_attachment(store) } } From 1ced9ff401d5cc7205ede234205c7714b5980527 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Fri, 29 Dec 2023 11:11:46 -0800 Subject: [PATCH 20/36] Fix examples --- examples/3d/split_screen.rs | 11 +++++------ examples/3d/two_passes.rs | 7 ++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/examples/3d/split_screen.rs b/examples/3d/split_screen.rs index 1a0f215d6464f..deeb11ca58741 100644 --- a/examples/3d/split_screen.rs +++ b/examples/3d/split_screen.rs @@ -3,8 +3,10 @@ use std::f32::consts::PI; use bevy::{ - core_pipeline::clear_color::ClearColorConfig, pbr::CascadeShadowConfigBuilder, prelude::*, - render::camera::Viewport, window::WindowResized, + pbr::CascadeShadowConfigBuilder, + prelude::*, + render::camera::{ClearColorConfig, Viewport}, + window::WindowResized, }; fn main() { @@ -67,10 +69,7 @@ fn setup( camera: Camera { // Renders the right camera after the left camera, which has a default priority of 0 order: 1, - ..default() - }, - camera_3d: Camera3d { - // don't clear on the second camera because the first camera already cleared the window + // Don't clear on the second camera because the first camera already cleared the window clear_color: ClearColorConfig::None, ..default() }, diff --git a/examples/3d/two_passes.rs b/examples/3d/two_passes.rs index eded9674964da..59ed3c9a3d8c0 100644 --- a/examples/3d/two_passes.rs +++ b/examples/3d/two_passes.rs @@ -1,6 +1,6 @@ //! Renders two 3d passes to the same window from different perspectives. -use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*}; +use bevy::{prelude::*, render::camera::ClearColorConfig}; fn main() { App::new() @@ -47,13 +47,10 @@ fn setup( // camera commands.spawn(Camera3dBundle { transform: Transform::from_xyz(10.0, 10., -5.0).looking_at(Vec3::ZERO, Vec3::Y), - camera_3d: Camera3d { - clear_color: ClearColorConfig::None, - ..default() - }, camera: Camera { // renders after / on top of the main camera order: 1, + clear_color: ClearColorConfig::None, ..default() }, ..default() From 88714b25bc2aac8f42d5711654e75906e933c9e1 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Fri, 29 Dec 2023 13:27:17 -0800 Subject: [PATCH 21/36] Fix depth attachment for niche use cases --- crates/bevy_render/src/texture/texture_attachment.rs | 8 +++++--- crates/bevy_render/src/view/mod.rs | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index f5f2670cd19ef..b7bc117f781b6 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -99,10 +99,12 @@ impl DepthAttachment { } /// Get this texture view as an attachment. The attachment will be cleared with a value of - /// `clear_value` if this is the first time calling this function, and a clear value was provided, - /// otherwise it will be loaded. + /// `clear_value` if this is the first time calling this function with `store` == StoreOp::Store, + /// and a clear value was provided, otherwise it will be loaded. pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment { - let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); + let first_call = self + .is_first_call + .fetch_and(store != StoreOp::Store, Ordering::SeqCst); RenderPassDepthStencilAttachment { view: &self.view, diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index c37b4c3396b1d..af91222152886 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -354,6 +354,10 @@ impl ViewDepthTexture { pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment { self.attachment.get_attachment(store) } + + pub fn view(&self) -> &TextureView { + &self.attachment.view + } } pub fn prepare_view_uniforms( From 6916691cb6de52986562ff0da3f8feb9e2f8ff9d Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Fri, 29 Dec 2023 17:07:40 -0800 Subject: [PATCH 22/36] Update crates/bevy_render/src/texture/texture_attachment.rs Co-authored-by: vero --- crates/bevy_render/src/texture/texture_attachment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index b7bc117f781b6..8212de66ca909 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -59,7 +59,7 @@ impl ColorAttachment { /// Get this texture view as an attachment, without the resolve target. The attachment will be cleared with /// a value of `clear_color` if this is the first time calling this function, otherwise it will be loaded. /// - /// The returned attachment will always have writing enabled (`store: StopOp::Load`). + /// The returned attachment will always have writing enabled (`store: StoreOp::Load`). pub fn get_unsampled_attachment(&self) -> RenderPassColorAttachment { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); From 1c2941583eace256da44fc6ca3ca650dfd0745c4 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Fri, 29 Dec 2023 17:07:48 -0800 Subject: [PATCH 23/36] Update crates/bevy_render/src/texture/texture_attachment.rs Co-authored-by: vero --- crates/bevy_render/src/texture/texture_attachment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 8212de66ca909..38b7d5aa8e0f8 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -34,7 +34,7 @@ impl ColorAttachment { /// Get this texture view as an attachment. The attachment will be cleared with a value of /// `clear_color` if this is the first time calling this function, otherwise it will be loaded. /// - /// The returned attachment will always have writing enabled (`store: StopOp::Load`). + /// The returned attachment will always have writing enabled (`store: StoreOp::Load`). pub fn get_attachment(&self) -> RenderPassColorAttachment { if let Some(resolve_target) = self.resolve_target.as_ref() { let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst); From de5a84f2cbc927de239d79fb87be468ef4acd269 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Fri, 29 Dec 2023 17:10:42 -0800 Subject: [PATCH 24/36] Fix webgl --- .../src/core_3d/main_transparent_pass_3d_node.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs index 7c86d0de44016..c0116ddac9a64 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs @@ -66,10 +66,7 @@ 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: true, - }))], + color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: None, }; From 97536679b2f69a39975b1739647087b49a7a717e Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Fri, 29 Dec 2023 17:13:48 -0800 Subject: [PATCH 25/36] Fix webgl2 for deferred --- crates/bevy_core_pipeline/src/deferred/node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index a3e23e59307a1..72d7d66bbbcfa 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -88,7 +88,7 @@ impl ViewNode for DeferredGBufferPrepassNode { resolve_target: None, ops: Operations { load: LoadOp::Load, - store: true, + store: StoreOp::Store, }, } } From 3117ade0430718b4eca0a85e2b7f858c7e1e23e9 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:19:26 -0800 Subject: [PATCH 26/36] Fix doc links --- crates/bevy_render/src/texture/texture_attachment.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/texture/texture_attachment.rs b/crates/bevy_render/src/texture/texture_attachment.rs index 38b7d5aa8e0f8..908d2e3a2869a 100644 --- a/crates/bevy_render/src/texture/texture_attachment.rs +++ b/crates/bevy_render/src/texture/texture_attachment.rs @@ -8,7 +8,7 @@ use wgpu::{ LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, StoreOp, }; -/// A wrapper for a [CachedTexture] that is used as a [RenderPassColorAttachment]. +/// A wrapper for a [`CachedTexture`] that is used as a [`RenderPassColorAttachment`]. #[derive(Clone)] pub struct ColorAttachment { pub texture: CachedTexture, @@ -82,7 +82,7 @@ impl ColorAttachment { } } -/// A wrapper for a [TextureView] that is used as a depth-only [RenderPassDepthStencilAttachment]. +/// A wrapper for a [`TextureView`] that is used as a depth-only [`RenderPassDepthStencilAttachment`]. pub struct DepthAttachment { pub view: TextureView, clear_value: Option, @@ -99,7 +99,7 @@ impl DepthAttachment { } /// Get this texture view as an attachment. The attachment will be cleared with a value of - /// `clear_value` if this is the first time calling this function with `store` == StoreOp::Store, + /// `clear_value` if this is the first time calling this function with `store` == [`StoreOp::Store`], /// and a clear value was provided, otherwise it will be loaded. pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment { let first_call = self From d00dd5124d14226120d5e8ba04ae5546e000690b Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:30:47 -0800 Subject: [PATCH 27/36] Clippy lint --- crates/bevy_core_pipeline/src/msaa_writeback.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index 8aa2a659d6e70..06f294dae0e7f 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -93,7 +93,7 @@ impl Node for MsaaWritebackNode { color_attachments: &[Some(RenderPassColorAttachment { // If MSAA is enabled, then the sampled texture will always exist view: target.sampled_main_texture_view().unwrap(), - resolve_target: Some(&post_process.destination), + resolve_target: Some(post_process.destination), ops: Operations { load: LoadOp::Clear(Color::BLACK.into()), store: StoreOp::Store, From aa6169a69023ff138901a2ce15cc5ae697d45699 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:34:43 -0800 Subject: [PATCH 28/36] Fix missing import in example --- examples/ecs/iter_combinations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ecs/iter_combinations.rs b/examples/ecs/iter_combinations.rs index 5f63cd52bfbf0..23da0303858bf 100644 --- a/examples/ecs/iter_combinations.rs +++ b/examples/ecs/iter_combinations.rs @@ -1,6 +1,6 @@ //! Shows how to iterate over combinations of query results. -use bevy::{pbr::AmbientLight, prelude::*}; +use bevy::{pbr::AmbientLight, prelude::*, render::camera::ClearColor}; use rand::{rngs::StdRng, Rng, SeedableRng}; fn main() { From ec9fd6989beaa10340db057b4aec869aaa311579 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:40:45 -0800 Subject: [PATCH 29/36] Add clear color back to prelude --- crates/bevy_render/src/lib.rs | 2 +- examples/ecs/iter_combinations.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index a8243422d607d..d51bb393ca311 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -27,7 +27,7 @@ pub mod view; pub mod prelude { #[doc(hidden)] pub use crate::{ - camera::{Camera, OrthographicProjection, PerspectiveProjection, Projection}, + camera::{Camera, ClearColor, OrthographicProjection, PerspectiveProjection, Projection}, color::Color, mesh::{morph::MorphWeights, shape, Mesh}, render_resource::Shader, diff --git a/examples/ecs/iter_combinations.rs b/examples/ecs/iter_combinations.rs index 23da0303858bf..5f63cd52bfbf0 100644 --- a/examples/ecs/iter_combinations.rs +++ b/examples/ecs/iter_combinations.rs @@ -1,6 +1,6 @@ //! Shows how to iterate over combinations of query results. -use bevy::{pbr::AmbientLight, prelude::*, render::camera::ClearColor}; +use bevy::{pbr::AmbientLight, prelude::*}; use rand::{rngs::StdRng, Rng, SeedableRng}; fn main() { From a4643246034fc2ce543eb84c5f75b2dbda48ef80 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:45:51 -0800 Subject: [PATCH 30/36] Fix more examples --- crates/bevy_render/src/lib.rs | 5 ++++- examples/3d/split_screen.rs | 5 +---- examples/3d/two_passes.rs | 2 +- tests/window/resizing.rs | 6 ++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index d51bb393ca311..e7ed0545eebd1 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -27,7 +27,10 @@ pub mod view; pub mod prelude { #[doc(hidden)] pub use crate::{ - camera::{Camera, ClearColor, OrthographicProjection, PerspectiveProjection, Projection}, + camera::{ + Camera, ClearColor, ClearColorConfig, OrthographicProjection, PerspectiveProjection, + Projection, + }, color::Color, mesh::{morph::MorphWeights, shape, Mesh}, render_resource::Shader, diff --git a/examples/3d/split_screen.rs b/examples/3d/split_screen.rs index deeb11ca58741..23c5e455358a3 100644 --- a/examples/3d/split_screen.rs +++ b/examples/3d/split_screen.rs @@ -3,10 +3,7 @@ use std::f32::consts::PI; use bevy::{ - pbr::CascadeShadowConfigBuilder, - prelude::*, - render::camera::{ClearColorConfig, Viewport}, - window::WindowResized, + pbr::CascadeShadowConfigBuilder, prelude::*, render::camera::Viewport, window::WindowResized, }; fn main() { diff --git a/examples/3d/two_passes.rs b/examples/3d/two_passes.rs index 59ed3c9a3d8c0..8ded87396e3a4 100644 --- a/examples/3d/two_passes.rs +++ b/examples/3d/two_passes.rs @@ -1,6 +1,6 @@ //! Renders two 3d passes to the same window from different perspectives. -use bevy::{prelude::*, render::camera::ClearColorConfig}; +use bevy::prelude::*; fn main() { App::new() diff --git a/tests/window/resizing.rs b/tests/window/resizing.rs index 0d9135989c164..a6da0450dd00f 100644 --- a/tests/window/resizing.rs +++ b/tests/window/resizing.rs @@ -1,7 +1,7 @@ //! A test to confirm that `bevy` allows setting the window to arbitrary small sizes //! This is run in CI to ensure that this doesn't regress again. -use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*, window::WindowResolution}; +use bevy::{prelude::*, window::WindowResolution}; // The smallest size reached is 1x1, as X11 doesn't support windows with a 0 dimension // TODO: Add a check for platforms other than X11 for 0xk and kx0, despite those currently unsupported on CI. @@ -155,11 +155,9 @@ fn setup_2d(mut commands: Commands) { camera: Camera { // render the 2d camera after the 3d camera order: 1, - ..default() - }, - camera_2d: Camera2d { // do not use a clear color clear_color: ClearColorConfig::None, + ..default() }, ..default() }); From 15f8ecc2fd81376ffeef3a9bc123fe3e21c5608d Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:50:31 -0800 Subject: [PATCH 31/36] Fix more examples --- examples/3d/render_to_texture.rs | 5 +---- examples/shader/post_processing.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/3d/render_to_texture.rs b/examples/3d/render_to_texture.rs index a319e7d6e4e03..a1ab2d77821f8 100644 --- a/examples/3d/render_to_texture.rs +++ b/examples/3d/render_to_texture.rs @@ -100,14 +100,11 @@ fn setup( commands.spawn(( Camera3dBundle { - camera_3d: Camera3d { - clear_color: Color::WHITE.into(), - ..default() - }, camera: Camera { // render before the "main pass" camera order: -1, target: RenderTarget::Image(image_handle.clone()), + clear_color: Color::WHITE.into(), ..default() }, transform: Transform::from_translation(Vec3::new(0.0, 0.0, 15.0)) diff --git a/examples/shader/post_processing.rs b/examples/shader/post_processing.rs index ad684675d806b..cb5168c4f552f 100644 --- a/examples/shader/post_processing.rs +++ b/examples/shader/post_processing.rs @@ -305,7 +305,7 @@ fn setup( Camera3dBundle { transform: Transform::from_translation(Vec3::new(0.0, 0.0, 5.0)) .looking_at(Vec3::default(), Vec3::Y), - camera_3d: Camera3d { + camera: Camera { clear_color: Color::WHITE.into(), ..default() }, From 8c12fadbdf877bba7ec577aedd00cee7d3ba6e9d Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:52:07 -0800 Subject: [PATCH 32/36] Update crates/bevy_core_pipeline/src/core_2d/camera_2d.rs Co-authored-by: Alice Cecile --- crates/bevy_core_pipeline/src/core_2d/camera_2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs index 1971f31b55a33..a73eac16b0758 100644 --- a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs +++ b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs @@ -12,7 +12,7 @@ use bevy_transform::prelude::{GlobalTransform, Transform}; #[derive(Component, Default, Reflect, Clone, ExtractComponent)] #[extract_component_filter(With)] #[reflect(Component)] -pub struct Camera2d {} +pub struct Camera2d; #[derive(Bundle)] pub struct Camera2dBundle { From bcba6f9da44246a19bfcc5bc4f9c674faf817af3 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:56:01 -0800 Subject: [PATCH 33/36] Appease clippy --- crates/bevy_core_pipeline/src/core_2d/camera_2d.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs index 1971f31b55a33..7bab90e8fe5e3 100644 --- a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs +++ b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs @@ -52,7 +52,7 @@ impl Default for Camera2dBundle { transform, global_transform: Default::default(), camera: Camera::default(), - camera_2d: Camera2d::default(), + camera_2d: Camera2d, tonemapping: Tonemapping::None, deband_dither: DebandDither::Disabled, } @@ -90,7 +90,7 @@ impl Camera2dBundle { transform, global_transform: Default::default(), camera: Camera::default(), - camera_2d: Camera2d::default(), + camera_2d: Camera2d, tonemapping: Tonemapping::None, deband_dither: DebandDither::Disabled, } From f3f4f147da264fb91c8ac312dbe94c70fc76dfda Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:00:52 -0800 Subject: [PATCH 34/36] Fix broken test (the other one this time) --- tests/window/minimising.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/window/minimising.rs b/tests/window/minimising.rs index 40314a2153a9f..b60829cb088af 100644 --- a/tests/window/minimising.rs +++ b/tests/window/minimising.rs @@ -1,6 +1,6 @@ //! A test to confirm that `bevy` allows minimising the window //! This is run in CI to ensure that this doesn't regress again. -use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*}; +use bevy::prelude::*; fn main() { // TODO: Combine this with `resizing` once multiple_windows is simpler than @@ -72,11 +72,9 @@ fn setup_2d(mut commands: Commands) { camera: Camera { // render the 2d camera after the 3d camera order: 1, - ..default() - }, - camera_2d: Camera2d { // do not use a clear color clear_color: ClearColorConfig::None, + ..default() }, ..default() }); From f5c5806702aee590443932efc1cb4bea22af1911 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:14:27 -0800 Subject: [PATCH 35/36] More fixes --- crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs | 2 ++ .../src/core_3d/main_transparent_pass_3d_node.rs | 2 ++ crates/bevy_core_pipeline/src/deferred/node.rs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs index 7b926dee296bf..656db89100819 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs @@ -77,6 +77,8 @@ impl Node for MainPass2dNode { label: Some("reset_viewport_pass_2d"), color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, }; render_context diff --git a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs index c0116ddac9a64..ba379edb0dcdf 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs @@ -68,6 +68,8 @@ impl ViewNode for MainTransparentPass3dNode { label: Some("reset_viewport_pass_3d"), color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, }; render_context diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 72d7d66bbbcfa..8fac4d77fb32f 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -71,7 +71,7 @@ impl ViewNode for DeferredGBufferPrepassNode { #[cfg(all(feature = "webgl", target_arch = "wasm32"))] if let Some(deferred_texture) = &view_prepass_textures.deferred { render_context.command_encoder().clear_texture( - &deferred_texture.texture, + &deferred_texture.texture.texture, &bevy_render::render_resource::ImageSubresourceRange::default(), ); } From c6063c5a28ca4a63818cc77d09524553c3825691 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:22:57 -0800 Subject: [PATCH 36/36] Fix doc link --- crates/bevy_core_pipeline/src/core_3d/camera_3d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs b/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs index 4bb98fd5cb8bd..bdcd81c92314e 100644 --- a/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs +++ b/crates/bevy_core_pipeline/src/core_3d/camera_3d.rs @@ -32,7 +32,7 @@ pub struct Camera3d { /// regardless of this setting. /// - Setting this to `0` disables the screen-space refraction effect entirely, and falls /// back to refracting only the environment map light's texture. - /// - If set to more than `0`, any opaque [`clear_color`](Camera3d::clear_color) will obscure the environment + /// - If set to more than `0`, any opaque [`clear_color`](Camera::clear_color) will obscure the environment /// map light's texture, preventing it from being visible “through” transmissive materials. If you'd like /// to still have the environment map show up in your refractions, you can set the clear color's alpha to `0.0`. /// Keep in mind that depending on the platform and your window settings, this may cause the window to become