Synvael/crates/renderer/src/swapchain.rs

114 lines
3.6 KiB
Rust

use crate::error::RendererError;
use ash::{Device, Instance, khr, vk};
/// Creates a swapchain and retrieves its images.
pub fn create_swapchain(
instance: &Instance,
physical_device: vk::PhysicalDevice,
device: &Device,
surface_loader: &khr::surface::Instance,
surface: vk::SurfaceKHR,
width: u32,
height: u32,
) -> Result<
(
khr::swapchain::Device,
vk::SwapchainKHR,
Vec<vk::Image>,
vk::Format,
vk::Extent2D,
),
RendererError,
> {
let surface_capabilities = unsafe {
surface_loader.get_physical_device_surface_capabilities(physical_device, surface)?
};
let surface_formats =
unsafe { surface_loader.get_physical_device_surface_formats(physical_device, surface)? };
let _surface_present_modes = unsafe {
surface_loader.get_physical_device_surface_present_modes(physical_device, surface)?
};
let format = surface_formats
.iter()
.find(|f| {
f.format == vk::Format::B8G8R8A8_SRGB
&& f.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
})
.unwrap_or(&surface_formats[0]);
let present_mode = vk::PresentModeKHR::FIFO;
let extent = if surface_capabilities.current_extent.width != u32::MAX {
surface_capabilities.current_extent
} else {
vk::Extent2D {
width: width.clamp(
surface_capabilities.min_image_extent.width,
surface_capabilities.max_image_extent.width,
),
height: height.clamp(
surface_capabilities.min_image_extent.height,
surface_capabilities.max_image_extent.height,
),
}
};
let image_count = if surface_capabilities.max_image_count > 0
&& surface_capabilities.min_image_count + 1 > surface_capabilities.max_image_count
{
surface_capabilities.max_image_count
} else {
surface_capabilities.min_image_count + 1
};
let swapchain_loader = khr::swapchain::Device::new(instance, device);
let create_info = vk::SwapchainCreateInfoKHR::default()
.surface(surface)
.min_image_count(image_count)
.image_format(format.format)
.image_color_space(format.color_space)
.image_extent(extent)
.image_array_layers(1)
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
.pre_transform(surface_capabilities.current_transform)
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
.present_mode(present_mode)
.clipped(true);
let swapchain = unsafe { swapchain_loader.create_swapchain(&create_info, None)? };
let images = unsafe { swapchain_loader.get_swapchain_images(swapchain)? };
Ok((swapchain_loader, swapchain, images, format.format, extent))
}
/// Creates image views for the swapchain images.
pub fn create_image_views(
device: &Device,
images: &[vk::Image],
format: vk::Format,
) -> Result<Vec<vk::ImageView>, RendererError> {
let mut views = Vec::with_capacity(images.len());
for &image in images {
let create_info = vk::ImageViewCreateInfo::default()
.image(image)
.view_type(vk::ImageViewType::TYPE_2D)
.format(format)
.subresource_range(vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
});
let view = unsafe { device.create_image_view(&create_info, None)? };
views.push(view);
}
Ok(views)
}