mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
Run a clear pass on Windows without any Views (#3304)
Fixes #3043 `surface_texture.present()` will cause panics if no work is done on a given frame. "Views" are how we queue up work. Without any cameras, no work is produced. This adds a "clear pass" for windows without views, which ensures we clear windows (thus doing work) every frame. This is a "quick fix". It can be made much cleaner once we make "render targets" a concept and move some responsibilities around. Then we just clear the "render target" once instead of clearing "views". I _might_ have time to tackle that work prior to 0.6, but I doubt it. If "render targets" don't make it in to 0.6, they will be one of the first things I tackle after release.
This commit is contained in:
parent
172f4d6d78
commit
fe9b5003c5
1 changed files with 54 additions and 7 deletions
|
@ -1,15 +1,27 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use crate::ClearColor;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_render2::{
|
||||
camera::ExtractedCamera,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo},
|
||||
render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor},
|
||||
render_resource::{
|
||||
LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment,
|
||||
RenderPassDescriptor,
|
||||
},
|
||||
renderer::RenderContext,
|
||||
view::{ExtractedView, ViewDepthTexture, ViewTarget},
|
||||
view::{ExtractedView, ExtractedWindows, ViewDepthTexture, ViewTarget},
|
||||
};
|
||||
|
||||
pub struct ClearPassNode {
|
||||
query:
|
||||
QueryState<(&'static ViewTarget, Option<&'static ViewDepthTexture>), With<ExtractedView>>,
|
||||
query: QueryState<
|
||||
(
|
||||
&'static ViewTarget,
|
||||
Option<&'static ViewDepthTexture>,
|
||||
Option<&'static ExtractedCamera>,
|
||||
),
|
||||
With<ExtractedView>,
|
||||
>,
|
||||
}
|
||||
|
||||
impl ClearPassNode {
|
||||
|
@ -35,9 +47,17 @@ impl Node for ClearPassNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
/* This gets all ViewTargets and ViewDepthTextures and clears its attachments */
|
||||
for (target, depth) in self.query.iter_manual(world) {
|
||||
let clear_color = world.get_resource::<ClearColor>().unwrap();
|
||||
let mut cleared_windows = HashSet::new();
|
||||
let clear_color = world.get_resource::<ClearColor>().unwrap();
|
||||
|
||||
// This gets all ViewTargets and ViewDepthTextures and clears its attachments
|
||||
// TODO: This has the potential to clear the same target multiple times, if there
|
||||
// are multiple views drawing to the same target. This should be fixed when we make
|
||||
// clearing happen on "render targets" instead of "views" (see the TODO below for more context).
|
||||
for (target, depth, camera) in self.query.iter_manual(world) {
|
||||
if let Some(camera) = camera {
|
||||
cleared_windows.insert(camera.window_id);
|
||||
}
|
||||
let pass_descriptor = RenderPassDescriptor {
|
||||
label: Some("clear_pass"),
|
||||
color_attachments: &[target.get_color_attachment(Operations {
|
||||
|
@ -59,6 +79,33 @@ impl Node for ClearPassNode {
|
|||
.begin_render_pass(&pass_descriptor);
|
||||
}
|
||||
|
||||
// TODO: This is a hack to ensure we don't call present() on frames without any work,
|
||||
// which will cause panics. The real fix here is to clear "render targets" directly
|
||||
// instead of "views". This should be removed once full RenderTargets are implemented.
|
||||
let windows = world.get_resource::<ExtractedWindows>().unwrap();
|
||||
for window in windows.values() {
|
||||
// skip windows that have already been cleared
|
||||
if cleared_windows.contains(&window.id) {
|
||||
continue;
|
||||
}
|
||||
let pass_descriptor = RenderPassDescriptor {
|
||||
label: Some("clear_pass"),
|
||||
color_attachments: &[RenderPassColorAttachment {
|
||||
view: window.swap_chain_texture.as_ref().unwrap(),
|
||||
resolve_target: None,
|
||||
ops: Operations {
|
||||
load: LoadOp::Clear(clear_color.0.into()),
|
||||
store: true,
|
||||
},
|
||||
}],
|
||||
depth_stencil_attachment: None,
|
||||
};
|
||||
|
||||
render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue