bevyengine / bevyengine/bevy

# Changing `WindowResolution` doesn't impact the window properly inside `bevy_winit`

Open
#24,724 1 comment 0 reactions 0 assignees View on GitHub
A-Windowing C-Bug D-Straightforward S-Ready-For-Implementation
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 16h
Merged PRs (30d)
171

Description

## Bevy version and features

```toml
bevy = { version = "0.19" }
```

## Relevant system information
- cargo 1.96.0 (30a34c682 2026-05-25)
- Latest CachyOS, KDE

```
AdapterInfo { name: "AMD Radeon RX 9070 XT (RADV GFX1201)", vendor: 4098, device: 30032, device_type: DiscreteGpu, device_pci_bus_id: "0000:03:00.0", driver: "radv", driver_info: "Mesa 26.1.2-arch3.1", backend: Vulkan, subgroup_min_size: 32, subgroup_max_size: 64, transient_saves_memory: false }
```

## What you did

I'm working on a pixel-style game and I'm trying to utilizing resolution scaling for that.
I want to keep my logical resolution as 640x360 at all times, while overriding the scale factor, which should scale the physical resolution.

Below is a MRE of what I'm doing: setting the physical resolution to 1280x720 and the `scale_factor_override` to `Some(2.0)`:
```rust
use bevy::input::common_conditions::input_just_pressed;
use bevy::prelude::*;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, startup)
.add_systems(
Update,
(
update_resolution_text,
change_resolution.run_if(input_just_pressed(KeyCode::Space)),
reset_resolution.run_if(input_just_pressed(KeyCode::Escape)),
),
)
.run();
}

fn startup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn(Text::default());
commands.spawn((
Text2d::new("I'm at [0, -180]"),
Transform::from_translation(vec3(0.0, -180.0, 0.0)),
));
}
fn reset_resolution(mut q_window: Query<&mut Window>) {
let mut bevy_window = q_window.single_mut().unwrap();
bevy_window.resolution.set_scale_factor_override(None);
bevy_window.resolution.set_physical_resolution(1280, 720);
}
fn change_resolution(mut q_window: Query<&mut Window>) {
let mut bevy_window = q_window.single_mut().unwrap();
bevy_window.resolution.set_scale_factor_override(Some(2.0));
bevy_window.resolution.set_physical_resolution(1280, 720);
// After setting the above I expect a window with HD size, but 640x360 internal resolution
}
/// Only for informative purposes, to display the current window state.
fn update_resolution_text(mut q_text: Query<&mut Text>, q_window: Query<&Window>) {
let res = q_window.single().unwrap().resolution.clone();

q_text.single_mut().unwrap().0 = format!(
"Logical size: {}\nPhysical size: {}\nBase scale: {}\nScale override: {:?}",
res.size(),
res.physical_size(),
res.base_scale_factor(),
res.scale_factor_override()
);
}
```

## What went wrong

My expectation would be that I get a window of HD (physical) size and 640x360 logical size.
As a visual check, I've put a Text entity at \[0, -180\], which should place it just at the bottom of the window.

What happens is that I get a window with physical size: 2560x1440 (double 1280x720) and logical size: 1280x720.
Only after calling the system and changing the resolution *an additional time* do I get the desired effect.
(If I were to request 1920x1080 with override=3.0 I would get the FHD logical size and triple that in physical size).

This to me is a bug (or at least an unexpected behaviour).
The requested `WindowResolution` should be resolved to the same window state regardless of the state it's requested in.

I believe the culprit is in https://github.com/bevyengine/bevy/blob/097fc03ce5c767c303b882a7d4fcb919ccfdb6d4/crates/bevy_winit/src/system.rs#L305.

I'm happy to work on this and provide a PR, but I'd like to first confirm that this is reproducible for others and we have an agreement of the desired behaviour.

## Additional information

I'm also pretty sure that there is another bug in this `WindowResolution` handling.
If I were to, instead of `bevy_window.resolution.set_scale_factor_override(Some(2.0))`, set the *base* scale factor with `bevy_window.resolution.set_scale_factor(2.0)` then (with the default initial window resolution of 1280x720) it would have no effect on the window state.
Only after resizing the window manually (or setting it to a different value than the current one) I will get the scaling factor effect.
So it looks like: if the physical resolution was not changed, the `base_scale_factor` will have no effect.

Contributor guide

Open the contributing guide

Research direction

Reproduce the MRE and start at crates/bevy_winit/src/system.rs around line 305, then trace how WindowResolution updates are applied. Verify both the scale-factor override and base scale-factor cases from the reported initial state. Done means a single resolution update produces the requested physical and logical sizes consistently, without requiring a second change.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
desktop-dev, game-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.