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
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:
parent
1cb9309a56
commit
174e12591c
5 changed files with 290 additions and 320 deletions
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue