Skip to content

Commit f0d48da

Browse files
committed
Add an example to test small window sizes (#3597)
# Objective We keep getting issues where things break at small window sizes, e.g #3368 (caused by #3153), #3596 ('caused' by #3545) ## Solution - Add a test that we can make small windows. Currently, this fails on my machine with some quite scary vulkan errors: ``` 2022-01-08T22:55:13.770261Z ERROR wgpu_hal::vulkan::instance: VALIDATION [VUID-VkSwapchainCreateInfoKHR-imageExtent-01274 (0x7cd0911d)] Validation Error: [ VUID-VkSwapchainCreateInfoKHR-imageExtent-01274 ] Object 0: handle = 0x1adbd410a60, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x7cd0911d | vkCreateSwapchainKHR() called with imageExtent = (225,60), which is outside the bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (225,56), minImageExtent = (225,56), maxImageExtent = (225,56). The Vulkan spec states: imageExtent must be between minImageExtent and maxImageExtent, inclusive, where minImageExtent and maxImageExtent are members of the VkSurfaceCapabilitiesKHR structure returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the surface (https://vulkan.lunarg.com/doc/view/1.2.198.1/windows/1.2-extensions/vkspec.html#VUID-VkSwapchainCreateInfoKHR-imageExtent-01274) 2022-01-08T22:55:13.770808Z ERROR wgpu_hal::vulkan::instance: objects: (type: DEVICE, hndl: 0x1adbd410a60, name: ?) 2022-01-08T22:55:13.787403Z ERROR wgpu_hal::vulkan::instance: VALIDATION [VUID-VkSwapchainCreateInfoKHR-imageExtent-01274 (0x7cd0911d)] Validation Error: [ VUID-VkSwapchainCreateInfoKHR-imageExtent-01274 ] Object 0: handle = 0x1adbd410a60, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x7cd0911d | vkCreateSwapchainKHR() called with imageExtent = (225,56), which is outside the bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (225,52), minImageExtent = (225,52), maxImageExtent = (225,52). The Vulkan spec states: imageExtent must be between minImageExtent and maxImageExtent, inclusive, where minImageExtent and maxImageExtent are members of the VkSurfaceCapabilitiesKHR structure returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the surface (https://vulkan.lunarg.com/doc/view/1.2.198.1/windows/1.2-extensions/vkspec.html#VUID-VkSwapchainCreateInfoKHR-imageExtent-01274) ``` etc. This might be a new issue here, although I'm surprised it's vulkan giving this error; wgpu should stop it if this is illegal.
1 parent bc7293e commit f0d48da

File tree

5 files changed

+244
-0
lines changed

5 files changed

+244
-0
lines changed

.github/example-run/minimising.ron

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(
2+
exit_after: Some(90)
3+
)

.github/example-run/resizing.ron

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(
2+
// Ensures that the full cycle will run
3+
exit_after: Some(410)
4+
)

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,15 @@ path = "examples/window/transparent_window.rs"
615615
name = "window_settings"
616616
path = "examples/window/window_settings.rs"
617617

618+
[[example]]
619+
name = "resizing"
620+
path = "tests/window/resizing.rs"
621+
622+
[[example]]
623+
name = "minimising"
624+
path = "tests/window/minimising.rs"
625+
626+
618627
# Android
619628
[[example]]
620629
crate-type = ["cdylib"]

tests/window/minimising.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//! A test to confirm that `bevy` allows minimising the window
2+
//! This is run in CI to ensure that this doesn't regress again.
3+
use bevy::prelude::*;
4+
5+
fn main() {
6+
// TODO: Combine this with `resizing` once multiple_windows is simpler than
7+
// it is currently.
8+
App::new()
9+
.insert_resource(WindowDescriptor {
10+
title: "Minimising".into(),
11+
..Default::default()
12+
})
13+
.add_plugins(DefaultPlugins)
14+
.add_system(minimise_automatically)
15+
.add_startup_system(setup_3d)
16+
.add_startup_system(setup_2d)
17+
.run();
18+
}
19+
20+
fn minimise_automatically(mut windows: ResMut<Windows>, mut frames: Local<u32>) {
21+
if *frames == 60 {
22+
windows.get_primary_mut().unwrap().set_minimized(true);
23+
} else {
24+
*frames += 1;
25+
}
26+
}
27+
28+
/// A simple 3d scene, taken from the `3d_scene` example
29+
fn setup_3d(
30+
mut commands: Commands,
31+
mut meshes: ResMut<Assets<Mesh>>,
32+
mut materials: ResMut<Assets<StandardMaterial>>,
33+
) {
34+
// plane
35+
commands.spawn_bundle(PbrBundle {
36+
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
37+
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
38+
..default()
39+
});
40+
// cube
41+
commands.spawn_bundle(PbrBundle {
42+
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
43+
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
44+
transform: Transform::from_xyz(0.0, 0.5, 0.0),
45+
..default()
46+
});
47+
// light
48+
commands.spawn_bundle(PointLightBundle {
49+
point_light: PointLight {
50+
intensity: 1500.0,
51+
shadows_enabled: true,
52+
..default()
53+
},
54+
transform: Transform::from_xyz(4.0, 8.0, 4.0),
55+
..default()
56+
});
57+
// camera
58+
commands.spawn_bundle(PerspectiveCameraBundle {
59+
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
60+
..default()
61+
});
62+
}
63+
64+
/// A simple 2d scene, taken from the `rect` example
65+
fn setup_2d(mut commands: Commands) {
66+
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
67+
commands.spawn_bundle(SpriteBundle {
68+
sprite: Sprite {
69+
color: Color::rgb(0.25, 0.25, 0.75),
70+
custom_size: Some(Vec2::new(50.0, 50.0)),
71+
..default()
72+
},
73+
..default()
74+
});
75+
}

tests/window/resizing.rs

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
//! A test to confirm that `bevy` allows setting the window to arbitrary small sizes
2+
//! This is run in CI to ensure that this doesn't regress again.
3+
4+
use bevy::{input::system::exit_on_esc_system, prelude::*};
5+
6+
// The smallest size reached is 1x1, as X11 doesn't support windows with a 0 dimension
7+
// TODO: Add a check for platforms other than X11 for 0xk and kx0, despite those currently unsupported on CI.
8+
const MAX_WIDTH: u16 = 401;
9+
const MAX_HEIGHT: u16 = 401;
10+
const MIN_WIDTH: u16 = 1;
11+
const MIN_HEIGHT: u16 = 1;
12+
const RESIZE_STEP: u16 = 4;
13+
14+
struct Dimensions {
15+
width: u16,
16+
height: u16,
17+
}
18+
19+
fn main() {
20+
App::new()
21+
.insert_resource(WindowDescriptor {
22+
width: MAX_WIDTH.try_into().unwrap(),
23+
height: MAX_HEIGHT.try_into().unwrap(),
24+
scale_factor_override: Some(1.),
25+
title: "Resizing".into(),
26+
..Default::default()
27+
})
28+
.insert_resource(Dimensions {
29+
width: MAX_WIDTH,
30+
height: MAX_HEIGHT,
31+
})
32+
.add_plugins(DefaultPlugins)
33+
.insert_resource(Phase::ContractingY)
34+
.add_system(change_window_size)
35+
.add_system(sync_dimensions)
36+
.add_system(exit_on_esc_system)
37+
.add_startup_system(setup_3d)
38+
.add_startup_system(setup_2d)
39+
.run();
40+
}
41+
42+
enum Phase {
43+
ContractingY,
44+
ContractingX,
45+
ExpandingY,
46+
ExpandingX,
47+
}
48+
49+
use Phase::*;
50+
51+
fn change_window_size(
52+
mut windows: ResMut<Dimensions>,
53+
mut phase: ResMut<Phase>,
54+
mut first_complete: Local<bool>,
55+
) {
56+
// Put off rendering for one frame, as currently for a frame where
57+
// resizing happens, nothing is presented.
58+
// TODO: Debug and fix this if feasible
59+
if !*first_complete {
60+
*first_complete = true;
61+
return;
62+
}
63+
let height = windows.height;
64+
let width = windows.width;
65+
match *phase {
66+
Phase::ContractingY => {
67+
if height <= MIN_HEIGHT {
68+
*phase = ContractingX;
69+
} else {
70+
windows.height -= RESIZE_STEP;
71+
}
72+
}
73+
Phase::ContractingX => {
74+
if width <= MIN_WIDTH {
75+
*phase = ExpandingY;
76+
} else {
77+
windows.width -= RESIZE_STEP;
78+
}
79+
}
80+
Phase::ExpandingY => {
81+
if height >= MAX_HEIGHT {
82+
*phase = ExpandingX;
83+
} else {
84+
windows.height += RESIZE_STEP;
85+
}
86+
}
87+
Phase::ExpandingX => {
88+
if width >= MAX_WIDTH {
89+
*phase = ContractingY;
90+
} else {
91+
windows.width += RESIZE_STEP;
92+
}
93+
}
94+
}
95+
}
96+
97+
fn sync_dimensions(dim: Res<Dimensions>, mut windows: ResMut<Windows>) {
98+
if dim.is_changed() {
99+
windows.get_primary_mut().unwrap().set_resolution(
100+
dim.width.try_into().unwrap(),
101+
dim.height.try_into().unwrap(),
102+
);
103+
}
104+
}
105+
106+
/// A simple 3d scene, taken from the `3d_scene` example
107+
fn setup_3d(
108+
mut commands: Commands,
109+
mut meshes: ResMut<Assets<Mesh>>,
110+
mut materials: ResMut<Assets<StandardMaterial>>,
111+
) {
112+
// plane
113+
commands.spawn_bundle(PbrBundle {
114+
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
115+
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
116+
..default()
117+
});
118+
// cube
119+
commands.spawn_bundle(PbrBundle {
120+
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
121+
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
122+
transform: Transform::from_xyz(0.0, 0.5, 0.0),
123+
..default()
124+
});
125+
// light
126+
commands.spawn_bundle(PointLightBundle {
127+
point_light: PointLight {
128+
intensity: 1500.0,
129+
shadows_enabled: true,
130+
..default()
131+
},
132+
transform: Transform::from_xyz(4.0, 8.0, 4.0),
133+
..default()
134+
});
135+
// camera
136+
commands.spawn_bundle(PerspectiveCameraBundle {
137+
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
138+
..default()
139+
});
140+
}
141+
142+
/// A simple 2d scene, taken from the `rect` example
143+
fn setup_2d(mut commands: Commands) {
144+
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
145+
commands.spawn_bundle(SpriteBundle {
146+
sprite: Sprite {
147+
color: Color::rgb(0.25, 0.25, 0.75),
148+
custom_size: Some(Vec2::new(50.0, 50.0)),
149+
..default()
150+
},
151+
..default()
152+
});
153+
}

0 commit comments

Comments
 (0)