Use Arc to store reference and store dependencies for each vulkan types
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 0s

Arc it's used because later, i can use on multi-threaded programs
This commit is contained in:
Florian RICHER 2024-11-15 22:40:36 +01:00
parent 1cb9309a56
commit 174e12591c
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
5 changed files with 290 additions and 320 deletions

View file

@ -1,9 +1,12 @@
use crate::vulkan::{VkSurface, LOG_TARGET};
use std::sync::Arc;
use crate::vulkan::{VkDevice, VkInstance, VkPhysicalDevice, VkSurface, LOG_TARGET};
use ash::prelude::VkResult;
use ash::vk;
use crate::display::Window;
pub struct VkSwapchain {
pub(super) swapchain_loader: ash::khr::swapchain::Device,
surface: Arc<VkSurface>,
device: Arc<VkDevice>,
swapchain: Option<vk::SwapchainKHR>,
pub(super) desired_image_count: u32,
@ -11,70 +14,136 @@ pub struct VkSwapchain {
pub(super) surface_resolution: vk::Extent2D,
pub(super) present_mode: vk::PresentModeKHR,
pub(super) pre_transform: vk::SurfaceTransformFlagsKHR,
pub(super) present_images: Option<Vec<vk::Image>>,
pub(super) present_image_views: Option<Vec<vk::ImageView>>,
}
impl VkSwapchain {
pub(super) fn new(
swapchain_loader: ash::khr::swapchain::Device,
desired_image_count: u32,
surface_format: vk::SurfaceFormatKHR,
surface_resolution: vk::Extent2D,
present_mode: vk::PresentModeKHR,
pre_transform: vk::SurfaceTransformFlagsKHR,
) -> Self {
Self {
swapchain_loader,
pub(super) fn new<'a, 'b>(
window: &Window,
surface: Arc<VkSurface>,
device: Arc<VkDevice>,
physical_device: &VkPhysicalDevice,
) -> anyhow::Result<Self> {
log::debug!(target: LOG_TARGET, "Creating swapchain");
let (
surface_formats,
surface_capabilities,
present_modes
) = surface.get_physical_device_surface_infos(physical_device)?;
log::debug!(target: LOG_TARGET, "Supported surface formats by physical device: {surface_formats:#?}");
log::debug!(target: LOG_TARGET, "Surface capabilities: {surface_capabilities:#?}");
let surface_format = surface_formats
.first()
.and_then(|f| Some(*f))
.ok_or_else(|| anyhow::anyhow!("No available surface formats"))?;
log::debug!(target: LOG_TARGET, "Selected surface format: {surface_format:?}");
let mut desired_image_count = surface_capabilities.min_image_count + 1;
if surface_capabilities.max_image_count > 0
&& desired_image_count > surface_capabilities.max_image_count
{
desired_image_count = surface_capabilities.max_image_count;
}
log::debug!(target: LOG_TARGET, "Selected surface image count: {desired_image_count}");
let window_size = window.size()
.ok_or_else(|| anyhow::anyhow!("Window size is not valid"))?
.to_physical::<u32>(1.0);
log::debug!(target: LOG_TARGET, "Window size: {window_size:?}");
let surface_resolution = match surface_capabilities.current_extent.width {
u32::MAX => vk::Extent2D {
width: window_size.width,
height: window_size.height,
},
_ => surface_capabilities.current_extent,
};
log::debug!(target: LOG_TARGET, "Surface resolution: {surface_resolution:?}");
let pre_transform = if surface_capabilities
.supported_transforms
.contains(vk::SurfaceTransformFlagsKHR::IDENTITY)
{
vk::SurfaceTransformFlagsKHR::IDENTITY
} else {
surface_capabilities.current_transform
};
let present_mode = present_modes
.iter()
.cloned()
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
.unwrap_or(vk::PresentModeKHR::FIFO);
let mut swapchain = Self {
surface,
device,
desired_image_count,
surface_format,
surface_resolution,
present_mode,
pre_transform,
swapchain: None,
}
present_images: None,
present_image_views: None,
};
swapchain.create_swapchain()?;
Ok(swapchain)
}
pub(super) fn create_swapchain(&mut self, surface: &VkSurface) -> VkResult<()> {
let mut swapchain_create_info = self.create_swapchain_info(surface);
pub(super) fn create_swapchain(&mut self) -> VkResult<()> {
let mut swapchain_create_info = self.create_swapchain_info(&self.surface);
if let Some(old_swapchain) = self.swapchain {
swapchain_create_info.old_swapchain = old_swapchain;
}
let swapchain = unsafe {
self.swapchain_loader.create_swapchain(&swapchain_create_info, None)?
self.device.swapchain_loader.create_swapchain(&swapchain_create_info, None)?
};
match self.swapchain {
Some(_) => log::debug!(target: LOG_TARGET, "Swapchain created : {swapchain_create_info:#?}"),
None => log::debug!(target: LOG_TARGET, "Swapchain updated : {swapchain_create_info:#?}")
let present_images = unsafe { self.device.swapchain_loader.get_swapchain_images(swapchain)? };
let present_images_view = present_images
.iter()
.map(|i| {
self.device.create_image_view(*i, self.surface_format)
.expect("Failed to create image view")
})
.collect::<Vec<_>>();
if log::log_enabled!(target: LOG_TARGET, log::Level::Debug) {
let label = match self.swapchain {
None => "Swapchain created",
Some(_) => "Swapchain updated"
};
log::debug!(target: LOG_TARGET, "{label} ({swapchain:?}) : {swapchain_create_info:#?}");
}
self.swapchain = Some(swapchain);
self.present_image_views = Some(present_images_view);
self.present_images = Some(present_images);
Ok(())
}
pub(super) fn update_resolution(&mut self, surface: &VkSurface, width: u32, height: u32) -> VkResult<()> {
pub(super) fn update_resolution(&mut self, width: u32, height: u32) -> VkResult<()> {
log::debug!(target: LOG_TARGET, "New resolution requested for swapchain {width}x{height}");
self.surface_resolution = vk::Extent2D {
width,
height,
};
self.create_swapchain(surface)?;
self.create_swapchain()?;
Ok(())
}
pub(super) fn get_swapchain_images(&self) -> anyhow::Result<Vec<vk::Image>> {
let swapchain = self.swapchain
.ok_or_else(|| anyhow::anyhow!("Can't get swapchain images : Swapchain is not set"))?;
let images = unsafe { self.swapchain_loader.get_swapchain_images(swapchain)? };
Ok(images)
}
fn create_swapchain_info(&self, surface: &VkSurface) -> vk::SwapchainCreateInfoKHR {
vk::SwapchainCreateInfoKHR::default()
.surface(surface.surface)
@ -91,18 +160,17 @@ impl VkSwapchain {
.image_array_layers(1)
}
fn drop_current_swapchain(&mut self) {
fn drop_swapchain(&mut self) {
if let Some(swapchain) = self.swapchain {
unsafe {
self.swapchain_loader.destroy_swapchain(swapchain, None);
self.swapchain = None;
}
unsafe { self.device.swapchain_loader.destroy_swapchain(swapchain, None); }
self.swapchain = None;
log::debug!(target: LOG_TARGET, "Swapchain destroyed ({swapchain:?})");
}
}
}
impl Drop for VkSwapchain {
fn drop(&mut self) {
self.drop_current_swapchain()
self.drop_swapchain()
}
}