bevy_core_pipeline/core_2d/
main_opaque_pass_2d_node.rs

1use crate::core_2d::Opaque2d;
2use bevy_ecs::{prelude::World, query::QueryItem};
3use bevy_render::{
4    camera::ExtractedCamera,
5    diagnostic::RecordDiagnostics,
6    render_graph::{NodeRunError, RenderGraphContext, ViewNode},
7    render_phase::{TrackedRenderPass, ViewBinnedRenderPhases},
8    render_resource::{CommandEncoderDescriptor, RenderPassDescriptor, StoreOp},
9    renderer::RenderContext,
10    view::{ExtractedView, ViewDepthTexture, ViewTarget},
11};
12use tracing::error;
13#[cfg(feature = "trace")]
14use tracing::info_span;
15
16use super::AlphaMask2d;
17
18/// A [`bevy_render::render_graph::Node`] that runs the
19/// [`Opaque2d`] [`ViewBinnedRenderPhases`] and [`AlphaMask2d`] [`ViewBinnedRenderPhases`]
20#[derive(Default)]
21pub struct MainOpaquePass2dNode;
22impl ViewNode for MainOpaquePass2dNode {
23    type ViewQuery = (
24        &'static ExtractedCamera,
25        &'static ExtractedView,
26        &'static ViewTarget,
27        &'static ViewDepthTexture,
28    );
29
30    fn run<'w>(
31        &self,
32        graph: &mut RenderGraphContext,
33        render_context: &mut RenderContext<'w>,
34        (camera, view, target, depth): QueryItem<'w, Self::ViewQuery>,
35        world: &'w World,
36    ) -> Result<(), NodeRunError> {
37        let (Some(opaque_phases), Some(alpha_mask_phases)) = (
38            world.get_resource::<ViewBinnedRenderPhases<Opaque2d>>(),
39            world.get_resource::<ViewBinnedRenderPhases<AlphaMask2d>>(),
40        ) else {
41            return Ok(());
42        };
43
44        let diagnostics = render_context.diagnostic_recorder();
45
46        let color_attachments = [Some(target.get_color_attachment())];
47        let depth_stencil_attachment = Some(depth.get_attachment(StoreOp::Store));
48
49        let view_entity = graph.view_entity();
50        let (Some(opaque_phase), Some(alpha_mask_phase)) = (
51            opaque_phases.get(&view.retained_view_entity),
52            alpha_mask_phases.get(&view.retained_view_entity),
53        ) else {
54            return Ok(());
55        };
56        render_context.add_command_buffer_generation_task(move |render_device| {
57            #[cfg(feature = "trace")]
58            let _main_opaque_pass_2d_span = info_span!("main_opaque_pass_2d").entered();
59
60            // Command encoder setup
61            let mut command_encoder =
62                render_device.create_command_encoder(&CommandEncoderDescriptor {
63                    label: Some("main_opaque_pass_2d_command_encoder"),
64                });
65
66            // Render pass setup
67            let render_pass = command_encoder.begin_render_pass(&RenderPassDescriptor {
68                label: Some("main_opaque_pass_2d"),
69                color_attachments: &color_attachments,
70                depth_stencil_attachment,
71                timestamp_writes: None,
72                occlusion_query_set: None,
73            });
74            let mut render_pass = TrackedRenderPass::new(&render_device, render_pass);
75            let pass_span = diagnostics.pass_span(&mut render_pass, "main_opaque_pass_2d");
76
77            if let Some(viewport) = camera.viewport.as_ref() {
78                render_pass.set_camera_viewport(viewport);
79            }
80
81            // Opaque draws
82            if !opaque_phase.is_empty() {
83                #[cfg(feature = "trace")]
84                let _opaque_main_pass_2d_span = info_span!("opaque_main_pass_2d").entered();
85                if let Err(err) = opaque_phase.render(&mut render_pass, world, view_entity) {
86                    error!("Error encountered while rendering the 2d opaque phase {err:?}");
87                }
88            }
89
90            // Alpha mask draws
91            if !alpha_mask_phase.is_empty() {
92                #[cfg(feature = "trace")]
93                let _alpha_mask_main_pass_2d_span = info_span!("alpha_mask_main_pass_2d").entered();
94                if let Err(err) = alpha_mask_phase.render(&mut render_pass, world, view_entity) {
95                    error!("Error encountered while rendering the 2d alpha mask phase {err:?}");
96                }
97            }
98
99            pass_span.end(&mut render_pass);
100            drop(render_pass);
101            command_encoder.finish()
102        });
103
104        Ok(())
105    }
106}