Skip to content

Commit

Permalink
fix: Skip some rendering logics when the viewport width or height is…
Browse files Browse the repository at this point in the history
… zero (#15654)

# Objective

- Fixes #15285

## Solution

`winit` sends resized to zero events when the window is minimized only
on Windows OS(rust-windowing/winit#2015).
This makes updating window viewport size to `(0, 0)` and panicking when
calculating aspect ratio.

~~So, just skip these kinds of events - resizing to (0, 0) when the
window is minimized - on Windows OS~~

Idially, the camera extraction excludes the cameras whose target size
width or height is zero here;


https://github.com/bevyengine/bevy/blob/25bfa80e60e886031dd6eb1a3fe2ea548fc0a6c6/crates/bevy_render/src/camera/camera.rs#L1060-L1074

but it seems that winit event loop sends resize events after extraction
and before post update schedule, so they might panics before the
extraction filters them out.

Alternatively, it might be possible to change event loop evaluating
order or defer them to the right schedule but I'm afraid that it might
cause some breaking changes, so just skip rendering logics for such
windows and they will be all filtered out by the extractions on the next
frame and thereafter.

## Testing

Running the example in the original issue and minimizing causes panic,
or just running `tests/window/minimising.rs` with `cargo run --example
minimising` panics without this PR and doesn't panics with this PR.

I think that we should run it in CI on Windows OS btw
  • Loading branch information
ShoyuVanilla authored Oct 8, 2024
1 parent 0837ade commit a89ae8e
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 10 deletions.
4 changes: 3 additions & 1 deletion crates/bevy_core_pipeline/src/bloom/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ impl ExtractComponent for Bloom {
camera.is_active,
camera.hdr,
) {
(Some(URect { min: origin, .. }), Some(size), Some(target_size), true, true) => {
(Some(URect { min: origin, .. }), Some(size), Some(target_size), true, true)
if size.x != 0 && size.y != 0 =>
{
let threshold = bloom.prefilter.threshold;
let threshold_softness = bloom.prefilter.threshold_softness;
let knee = threshold * threshold_softness.clamp(0.0, 1.0);
Expand Down
9 changes: 6 additions & 3 deletions crates/bevy_pbr/src/cluster/assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,12 @@ pub(crate) fn assign_objects_to_clusters(
continue;
}

let Some(screen_size) = camera.physical_viewport_size() else {
clusters.clear();
continue;
let screen_size = match camera.physical_viewport_size() {
Some(screen_size) if screen_size.x != 0 && screen_size.y != 0 => screen_size,
_ => {
clusters.clear();
continue;
}
};

let mut requested_cluster_dimensions = config.dimensions_for_screen_size(screen_size);
Expand Down
12 changes: 8 additions & 4 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -965,10 +965,14 @@ pub fn camera_system<T: CameraProjection + Component>(
}
camera.computed.target_info = new_computed_target_info;
if let Some(size) = camera.logical_viewport_size() {
camera_projection.update(size.x, size.y);
camera.computed.clip_from_view = match &camera.sub_camera_view {
Some(sub_view) => camera_projection.get_clip_from_view_for_sub(sub_view),
None => camera_projection.get_clip_from_view(),
if size.x != 0.0 && size.y != 0.0 {
camera_projection.update(size.x, size.y);
camera.computed.clip_from_view = match &camera.sub_camera_view {
Some(sub_view) => {
camera_projection.get_clip_from_view_for_sub(sub_view)
}
None => camera_projection.get_clip_from_view(),
}
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions crates/bevy_render/src/camera/camera_driver_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ impl Node for CameraDriverNode {
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() {
if windows
.windows
.get(&window_entity)
.is_some_and(|w| w.physical_width > 0 && w.physical_height > 0)
{
camera_windows.insert(window_entity);
} else {
// The window doesn't exist anymore so we don't need to run the graph
// The window doesn't exist anymore or zero-sized so we don't need to run the graph
run_graph = false;
}
}
Expand Down

0 comments on commit a89ae8e

Please sign in to comment.