148 lines
No EOL
4.6 KiB
Rust
148 lines
No EOL
4.6 KiB
Rust
|
|
use anyhow::Result;
|
|
use winit::window::Window;
|
|
|
|
use vulkanalia::prelude::v1_0::*;
|
|
|
|
// extension imports
|
|
use vulkanalia::vk::KhrSurfaceExtension;
|
|
use vulkanalia::vk::KhrSwapchainExtension;
|
|
|
|
use crate::app_data;
|
|
use crate::queue_family_indices;
|
|
use crate::image;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct SwapchainSupport {
|
|
pub capabilities: vk::SurfaceCapabilitiesKHR,
|
|
pub formats: Vec<vk::SurfaceFormatKHR>,
|
|
pub present_modes: Vec<vk::PresentModeKHR>,
|
|
}
|
|
|
|
impl SwapchainSupport {
|
|
pub unsafe fn get(
|
|
instance: &Instance,
|
|
data: &app_data::AppData,
|
|
physical_device: vk::PhysicalDevice,
|
|
) -> Result<Self> {
|
|
Ok(Self {
|
|
capabilities: instance
|
|
.get_physical_device_surface_capabilities_khr(
|
|
physical_device, data.surface)?,
|
|
formats: instance
|
|
.get_physical_device_surface_formats_khr(
|
|
physical_device, data.surface)?,
|
|
present_modes: instance
|
|
.get_physical_device_surface_present_modes_khr(
|
|
physical_device, data.surface)?,
|
|
})
|
|
}
|
|
}
|
|
|
|
pub fn get_swapchain_surface_format(
|
|
formats: &[vk::SurfaceFormatKHR],
|
|
) -> vk::SurfaceFormatKHR {
|
|
formats
|
|
.iter()
|
|
.cloned()
|
|
.find(|f| {
|
|
f.format == vk::Format::B8G8R8A8_SRGB
|
|
&& f.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
|
|
})
|
|
.unwrap_or_else(|| formats[0])
|
|
}
|
|
|
|
pub fn get_swapchain_present_mode(
|
|
present_modes: &[vk::PresentModeKHR],
|
|
) -> vk::PresentModeKHR {
|
|
present_modes
|
|
.iter()
|
|
.cloned()
|
|
.find(|m| *m == vk::PresentModeKHR::MAILBOX)
|
|
.unwrap_or(vk::PresentModeKHR::FIFO)
|
|
}
|
|
|
|
pub fn get_swapchain_extent(
|
|
window: &Window,
|
|
capabilities: vk::SurfaceCapabilitiesKHR,
|
|
) -> vk::Extent2D {
|
|
if capabilities.current_extent.width != u32::MAX {
|
|
capabilities.current_extent
|
|
} else {
|
|
vk::Extent2D::builder()
|
|
.width(window.inner_size().width.clamp(
|
|
capabilities.min_image_extent.width,
|
|
capabilities.max_image_extent.width,
|
|
))
|
|
.height(window.inner_size().height.clamp(
|
|
capabilities.min_image_extent.height,
|
|
capabilities.max_image_extent.height,
|
|
))
|
|
.build()
|
|
}
|
|
}
|
|
|
|
pub unsafe fn create_swapchain(
|
|
window: &Window,
|
|
instance: &Instance,
|
|
device: &Device,
|
|
data: &mut app_data::AppData,
|
|
) -> Result<()> {
|
|
let indices = queue_family_indices::QueueFamilyIndices::get(instance, data, data.physical_device)?;
|
|
let support = SwapchainSupport::get(instance, data, data.physical_device)?;
|
|
|
|
let surface_format = get_swapchain_surface_format(&support.formats);
|
|
let present_mode = get_swapchain_present_mode(&support.present_modes);
|
|
let extent = get_swapchain_extent(window, support.capabilities);
|
|
|
|
let mut image_count = support.capabilities.min_image_count + 1;
|
|
if support.capabilities.max_image_count != 0
|
|
&& image_count > support.capabilities.max_image_count
|
|
{
|
|
image_count = support.capabilities.max_image_count;
|
|
}
|
|
|
|
let mut queue_family_indices = vec![];
|
|
let image_sharing_mode = if indices.graphics != indices.present {
|
|
queue_family_indices.push(indices.graphics);
|
|
queue_family_indices.push(indices.present);
|
|
vk::SharingMode::CONCURRENT
|
|
} else {
|
|
vk::SharingMode::EXCLUSIVE
|
|
};
|
|
|
|
let info = vk::SwapchainCreateInfoKHR::builder()
|
|
.surface(data.surface)
|
|
.min_image_count(image_count)
|
|
.image_format(surface_format.format)
|
|
.image_color_space(surface_format.color_space)
|
|
.image_extent(extent)
|
|
.image_array_layers(1)
|
|
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
|
.image_sharing_mode(image_sharing_mode)
|
|
.queue_family_indices(&queue_family_indices)
|
|
.pre_transform(support.capabilities.current_transform)
|
|
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
|
|
.present_mode(present_mode)
|
|
.clipped(true)
|
|
.old_swapchain(vk::SwapchainKHR::null());
|
|
data.swapchain = device.create_swapchain_khr(&info, None)?;
|
|
data.swapchain_format = surface_format.format;
|
|
data.swapchain_extent = extent;
|
|
data.swapchain_images = device.get_swapchain_images_khr(data.swapchain)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub unsafe fn create_swapchain_image_views(
|
|
device: &Device,
|
|
data: &mut app_data::AppData,
|
|
) -> Result<()> {
|
|
data.swapchain_image_views = data
|
|
.swapchain_images
|
|
.iter()
|
|
.map(|i| image::create_image_view(device, *i, data.swapchain_format, vk::ImageAspectFlags::COLOR, 1))
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
Ok(())
|
|
} |