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,27 +1,43 @@
use crate::display::Window;
use crate::vulkan::{VkDevice, VkInstance, VkPhysicalDevice, VkSwapchain, LOG_TARGET};
use std::sync::Arc;
use crate::vulkan::{VkInstance, VkPhysicalDevice, LOG_TARGET};
use ash::prelude::VkResult;
use ash::vk;
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
pub struct VkSurface {
surface_loader: ash::khr::surface::Instance,
instance: Arc<VkInstance>,
pub(super) surface: vk::SurfaceKHR,
}
impl VkSurface {
pub fn new(
surface_loader: ash::khr::surface::Instance,
surface: vk::SurfaceKHR,
) -> Self {
Self {
surface_loader,
window: &crate::display::Window,
instance: Arc<VkInstance>,
) -> anyhow::Result<Self> {
let window_handle = window.handle()
.ok_or_else(|| anyhow::anyhow!("Window handle is not available."))?;
let surface = unsafe {
ash_window::create_surface(
&instance.entry,
&instance.handle,
window_handle.display_handle()?.as_raw(),
window_handle.window_handle()?.as_raw(),
None,
)?
};
log::debug!(target: LOG_TARGET, "Surface created ({:?})", surface);
Ok(Self {
instance,
surface,
}
})
}
pub fn physical_device_queue_supported(&self, physical_device: &VkPhysicalDevice, queue_index: u32) -> VkResult<bool> {
unsafe {
self.surface_loader.get_physical_device_surface_support(
self.instance.surface_loader.get_physical_device_surface_support(
physical_device.handle,
queue_index,
self.surface,
@ -29,115 +45,37 @@ impl VkSurface {
}
}
pub fn get_physical_device_surface_formats(&self, physical_device: &VkPhysicalDevice) -> VkResult<Vec<vk::SurfaceFormatKHR>> {
pub fn get_physical_device_surface_infos(&self, physical_device: &VkPhysicalDevice) -> VkResult<(
Vec<vk::SurfaceFormatKHR>,
vk::SurfaceCapabilitiesKHR,
Vec<vk::PresentModeKHR>
)> {
unsafe {
self.surface_loader.get_physical_device_surface_formats(
let formats = self.instance.surface_loader.get_physical_device_surface_formats(
physical_device.handle,
self.surface,
)
}
}
)?;
pub fn get_physical_device_surface_capabilities(&self, physical_device: &VkPhysicalDevice) -> VkResult<vk::SurfaceCapabilitiesKHR> {
unsafe {
self.surface_loader.get_physical_device_surface_capabilities(
let capabilities = self.instance.surface_loader.get_physical_device_surface_capabilities(
physical_device.handle,
self.surface,
)
}
}
)?;
pub fn get_physical_device_surface_present_modes(&self, physical_device: &VkPhysicalDevice) -> VkResult<Vec<vk::PresentModeKHR>> {
unsafe {
self.surface_loader.get_physical_device_surface_present_modes(
let present_modes = self.instance.surface_loader.get_physical_device_surface_present_modes(
physical_device.handle,
self.surface,
)
)?;
Ok((formats, capabilities, present_modes))
}
}
pub fn create_swapchain(
&self,
window: &Window,
instance: &VkInstance,
device: &VkDevice,
physical_device: &VkPhysicalDevice,
) -> anyhow::Result<VkSwapchain> {
log::debug!(target: LOG_TARGET, "Creating swapchain");
let surface_formats = self.get_physical_device_surface_formats(physical_device)?;
log::debug!(target: LOG_TARGET, "Supported surface formats by physical device: {surface_formats:#?}");
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 surface_capabilities = self.get_physical_device_surface_capabilities(physical_device)?;
log::debug!(target: LOG_TARGET, "Surface capabilities: {surface_capabilities:#?}");
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_modes = self
.get_physical_device_surface_present_modes(physical_device)?;
let present_mode = present_modes
.iter()
.cloned()
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
.unwrap_or(vk::PresentModeKHR::FIFO);
let swapchain_loader = ash::khr::swapchain::Device::new(&instance.handle, &device.handle);
let mut swapchain = VkSwapchain::new(
swapchain_loader,
desired_image_count,
surface_format,
surface_resolution,
present_mode,
pre_transform,
);
swapchain.create_swapchain(&self)?;
Ok(swapchain)
}
}
impl Drop for VkSurface {
fn drop(&mut self) {
unsafe {
self.surface_loader.destroy_surface(self.surface, None);
self.instance.surface_loader.destroy_surface(self.surface, None);
}
log::debug!(target: LOG_TARGET, "Surface destroyed");
log::debug!(target: LOG_TARGET, "Surface destroyed ({:?})", self.surface);
}
}