114 lines
3.6 KiB
Rust
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)
|
|
}
|