You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

150 lines
3.4 KiB

use crate::render::{
Conf, Device, OwnedImage, PhysicalDevice, Queue, Surface,
};
use ash::vk;
use std::rc::Rc;
pub struct Swapchain {
handle: vk::SwapchainKHR,
pub device: Rc<Device>,
pub surface: Rc<Surface>,
pub format: vk::Format,
pub extent: vk::Extent2D,
}
impl Swapchain {
pub fn create(
device: Rc<Device>,
phys_device: &PhysicalDevice,
surface: Rc<Surface>,
conf: &Conf,
queue_graphics: &Queue,
queue_surface: &Queue,
) -> Result<Rc<Self>, vk::Result> {
let capabilities = unsafe {
device.instance.surface_ext.get_physical_device_surface_capabilities(
**phys_device,
**surface,
)?
};
let formats = unsafe {
device
.instance
.surface_ext
.get_physical_device_surface_formats(**phys_device, **surface)?
};
let modes = unsafe {
device.instance.surface_ext.get_physical_device_surface_present_modes(
**phys_device,
**surface,
)?
};
let extent = if capabilities.current_extent.width != u32::max_value() {
capabilities.current_extent
} else {
vk::Extent2D {
width: capabilities
.min_image_extent
.width
.max(capabilities.max_image_extent.width),
height: capabilities
.min_image_extent
.height
.max(capabilities.max_image_extent.height),
}
};
let format = *formats
.iter()
.find(|format| {
format.format == vk::Format::B8G8R8A8_UNORM &&
format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
})
.unwrap_or_else(|| &formats[0]);
let mode = *modes
.iter()
.find(|&&mode| mode == conf.swap_mode.into())
.unwrap_or_else(|| &vk::PresentModeKHR::FIFO);
let min_image_count = capabilities.min_image_count + 1;
let min_image_count =
if capabilities.max_image_count > 0 &&
min_image_count > capabilities.max_image_count
{
capabilities.max_image_count
} else {
min_image_count
};
let queue_family_indices = [queue_graphics.index, queue_surface.index];
let create_info = vk::SwapchainCreateInfoKHR {
min_image_count,
present_mode: mode,
image_extent: extent,
surface: **surface,
image_format: format.format,
image_color_space: format.color_space,
image_array_layers: 1,
image_usage: vk::ImageUsageFlags::COLOR_ATTACHMENT,
image_sharing_mode: if queue_graphics.index != queue_surface.index {
vk::SharingMode::CONCURRENT
} else {
vk::SharingMode::EXCLUSIVE
},
queue_family_index_count: queue_family_indices.len() as u32,
p_queue_family_indices: queue_family_indices.as_ptr(),
pre_transform: capabilities.current_transform,
composite_alpha: vk::CompositeAlphaFlagsKHR::OPAQUE,
clipped: vk::TRUE,
..Default::default()
};
let handle =
unsafe { device.swapchain_ext.create_swapchain(&create_info, None)? };
Ok(Rc::new(Self {
handle,
device,
surface,
extent,
format: format.format,
}))
}
pub fn get_images(
this: Rc<Self>,
) -> Result<Vec<Rc<OwnedImage>>, vk::Result> {
let images = unsafe {
this.device.swapchain_ext.get_swapchain_images(this.handle)?
};
Ok(images
.iter()
.map(|&image| OwnedImage::own(this.clone(), image))
.collect())
}
}
impl Drop for Swapchain {
fn drop(&mut self) {
unsafe {
self.device.swapchain_ext.destroy_swapchain(self.handle, None);
}
}
}
impl std::ops::Deref for Swapchain {
type Target = vk::SwapchainKHR;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
// EOF