abrasion/engine/src/render/vulkan/swapchains.rs

86 lines
2.8 KiB
Rust

use std::sync::Arc;
use vulkano::swapchain as vs;
use vulkano::image as vm;
use vulkano::format as vf;
use vulkano::sync as vy;
pub struct Swapchains<WT> {
chain: Arc<vs::Swapchain<WT>>,
images: Vec<Arc<vm::SwapchainImage<WT>>>,
}
impl<WT> Swapchains<WT> {
pub fn new(binding: &super::binding::Binding<WT>) -> Self {
let physical_device = binding.physical_device();
let capabilities = binding.surface.capabilities(physical_device).expect("could not get capabilities");
let surface_format = Self::choose_swap_surface_format(&capabilities.supported_formats);
let present_mode = Self::choose_swap_present_mode(capabilities.present_modes);
let extent = Self::choose_swap_extent(&capabilities);
let mut image_count = capabilities.min_image_count + 1;
if let Some(max_image_count) = capabilities.max_image_count {
if image_count > max_image_count {
image_count = max_image_count;
}
}
let image_usage = vm::ImageUsage {
color_attachment: true,
.. vm::ImageUsage::none()
};
let indices = super::qfi::QueueFamilyIndices::find(&binding.surface, &physical_device).unwrap();
let sharing: vy::SharingMode = if indices.graphics_family != indices.present_family {
vec![&binding.graphics_queue, &binding.present_queue].as_slice().into()
} else {
(&binding.graphics_queue).into()
};
let (chain, images) = vs::Swapchain::new(
binding.device.clone(),
binding.surface.clone(),
image_count,
surface_format.0,
extent,
1,
image_usage,
sharing,
capabilities.current_transform,
vs::CompositeAlpha::Opaque,
present_mode,
true,
None,
).expect("could not create swap chain");
Self {
chain, images
}
}
fn choose_swap_surface_format(available_formats: &[(vf::Format, vs::ColorSpace)]) -> (vf::Format, vs::ColorSpace) {
*available_formats.iter()
.find(|(format, color_space)|
*format == vf::Format::B8G8R8A8Unorm && *color_space == vs::ColorSpace::SrgbNonLinear
)
.unwrap_or_else(|| &available_formats[0])
}
fn choose_swap_present_mode(available_present_modes: vs::SupportedPresentModes) -> vs::PresentMode {
if available_present_modes.mailbox {
vs::PresentMode::Mailbox
} else if available_present_modes.immediate {
vs::PresentMode::Immediate
} else {
vs::PresentMode::Fifo
}
}
fn choose_swap_extent(capabilities: &vs::Capabilities) -> [u32; 2] {
capabilities.current_extent.expect("could not get current extent")
}
}