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::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, 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) }