Skip to content

Commit

Permalink
Improve swapchain format API
Browse files Browse the repository at this point in the history
  • Loading branch information
attackgoat committed Dec 16, 2023
1 parent 94302fd commit b4c2198
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 35 deletions.
4 changes: 3 additions & 1 deletion contrib/screen-13-hot/examples/glsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ lazy_static! {
fn main() -> Result<(), DisplayError> {
pretty_env_logger::init();

let event_loop = EventLoop::new().build()?;
let event_loop = EventLoop::new()
.desired_surface_format(|formats| EventLoopBuilder::linear_surface_format(formats).unwrap())
.build()?;

// Create a compute pipeline - the same as normal except for "Hot" prefixes and we provide the
// shader source code path instead of the shader source code bytes
Expand Down
5 changes: 4 additions & 1 deletion examples/imgui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ fn main() -> Result<(), DisplayError> {
pretty_env_logger::init();

// Screen 13 things we need for this demo
let event_loop = EventLoop::new().desired_swapchain_image_count(2).build()?;
let event_loop = EventLoop::new()
.desired_surface_format(|formats| EventLoopBuilder::linear_surface_format(formats).unwrap())
.desired_swapchain_image_count(2)
.build()?;
let display = ComputePresenter::new(&event_loop.device)?;
let mut imgui = ImGui::new(&event_loop.device);
let mut pool = LazyPool::new(&event_loop.device);
Expand Down
4 changes: 3 additions & 1 deletion examples/rt_triangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ fn create_ray_trace_pipeline(device: &Arc<Device>) -> Result<Arc<RayTracePipelin
fn main() -> anyhow::Result<()> {
pretty_env_logger::init();

let event_loop = EventLoop::new().build()?;
let event_loop = EventLoop::new()
.desired_surface_format(|formats| EventLoopBuilder::linear_surface_format(formats).unwrap())
.build()?;
let mut pool = HashPool::new(&event_loop.device);

// ------------------------------------------------------------------------------------------ //
Expand Down
1 change: 1 addition & 0 deletions examples/transitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ fn main() -> anyhow::Result<()> {
// Create Screen 13 things any similar program might need
let event_loop = EventLoop::new()
.window(|builder| builder.with_inner_size(LogicalSize::new(1024.0f64, 768.0f64)))
.desired_surface_format(|formats| EventLoopBuilder::linear_surface_format(formats).unwrap())
.build()?;
let display = ComputePresenter::new(&event_loop.device)?;
let mut imgui = ImGui::new(&event_loop.device);
Expand Down
68 changes: 36 additions & 32 deletions src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use {
};

/// Function type for selection of swapchain surface image format.
pub type SelectSurfaceFormatFn = dyn FnOnce(&[vk::SurfaceFormatKHR]) -> usize;
pub type SelectSurfaceFormatFn = dyn FnOnce(&[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR;

/// Describes a screen mode for display.
pub enum FullscreenMode {
Expand Down Expand Up @@ -279,11 +279,13 @@ impl EventLoopBuilder {
}

/// A function to select the desired swapchain surface image format.
pub fn desired_surface_format(
mut self,
surface_format_fn: impl Into<Box<SelectSurfaceFormatFn>>,
) -> Self {
let surface_format_fn = surface_format_fn.into();
///
/// By default sRGB will be selected unless it is not available.
pub fn desired_surface_format<F>(mut self, surface_format_fn: F) -> Self
where
F: 'static + FnOnce(&[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR,
{
let surface_format_fn = Box::new(surface_format_fn);
self.surface_format_fn = Some(surface_format_fn);
self
}
Expand Down Expand Up @@ -473,18 +475,14 @@ impl EventLoopBuilder {
);
}

let surface_format_fn = self
.surface_format_fn
.unwrap_or_else(|| Box::new(Self::select_swapchain_format));
let mut surface_format_idx = surface_format_fn(&surface_formats);

if surface_format_idx >= surface_formats.len() {
warn!("invalid surface format selected");

surface_format_idx = 0;
}

let surface_format = surface_formats[surface_format_idx];
let surface_format_fn = self.surface_format_fn.unwrap_or_else(|| {
Box::new(|formats| {
Self::srgb_surface_format(formats)
.or_else(|| Self::linear_surface_format(formats))
.unwrap_or(formats[0])
})
});
let surface_format = surface_format_fn(&surface_formats);
let swapchain = Swapchain::new(
&device,
surface,
Expand All @@ -507,29 +505,35 @@ impl EventLoopBuilder {
})
}

fn select_swapchain_format(formats: &[vk::SurfaceFormatKHR]) -> usize {
for (idx, format) in formats.iter().copied().enumerate() {
if format.color_space != vk::ColorSpaceKHR::SRGB_NONLINEAR {
continue;
}

/// Helper function to automatically select the best UNORM format.
pub fn linear_surface_format(formats: &[vk::SurfaceFormatKHR]) -> Option<vk::SurfaceFormatKHR> {
for swapchain in formats.iter().copied() {
if matches!(
format.format,
vk::Format::R8G8B8A8_SRGB | vk::Format::B8G8R8A8_SRGB
swapchain.format,
vk::Format::R8G8B8A8_UNORM | vk::Format::B8G8R8A8_UNORM
) {
return idx;
return Some(swapchain);
}
}

for (idx, format) in formats.iter().copied().enumerate() {
None
}

/// Helper function to automatically select the best sRGB format.
pub fn srgb_surface_format(formats: &[vk::SurfaceFormatKHR]) -> Option<vk::SurfaceFormatKHR> {
for swapchain in formats.iter().copied() {
if swapchain.color_space != vk::ColorSpaceKHR::SRGB_NONLINEAR {
continue;
}

if matches!(
format.format,
vk::Format::R8G8B8A8_UNORM | vk::Format::B8G8R8A8_UNORM
swapchain.format,
vk::Format::R8G8B8A8_SRGB | vk::Format::B8G8R8A8_SRGB
) {
return idx;
return Some(swapchain);
}
}

0
None
}
}

0 comments on commit b4c2198

Please sign in to comment.