vulkan_lib/vulkan-rs/src/swapchain.rs

336 lines
8.9 KiB
Rust
Raw Normal View History

2023-01-14 12:03:01 +00:00
use crate::prelude::*;
use anyhow::Result;
use std::cmp;
2024-03-28 20:30:06 +00:00
use std::sync::Mutex;
2023-01-14 12:03:01 +00:00
2023-04-09 21:19:41 +00:00
pub enum NextImageSynchronization<'a> {
2024-03-28 17:28:52 +00:00
Semaphore(&'a Semaphore<'a>),
Fence(&'a Fence<'a>),
2023-04-09 21:19:41 +00:00
}
2024-03-28 17:28:52 +00:00
impl<'a> From<&'a Semaphore<'a>> for NextImageSynchronization<'a> {
fn from(value: &'a Semaphore<'a>) -> Self {
2023-04-09 21:19:41 +00:00
Self::Semaphore(value)
}
}
2024-03-28 17:28:52 +00:00
impl<'a> From<&'a Fence<'a>> for NextImageSynchronization<'a> {
fn from(value: &'a Fence<'a>) -> Self {
2023-04-09 21:19:41 +00:00
Self::Fence(value)
}
}
2023-01-14 12:03:01 +00:00
#[derive(Debug)]
2024-03-28 17:28:52 +00:00
pub struct Swapchain<'a> {
width: u32,
height: u32,
index: u32,
2023-01-14 12:03:01 +00:00
2024-03-28 17:28:52 +00:00
device: &'a Device,
surface: Surface<'a>,
2023-01-14 12:03:01 +00:00
2024-03-28 17:28:52 +00:00
create_info: VkSwapchainCreateInfoKHR,
swapchain: VkSwapchainKHR,
2023-01-14 12:03:01 +00:00
usage: VkImageUsageFlagBits,
raw: bool,
}
2024-03-28 17:28:52 +00:00
impl<'a> Swapchain<'a> {
2023-01-14 12:03:01 +00:00
pub fn new(
2024-03-28 17:28:52 +00:00
device: &'a Device,
surface: Surface<'a>,
2023-01-14 12:03:01 +00:00
vsync: bool,
image_count: u32,
image_usage: impl Into<VkImageUsageFlagBits>,
prefered_format: VkFormat,
array_layers: u32,
2024-03-28 17:28:52 +00:00
) -> Result<Swapchain<'a>> {
2023-01-14 12:03:01 +00:00
let surface_caps = surface.capabilities(&device)?;
let extent = if surface_caps.currentExtent.width == u32::max_value() {
return Err(anyhow::Error::msg("Surface has no extent"));
} else {
VkExtent2D {
width: surface_caps.currentExtent.width,
height: surface_caps.currentExtent.height,
}
};
let mut present_mode = VK_PRESENT_MODE_FIFO_KHR;
if !vsync {
for present_mode_iter in surface.present_modes(&device)? {
if present_mode_iter == VK_PRESENT_MODE_MAILBOX_KHR {
present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
break;
} else if present_mode_iter == VK_PRESENT_MODE_IMMEDIATE_KHR {
present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
}
}
}
let swapchain_image_count = if surface_caps.maxImageCount < surface_caps.minImageCount {
cmp::max(image_count, surface_caps.minImageCount)
} else {
cmp::max(
cmp::min(image_count, surface_caps.maxImageCount),
surface_caps.minImageCount,
)
};
let pretransform =
if (surface_caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0 {
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR.into()
} else {
surface_caps.currentTransform
};
let (format, colorspace) = surface.format_colorspace(&device, prefered_format)?;
let swapchain_ci = VkSwapchainCreateInfoKHR::new(
0,
surface.vk_handle(),
swapchain_image_count,
format,
colorspace,
extent,
array_layers,
image_usage,
VK_SHARING_MODE_EXCLUSIVE,
&[],
pretransform,
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
present_mode,
device.physical_device().features().shaderClipDistance,
);
let swapchain = device.create_swapchain(&swapchain_ci)?;
2024-03-28 17:28:52 +00:00
Ok(Swapchain {
2024-03-28 20:30:06 +00:00
width: extent.width,
height: extent.height,
2023-01-14 12:03:01 +00:00
usage: swapchain_ci.imageUsage,
2024-03-28 20:30:06 +00:00
index: 0,
2023-01-14 12:03:01 +00:00
device,
2024-03-28 17:28:52 +00:00
surface,
2023-01-14 12:03:01 +00:00
2024-03-28 20:30:06 +00:00
create_info: swapchain_ci,
2023-01-14 12:03:01 +00:00
2024-03-28 20:30:06 +00:00
swapchain,
2023-01-14 12:03:01 +00:00
raw: false,
2024-03-28 17:28:52 +00:00
})
2023-01-14 12:03:01 +00:00
}
2024-03-28 20:30:06 +00:00
pub fn from_ci(device: &'a Device, swapchain_ci: &VkSwapchainCreateInfoKHR) -> Result<Self> {
2024-03-28 17:28:52 +00:00
Ok(Swapchain {
width: swapchain_ci.imageExtent.width,
height: swapchain_ci.imageExtent.height,
2023-11-29 11:20:28 +00:00
usage: swapchain_ci.imageUsage,
2024-03-28 17:28:52 +00:00
index: 0,
2023-11-29 11:20:28 +00:00
surface: Surface::from_vk_surface(
swapchain_ci.surface,
device.physical_device().instance(),
),
2024-03-28 17:28:52 +00:00
create_info: swapchain_ci.clone(),
2023-11-29 11:20:28 +00:00
2024-03-28 17:28:52 +00:00
swapchain: device.create_swapchain(swapchain_ci)?,
2023-11-29 11:20:28 +00:00
device,
raw: false,
2024-03-28 17:28:52 +00:00
})
2023-01-14 12:03:01 +00:00
}
pub fn from_raw(
2024-03-28 17:28:52 +00:00
device: &'a Device,
2023-01-14 12:03:01 +00:00
swapchain_ci: &VkSwapchainCreateInfoKHR,
swapchain: VkSwapchainKHR,
2024-03-28 17:28:52 +00:00
) -> Self {
Swapchain {
width: swapchain_ci.imageExtent.width,
height: swapchain_ci.imageExtent.height,
2023-01-14 12:03:01 +00:00
usage: swapchain_ci.imageUsage,
2024-03-28 17:28:52 +00:00
index: 0,
2023-01-14 12:03:01 +00:00
surface: Surface::from_vk_surface(
swapchain_ci.surface,
device.physical_device().instance(),
),
device,
2024-03-28 17:28:52 +00:00
create_info: swapchain_ci.clone(),
swapchain,
2023-01-14 12:03:01 +00:00
raw: true,
2024-03-28 17:28:52 +00:00
}
2023-01-14 12:03:01 +00:00
}
2024-03-28 20:30:06 +00:00
pub fn recreate(&mut self) -> Result<()> {
2023-01-14 12:03:01 +00:00
// wait for the device to get idle
self.device.wait_idle()?;
2024-03-28 20:30:06 +00:00
let surface_caps = self.surface.capabilities(self.device)?;
2023-01-14 12:03:01 +00:00
let extent = if surface_caps.currentExtent.width == u32::max_value()
|| surface_caps.currentExtent.height == u32::max_value()
{
return Err(anyhow::Error::msg("Surface has no extent"));
} else if surface_caps.currentExtent.width == 0 || surface_caps.currentExtent.height == 0 {
// don't recreate swapchain
return Ok(());
} else {
VkExtent2D {
width: surface_caps.currentExtent.width,
height: surface_caps.currentExtent.height,
}
};
2024-03-28 20:30:06 +00:00
let mut swapchain_ci = self.create_info.clone();
2023-01-14 12:03:01 +00:00
swapchain_ci.imageExtent = extent;
2024-03-28 20:30:06 +00:00
swapchain_ci.set_old_swapchain(self.swapchain);
2023-01-14 12:03:01 +00:00
let swapchain = self.device.create_swapchain(&swapchain_ci)?;
// destroy the old swapchain
self.destroy();
// replace swapchain
2024-03-28 20:30:06 +00:00
self.swapchain = swapchain;
2023-01-14 12:03:01 +00:00
// set new surface size
2024-03-28 20:30:06 +00:00
self.width = extent.width;
self.height = extent.height;
2023-01-14 12:03:01 +00:00
Ok(())
}
2024-03-28 17:28:52 +00:00
pub fn acquire_next_image<'b>(
2024-03-28 20:30:06 +00:00
&mut self,
2023-01-14 12:03:01 +00:00
time_out: u64,
2024-03-28 17:28:52 +00:00
synchro: impl Into<NextImageSynchronization<'b>>,
2023-01-14 12:03:01 +00:00
) -> Result<OutOfDate<u32>> {
2023-04-09 21:19:41 +00:00
let synchro = synchro.into();
2023-01-14 12:03:01 +00:00
let res = self.device.acquire_next_image(
2024-03-28 20:30:06 +00:00
self.swapchain,
2023-01-14 12:03:01 +00:00
time_out,
2023-04-09 21:19:41 +00:00
match synchro {
NextImageSynchronization::Semaphore(semaphore) => Some(semaphore.vk_handle()),
NextImageSynchronization::Fence(_) => None,
},
match synchro {
NextImageSynchronization::Semaphore(_) => None,
NextImageSynchronization::Fence(fence) => Some(fence.vk_handle()),
},
2023-01-14 12:03:01 +00:00
);
if let Ok(r) = &res {
if let OutOfDate::Ok(i) = r {
2024-03-28 20:30:06 +00:00
self.index = *i;
2023-01-14 12:03:01 +00:00
}
}
res
}
/// set current
/// only use when externally acquired next index !!!
2024-03-28 20:30:06 +00:00
pub unsafe fn set_image_index(&mut self, index: u32) {
self.index = index;
2023-01-14 12:03:01 +00:00
}
pub fn current_index(&self) -> u32 {
2024-03-28 20:30:06 +00:00
self.index
2023-01-14 12:03:01 +00:00
}
pub fn vk_images(&self) -> Result<Vec<VkImage>> {
2024-03-28 20:30:06 +00:00
self.device.swapchain_images(self.swapchain)
2023-01-14 12:03:01 +00:00
}
pub fn wrap_images(
&self,
images: &[VkImage],
2024-03-28 20:30:06 +00:00
queue: &'a Mutex<Queue<'a>>,
2023-01-14 12:03:01 +00:00
assume_layout: bool,
2024-03-28 17:28:52 +00:00
) -> Result<Vec<Image<'a>>> {
2023-01-14 12:03:01 +00:00
let format = self.format();
let tiling = VK_IMAGE_TILING_OPTIMAL;
if !Image::check_configuration(&self.device, tiling, format, self.usage) {
return Err(anyhow::Error::msg(format!(
"Image configuration not allowed (tiling: {:?}, format: {:?}, usage: {:?})",
tiling, format, self.usage,
)));
}
let mut swapchain_images = Vec::new();
for image in images {
swapchain_images.push(
Image::from_preinitialized(
*image,
format,
self.width(),
self.height(),
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
self.usage,
assume_layout,
)
2024-03-28 17:28:52 +00:00
.attach_sampler(Sampler::nearest_sampler().build(self.device)?)
2023-01-14 12:03:01 +00:00
.build(&self.device, queue)?,
);
}
Ok(swapchain_images)
}
pub fn width(&self) -> u32 {
2024-03-28 17:28:52 +00:00
self.width
2023-01-14 12:03:01 +00:00
}
pub fn height(&self) -> u32 {
2024-03-28 17:28:52 +00:00
self.height
2023-01-14 12:03:01 +00:00
}
pub fn format(&self) -> VkFormat {
2024-03-28 17:28:52 +00:00
self.create_info.imageFormat
2023-01-14 12:03:01 +00:00
}
#[inline]
fn destroy(&self) {
2024-03-28 17:28:52 +00:00
self.device.destroy_swapchain(self.swapchain)
2023-01-14 12:03:01 +00:00
}
}
2024-03-28 17:28:52 +00:00
impl<'a> VulkanDevice for Swapchain<'a> {
fn device(&self) -> &Device {
2023-01-14 12:03:01 +00:00
&self.device
}
}
2024-03-28 17:28:52 +00:00
impl<'a> VkHandle<VkSwapchainKHR> for Swapchain<'a> {
2023-01-14 12:03:01 +00:00
fn vk_handle(&self) -> VkSwapchainKHR {
2024-03-28 17:28:52 +00:00
self.swapchain
2023-01-14 12:03:01 +00:00
}
}
2024-03-28 17:28:52 +00:00
impl<'a> VkHandle<VkSwapchainKHR> for &'a Swapchain<'a> {
2023-01-14 12:03:01 +00:00
fn vk_handle(&self) -> VkSwapchainKHR {
2024-03-28 17:28:52 +00:00
self.swapchain
2023-01-14 12:03:01 +00:00
}
}
2024-03-28 17:28:52 +00:00
impl<'a> Drop for Swapchain<'a> {
2023-01-14 12:03:01 +00:00
fn drop(&mut self) {
if !self.raw {
self.destroy();
}
}
}