Path: blob/main/crates/bevy_render/src/render_graph/camera_driver_node.rs
6596 views
use crate::{1camera::{ExtractedCamera, SortedCameras},2render_graph::{Node, NodeRunError, RenderGraphContext},3renderer::RenderContext,4view::ExtractedWindows,5};6use bevy_camera::{ClearColor, NormalizedRenderTarget};7use bevy_ecs::{entity::ContainsEntity, prelude::QueryState, world::World};8use bevy_platform::collections::HashSet;9use wgpu::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor, StoreOp};1011pub struct CameraDriverNode {12cameras: QueryState<&'static ExtractedCamera>,13}1415impl CameraDriverNode {16pub fn new(world: &mut World) -> Self {17Self {18cameras: world.query(),19}20}21}2223impl Node for CameraDriverNode {24fn update(&mut self, world: &mut World) {25self.cameras.update_archetypes(world);26}27fn run(28&self,29graph: &mut RenderGraphContext,30render_context: &mut RenderContext,31world: &World,32) -> Result<(), NodeRunError> {33let sorted_cameras = world.resource::<SortedCameras>();34let windows = world.resource::<ExtractedWindows>();35let mut camera_windows = <HashSet<_>>::default();36for sorted_camera in &sorted_cameras.0 {37let Ok(camera) = self.cameras.get_manual(world, sorted_camera.entity) else {38continue;39};4041let mut run_graph = true;42if let Some(NormalizedRenderTarget::Window(window_ref)) = camera.target {43let window_entity = window_ref.entity();44if windows45.windows46.get(&window_entity)47.is_some_and(|w| w.physical_width > 0 && w.physical_height > 0)48{49camera_windows.insert(window_entity);50} else {51// The window doesn't exist anymore or zero-sized so we don't need to run the graph52run_graph = false;53}54}55if run_graph {56graph.run_sub_graph(camera.render_graph, vec![], Some(sorted_camera.entity))?;57}58}5960let clear_color_global = world.resource::<ClearColor>();6162// wgpu (and some backends) require doing work for swap chains if you call `get_current_texture()` and `present()`63// This ensures that Bevy doesn't crash, even when there are no cameras (and therefore no work submitted).64for (id, window) in world.resource::<ExtractedWindows>().iter() {65if camera_windows.contains(id) && render_context.has_commands() {66continue;67}6869let Some(swap_chain_texture) = &window.swap_chain_texture_view else {70continue;71};7273#[cfg(feature = "trace")]74let _span = tracing::info_span!("no_camera_clear_pass").entered();75let pass_descriptor = RenderPassDescriptor {76label: Some("no_camera_clear_pass"),77color_attachments: &[Some(RenderPassColorAttachment {78view: swap_chain_texture,79depth_slice: None,80resolve_target: None,81ops: Operations {82load: LoadOp::Clear(clear_color_global.to_linear().into()),83store: StoreOp::Store,84},85})],86depth_stencil_attachment: None,87timestamp_writes: None,88occlusion_query_set: None,89};9091render_context92.command_encoder()93.begin_render_pass(&pass_descriptor);94}9596Ok(())97}98}99100101