use crate::{
camera::{ExtractedCamera, NormalizedRenderTarget, SortedCameras},
render_graph::{Node, NodeRunError, RenderGraphContext},
renderer::RenderContext,
view::ExtractedWindows,
};
use bevy_ecs::{prelude::QueryState, world::World};
use bevy_utils::HashSet;
use wgpu::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor, StoreOp};
pub struct CameraDriverNode {
cameras: QueryState<&'static ExtractedCamera>,
}
impl CameraDriverNode {
pub fn new(world: &mut World) -> Self {
Self {
cameras: world.query(),
}
}
}
impl Node for CameraDriverNode {
fn update(&mut self, world: &mut World) {
self.cameras.update_archetypes(world);
}
fn run(
&self,
graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
world: &World,
) -> Result<(), NodeRunError> {
let sorted_cameras = world.resource::<SortedCameras>();
let windows = world.resource::<ExtractedWindows>();
let mut camera_windows = HashSet::new();
for sorted_camera in &sorted_cameras.0 {
let Ok(camera) = self.cameras.get_manual(world, sorted_camera.entity) else {
continue;
};
let mut run_graph = true;
if let Some(NormalizedRenderTarget::Window(window_ref)) = camera.target {
let window_entity = window_ref.entity();
if windows.windows.get(&window_entity).is_some() {
camera_windows.insert(window_entity);
} else {
run_graph = false;
}
}
if run_graph {
graph.run_sub_graph(camera.render_graph, vec![], Some(sorted_camera.entity))?;
}
}
for (id, window) in world.resource::<ExtractedWindows>().iter() {
if camera_windows.contains(id) {
continue;
}
let Some(swap_chain_texture) = &window.swap_chain_texture_view else {
continue;
};
#[cfg(feature = "trace")]
let _span = bevy_utils::tracing::info_span!("no_camera_clear_pass").entered();
let pass_descriptor = RenderPassDescriptor {
label: Some("no_camera_clear_pass"),
color_attachments: &[Some(RenderPassColorAttachment {
view: swap_chain_texture,
resolve_target: None,
ops: Operations {
load: LoadOp::Clear(wgpu::Color::BLACK),
store: StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
};
render_context
.command_encoder()
.begin_render_pass(&pass_descriptor);
}
Ok(())
}
}