mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
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.
This commit is contained in:
parent
87991c50f1
commit
328c26d02c
5 changed files with 244 additions and 0 deletions
3
.github/example-run/minimising.ron
vendored
Normal file
3
.github/example-run/minimising.ron
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
(
|
||||||
|
exit_after: Some(90)
|
||||||
|
)
|
4
.github/example-run/resizing.ron
vendored
Normal file
4
.github/example-run/resizing.ron
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
(
|
||||||
|
// Ensures that the full cycle will run
|
||||||
|
exit_after: Some(410)
|
||||||
|
)
|
|
@ -615,6 +615,15 @@ path = "examples/window/transparent_window.rs"
|
||||||
name = "window_settings"
|
name = "window_settings"
|
||||||
path = "examples/window/window_settings.rs"
|
path = "examples/window/window_settings.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "resizing"
|
||||||
|
path = "tests/window/resizing.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "minimising"
|
||||||
|
path = "tests/window/minimising.rs"
|
||||||
|
|
||||||
|
|
||||||
# Android
|
# Android
|
||||||
[[example]]
|
[[example]]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
75
tests/window/minimising.rs
Normal file
75
tests/window/minimising.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
//! A test to confirm that `bevy` allows minimising the window
|
||||||
|
//! This is run in CI to ensure that this doesn't regress again.
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// TODO: Combine this with `resizing` once multiple_windows is simpler than
|
||||||
|
// it is currently.
|
||||||
|
App::new()
|
||||||
|
.insert_resource(WindowDescriptor {
|
||||||
|
title: "Minimising".into(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_system(minimise_automatically)
|
||||||
|
.add_startup_system(setup_3d)
|
||||||
|
.add_startup_system(setup_2d)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn minimise_automatically(mut windows: ResMut<Windows>, mut frames: Local<u32>) {
|
||||||
|
if *frames == 60 {
|
||||||
|
windows.get_primary_mut().unwrap().set_minimized(true);
|
||||||
|
} else {
|
||||||
|
*frames += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple 3d scene, taken from the `3d_scene` example
|
||||||
|
fn setup_3d(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
// plane
|
||||||
|
commands.spawn_bundle(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
// cube
|
||||||
|
commands.spawn_bundle(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||||
|
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
// light
|
||||||
|
commands.spawn_bundle(PointLightBundle {
|
||||||
|
point_light: PointLight {
|
||||||
|
intensity: 1500.0,
|
||||||
|
shadows_enabled: true,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
// camera
|
||||||
|
commands.spawn_bundle(PerspectiveCameraBundle {
|
||||||
|
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple 2d scene, taken from the `rect` example
|
||||||
|
fn setup_2d(mut commands: Commands) {
|
||||||
|
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||||
|
commands.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite {
|
||||||
|
color: Color::rgb(0.25, 0.25, 0.75),
|
||||||
|
custom_size: Some(Vec2::new(50.0, 50.0)),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
153
tests/window/resizing.rs
Normal file
153
tests/window/resizing.rs
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
//! A test to confirm that `bevy` allows setting the window to arbitrary small sizes
|
||||||
|
//! This is run in CI to ensure that this doesn't regress again.
|
||||||
|
|
||||||
|
use bevy::{input::system::exit_on_esc_system, prelude::*};
|
||||||
|
|
||||||
|
// The smallest size reached is 1x1, as X11 doesn't support windows with a 0 dimension
|
||||||
|
// TODO: Add a check for platforms other than X11 for 0xk and kx0, despite those currently unsupported on CI.
|
||||||
|
const MAX_WIDTH: u16 = 401;
|
||||||
|
const MAX_HEIGHT: u16 = 401;
|
||||||
|
const MIN_WIDTH: u16 = 1;
|
||||||
|
const MIN_HEIGHT: u16 = 1;
|
||||||
|
const RESIZE_STEP: u16 = 4;
|
||||||
|
|
||||||
|
struct Dimensions {
|
||||||
|
width: u16,
|
||||||
|
height: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.insert_resource(WindowDescriptor {
|
||||||
|
width: MAX_WIDTH.try_into().unwrap(),
|
||||||
|
height: MAX_HEIGHT.try_into().unwrap(),
|
||||||
|
scale_factor_override: Some(1.),
|
||||||
|
title: "Resizing".into(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_resource(Dimensions {
|
||||||
|
width: MAX_WIDTH,
|
||||||
|
height: MAX_HEIGHT,
|
||||||
|
})
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.insert_resource(Phase::ContractingY)
|
||||||
|
.add_system(change_window_size)
|
||||||
|
.add_system(sync_dimensions)
|
||||||
|
.add_system(exit_on_esc_system)
|
||||||
|
.add_startup_system(setup_3d)
|
||||||
|
.add_startup_system(setup_2d)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Phase {
|
||||||
|
ContractingY,
|
||||||
|
ContractingX,
|
||||||
|
ExpandingY,
|
||||||
|
ExpandingX,
|
||||||
|
}
|
||||||
|
|
||||||
|
use Phase::*;
|
||||||
|
|
||||||
|
fn change_window_size(
|
||||||
|
mut windows: ResMut<Dimensions>,
|
||||||
|
mut phase: ResMut<Phase>,
|
||||||
|
mut first_complete: Local<bool>,
|
||||||
|
) {
|
||||||
|
// Put off rendering for one frame, as currently for a frame where
|
||||||
|
// resizing happens, nothing is presented.
|
||||||
|
// TODO: Debug and fix this if feasible
|
||||||
|
if !*first_complete {
|
||||||
|
*first_complete = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let height = windows.height;
|
||||||
|
let width = windows.width;
|
||||||
|
match *phase {
|
||||||
|
Phase::ContractingY => {
|
||||||
|
if height <= MIN_HEIGHT {
|
||||||
|
*phase = ContractingX;
|
||||||
|
} else {
|
||||||
|
windows.height -= RESIZE_STEP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Phase::ContractingX => {
|
||||||
|
if width <= MIN_WIDTH {
|
||||||
|
*phase = ExpandingY;
|
||||||
|
} else {
|
||||||
|
windows.width -= RESIZE_STEP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Phase::ExpandingY => {
|
||||||
|
if height >= MAX_HEIGHT {
|
||||||
|
*phase = ExpandingX;
|
||||||
|
} else {
|
||||||
|
windows.height += RESIZE_STEP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Phase::ExpandingX => {
|
||||||
|
if width >= MAX_WIDTH {
|
||||||
|
*phase = ContractingY;
|
||||||
|
} else {
|
||||||
|
windows.width += RESIZE_STEP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_dimensions(dim: Res<Dimensions>, mut windows: ResMut<Windows>) {
|
||||||
|
if dim.is_changed() {
|
||||||
|
windows.get_primary_mut().unwrap().set_resolution(
|
||||||
|
dim.width.try_into().unwrap(),
|
||||||
|
dim.height.try_into().unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple 3d scene, taken from the `3d_scene` example
|
||||||
|
fn setup_3d(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
// plane
|
||||||
|
commands.spawn_bundle(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
// cube
|
||||||
|
commands.spawn_bundle(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||||
|
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
// light
|
||||||
|
commands.spawn_bundle(PointLightBundle {
|
||||||
|
point_light: PointLight {
|
||||||
|
intensity: 1500.0,
|
||||||
|
shadows_enabled: true,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
// camera
|
||||||
|
commands.spawn_bundle(PerspectiveCameraBundle {
|
||||||
|
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple 2d scene, taken from the `rect` example
|
||||||
|
fn setup_2d(mut commands: Commands) {
|
||||||
|
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||||
|
commands.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite {
|
||||||
|
color: Color::rgb(0.25, 0.25, 0.75),
|
||||||
|
custom_size: Some(Vec2::new(50.0, 50.0)),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue