bevy_core_pipeline/core_2d/
main_opaque_pass_2d_node.rs1use 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#[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 let mut command_encoder =
62 render_device.create_command_encoder(&CommandEncoderDescriptor {
63 label: Some("main_opaque_pass_2d_command_encoder"),
64 });
65
66 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 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 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}