diff --git a/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs index bce42cead700e..dae9217d3a867 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs @@ -4,8 +4,8 @@ use bevy_render::{ camera::ExtractedCamera, diagnostic::RecordDiagnostics, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, - render_phase::ViewSortedRenderPhases, - render_resource::{RenderPassDescriptor, StoreOp}, + render_phase::{TrackedRenderPass, ViewSortedRenderPhases}, + render_resource::{CommandEncoderDescriptor, RenderPassDescriptor, StoreOp}, renderer::RenderContext, view::{ExtractedView, ViewDepthTexture, ViewTarget}, }; @@ -42,63 +42,75 @@ impl ViewNode for MainTransparentPass2dNode { return Ok(()); }; - // This needs to run at least once to clear the background color, even if there are no items to render - { - #[cfg(feature = "trace")] - let _main_pass_2d = info_span!("main_transparent_pass_2d").entered(); - - let diagnostics = render_context.diagnostic_recorder(); - - let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { - label: Some("main_transparent_pass_2d"), - color_attachments: &[Some(target.get_color_attachment())], - // NOTE: For the transparent pass we load the depth buffer. There should be no - // need to write to it, but store is set to `true` as a workaround for issue #3776, - // https://github.com/bevyengine/bevy/issues/3776 - // so that wgpu does not clear the depth buffer. - // As the opaque and alpha mask passes run first, opaque meshes can occlude - // transparent ones. - depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)), - timestamp_writes: None, - occlusion_query_set: None, - }); - - let pass_span = diagnostics.pass_span(&mut render_pass, "main_transparent_pass_2d"); - - if let Some(viewport) = camera.viewport.as_ref() { - render_pass.set_camera_viewport(viewport); - } + let diagnostics = render_context.diagnostic_recorder(); + + render_context.add_command_buffer_generation_task(move |render_device| { + // Command encoder setup + let mut command_encoder = + render_device.create_command_encoder(&CommandEncoderDescriptor { + label: Some("main_transparent_pass_2d_command_encoder"), + }); - if !transparent_phase.items.is_empty() { + // This needs to run at least once to clear the background color, even if there are no items to render + { #[cfg(feature = "trace")] - let _transparent_main_pass_2d_span = - info_span!("transparent_main_pass_2d").entered(); - if let Err(err) = transparent_phase.render(&mut render_pass, world, view_entity) { - error!("Error encountered while rendering the transparent 2D phase {err:?}"); + let _main_pass_2d = info_span!("main_transparent_pass_2d").entered(); + + let render_pass = command_encoder.begin_render_pass(&RenderPassDescriptor { + label: Some("main_transparent_pass_2d"), + color_attachments: &[Some(target.get_color_attachment())], + // NOTE: For the transparent pass we load the depth buffer. There should be no + // need to write to it, but store is set to `true` as a workaround for issue #3776, + // https://github.com/bevyengine/bevy/issues/3776 + // so that wgpu does not clear the depth buffer. + // As the opaque and alpha mask passes run first, opaque meshes can occlude + // transparent ones. + depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)), + timestamp_writes: None, + occlusion_query_set: None, + }); + let mut render_pass = TrackedRenderPass::new(&render_device, render_pass); + + let pass_span = diagnostics.pass_span(&mut render_pass, "main_transparent_pass_2d"); + + if let Some(viewport) = camera.viewport.as_ref() { + render_pass.set_camera_viewport(viewport); + } + + if !transparent_phase.items.is_empty() { + #[cfg(feature = "trace")] + let _transparent_main_pass_2d_span = + info_span!("transparent_main_pass_2d").entered(); + if let Err(err) = transparent_phase.render(&mut render_pass, world, view_entity) + { + error!( + "Error encountered while rendering the transparent 2D phase {err:?}" + ); + } } + + pass_span.end(&mut render_pass); + } + + // WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't + // reset for the next render pass so add an empty render pass without a custom viewport + #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] + if camera.viewport.is_some() { + #[cfg(feature = "trace")] + 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())], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }; + + command_encoder.begin_render_pass(&pass_descriptor); } - pass_span.end(&mut render_pass); - } - - // WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't - // reset for the next render pass so add an empty render pass without a custom viewport - #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] - if camera.viewport.is_some() { - #[cfg(feature = "trace")] - 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())], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }; - - render_context - .command_encoder() - .begin_render_pass(&pass_descriptor); - } + command_encoder.finish() + }); Ok(()) }