Skip to content

Commit

Permalink
Fix for incorrectly sized x11 windows on AMD
Browse files Browse the repository at this point in the history
  • Loading branch information
attackgoat committed Oct 20, 2022
1 parent 0833da3 commit f075dc7
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 40 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [0.6.2] - 2022-10-20

### Fixed

- Crash/device lost while resizing the window
- Inconsistent frame timing on certain drivers
- Incorrect window size on certain drivers

### Added

Expand Down Expand Up @@ -211,4 +212,5 @@ _See [#25](https://github.com/attackgoat/screen-13/pull/25) for migration detail
[0.4.2]: https://crates.io/crates/screen-13/0.4.2
[0.5.0]: https://crates.io/crates/screen-13/0.5.0
[0.6.0]: https://crates.io/crates/screen-13/0.6.0
[0.6.1]: https://crates.io/crates/screen-13/0.6.1
[0.6.1]: https://crates.io/crates/screen-13/0.6.1
[0.6.2]: https://crates.io/crates/screen-13/0.6.2
35 changes: 5 additions & 30 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use {
super::{
driver::{
image_access_layout, CommandBuffer, Device, DriverError, Swapchain, SwapchainError,
SwapchainImage,
},
driver::{image_access_layout, CommandBuffer, Device, DriverError, SwapchainImage},
graph::{node::SwapchainImageNode, RenderGraph, ResolverPool},
},
ash::vk,
Expand All @@ -22,17 +19,11 @@ pub struct Display {
cmd_buf_idx: usize,
cmd_bufs: Vec<CommandBuffer>,
pool: Box<dyn ResolverPool>,
swapchain: Swapchain,
}

impl Display {
/// Constructs a new `Display` object.
pub fn new(
device: &Arc<Device>,
pool: Box<dyn ResolverPool>,
swapchain: Swapchain,
cmd_buf_count: usize,
) -> Self {
pub fn new(device: &Arc<Device>, pool: Box<dyn ResolverPool>, cmd_buf_count: usize) -> Self {
let mut cmd_bufs = Vec::with_capacity(cmd_buf_count);
for _ in 0..cmd_buf_count {
cmd_bufs.push(CommandBuffer::create(device, device.queue.family).unwrap());
Expand All @@ -42,17 +33,9 @@ impl Display {
cmd_buf_idx: 0,
cmd_bufs,
pool,
swapchain,
}
}

/// Returns a new `RenderGraph` with a bound swapchain image, if possible.
pub fn acquire_next_image(&mut self) -> Result<SwapchainImage, SwapchainError> {
trace!("acquire_next_image");

self.swapchain.acquire_next_image()
}

unsafe fn begin(cmd_buf: &mut CommandBuffer) -> Result<(), ()> {
cmd_buf
.device
Expand All @@ -69,11 +52,11 @@ impl Display {
}

/// Displays the given swapchain image using passes specified in `render_graph`, if possible.
pub fn present_image(
pub fn resolve_image(
&mut self,
render_graph: RenderGraph,
swapchain_image: SwapchainImageNode,
) -> Result<(), DisplayError> {
) -> Result<SwapchainImage, DisplayError> {
use std::slice::from_ref;

trace!("present_image");
Expand Down Expand Up @@ -149,13 +132,11 @@ impl Display {
let elapsed = Instant::now() - started;
trace!("🔜🔜🔜 vkQueueSubmit took {} μs", elapsed.as_micros(),);

self.swapchain.present_image(swapchain_image);

// Store the resolved graph because it contains bindings, leases, and other shared resources
// that need to be kept alive until the fence is waited upon.
CommandBuffer::push_fenced_drop(cmd_buf, resolver);

Ok(())
Ok(swapchain_image)
}

unsafe fn submit(
Expand Down Expand Up @@ -221,12 +202,6 @@ impl From<DriverError> for DisplayError {
}
}

impl From<SwapchainError> for DisplayError {
fn from(_: SwapchainError) -> Self {
Self::DeviceLost
}
}

impl std::fmt::Display for DisplayError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
Expand Down
2 changes: 1 addition & 1 deletion src/driver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub(crate) use self::{
},
shader::{DescriptorBinding, DescriptorBindingMap, DescriptorInfo},
surface::Surface,
swapchain::{Swapchain, SwapchainError, SwapchainImage, SwapchainInfo},
swapchain::{Swapchain, SwapchainImage, SwapchainInfo},
};

use {
Expand Down
15 changes: 14 additions & 1 deletion src/driver/swapchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use {
pub struct Swapchain {
device: Arc<Device>,
images: Vec<Option<Image>>,
pub info: SwapchainInfo,
info: SwapchainInfo,
next_semaphore: usize,
acquired_semaphores: Vec<vk::Semaphore>,
rendered_semaphores: Vec<vk::Semaphore>, // TODO: make a single semaphore
Expand Down Expand Up @@ -127,6 +127,10 @@ impl Swapchain {
}
}

pub fn info(&self) -> SwapchainInfo {
self.info
}

pub fn present_image(&mut self, image: SwapchainImage) {
let present_info = vk::PresentInfoKHR::builder()
.wait_semaphores(slice::from_ref(&image.rendered))
Expand Down Expand Up @@ -336,6 +340,13 @@ impl Swapchain {
Ok(())
}

pub fn set_info(&mut self, info: SwapchainInfo) {
if self.info != info {
self.info = info;
self.suboptimal = true;
}
}

fn clamp_desired_image_count(
desired_image_count: u32,
surface_capabilities: vk::SurfaceCapabilitiesKHR,
Expand Down Expand Up @@ -401,8 +412,10 @@ impl Deref for SwapchainImage {
pub enum SwapchainError {
/// This frame is lost but more may be acquired later.
DeviceLost,

/// This frame is not lost but there may be a delay while the next frame is recreated.
Suboptimal,

/// The surface was lost and must be recreated, which includes any operating system window.
SurfaceLost,
}
Expand Down
22 changes: 16 additions & 6 deletions src/event_loop.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
super::{
display::{Display, DisplayError},
driver::{Device, Driver, DriverConfigBuilder, DriverError},
driver::{Device, Driver, DriverConfigBuilder, DriverError, Swapchain},
frame::FrameContext,
graph::{RenderGraph, ResolverPool},
pool::hash::HashPool,
Expand Down Expand Up @@ -40,6 +40,7 @@ pub struct EventLoop {

display: Display,
event_loop: winit::event_loop::EventLoop<()>,
swapchain: Swapchain,

/// Provides access to the current operating system window.
pub window: Window,
Expand Down Expand Up @@ -129,7 +130,14 @@ impl EventLoop {
dt_filtered = dt_filtered + (dt_raw - dt_filtered) / 10.0;
};

let swapchain_image = self.display.acquire_next_image();
// Update the window size if it changes
let window_size = self.window.inner_size();
let mut swapchain_info = self.swapchain.info();
swapchain_info.width = window_size.width;
swapchain_info.height = window_size.height;
self.swapchain.set_info(swapchain_info);

let swapchain_image = self.swapchain.acquire_next_image();
if swapchain_image.is_err() {
events.clear();

Expand Down Expand Up @@ -162,7 +170,8 @@ impl EventLoop {
((elapsed.as_secs_f32() / refresh_rate) * 100.0) as usize,
);

self.display.present_image(render_graph, swapchain_image)?;
let swapchain_image = self.display.resolve_image(render_graph, swapchain_image)?;
self.swapchain.present_image(swapchain_image);
}

Ok(())
Expand Down Expand Up @@ -351,19 +360,20 @@ impl EventLoopBuilder {
let pool = self
.resolver_pool
.unwrap_or_else(|| Box::new(HashPool::new(&driver.device)));
let display = Display::new(&driver.device, pool, driver.swapchain, self.cmd_buf_count);
let display = Display::new(&driver.device, pool, self.cmd_buf_count);

info!(
"display resolution: {}x{} ({}x scale)",
"Window dimensions: {}x{} ({}x scale)",
width,
height,
window.scale_factor() as f32,
);

Ok(EventLoop {
device: Arc::clone(&driver.device),
device: driver.device,
display,
event_loop: self.event_loop,
swapchain: driver.swapchain,
window,
})
}
Expand Down

0 comments on commit f075dc7

Please sign in to comment.