2023-01-10 14:54:54 +11:00
|
|
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
2023-01-03 16:55:35 +11:00
|
|
|
use ash::prelude::VkResult;
|
|
|
|
use ash::vk;
|
|
|
|
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
|
|
|
|
|
|
|
pub struct VulkanSurface {
|
|
|
|
surface_loader: ash::extensions::khr::Surface,
|
2023-01-04 16:49:42 +11:00
|
|
|
pub surface: vk::SurfaceKHR,
|
2023-01-10 14:54:54 +11:00
|
|
|
pub present_queue: vk::Queue,
|
2023-01-03 16:55:35 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl VulkanSurface {
|
2023-01-10 14:54:54 +11:00
|
|
|
pub fn new(base: &VulkanBase, window: &winit::window::Window) -> VkResult<VulkanSurface> {
|
2023-01-03 16:55:35 +11:00
|
|
|
let surface = unsafe {
|
|
|
|
ash_window::create_surface(
|
|
|
|
&base.entry,
|
|
|
|
&base.instance,
|
|
|
|
window.raw_display_handle(),
|
|
|
|
window.raw_window_handle(),
|
|
|
|
None,
|
|
|
|
)?
|
|
|
|
};
|
|
|
|
|
|
|
|
let surface_loader = ash::extensions::khr::Surface::new(&base.entry, &base.instance);
|
|
|
|
|
|
|
|
let present_queue = unsafe {
|
2023-01-10 14:54:54 +11:00
|
|
|
let queue_family = base
|
|
|
|
.instance
|
2023-01-03 16:55:35 +11:00
|
|
|
.get_physical_device_queue_family_properties(base.physical_device)
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.find_map(|(index, info)| {
|
|
|
|
let supports_graphic_and_surface =
|
|
|
|
info.queue_flags.contains(vk::QueueFlags::GRAPHICS)
|
|
|
|
&& surface_loader
|
2023-01-10 14:54:54 +11:00
|
|
|
.get_physical_device_surface_support(
|
|
|
|
base.physical_device,
|
|
|
|
index as u32,
|
|
|
|
surface,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2023-01-03 16:55:35 +11:00
|
|
|
if supports_graphic_and_surface {
|
|
|
|
Some(index)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.expect("couldn't find suitable device");
|
|
|
|
base.device.get_device_queue(queue_family as u32, 0)
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(VulkanSurface {
|
|
|
|
surface,
|
|
|
|
surface_loader,
|
2023-01-10 14:54:54 +11:00
|
|
|
present_queue,
|
2023-01-03 16:55:35 +11:00
|
|
|
})
|
|
|
|
}
|
2023-01-04 16:49:42 +11:00
|
|
|
|
|
|
|
pub fn choose_format(&self, base: &VulkanBase) -> VkResult<vk::SurfaceFormatKHR> {
|
|
|
|
unsafe {
|
2023-01-10 14:54:54 +11:00
|
|
|
let available_formats = self
|
|
|
|
.surface_loader
|
|
|
|
.get_physical_device_surface_formats(base.physical_device, self.surface)?;
|
2023-01-04 16:49:42 +11:00
|
|
|
for available_format in available_formats.iter() {
|
|
|
|
if available_format.format == vk::Format::B8G8R8A8_SRGB
|
|
|
|
&& available_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
|
|
|
|
{
|
|
|
|
return Ok(available_format.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok(available_formats.first().unwrap().clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn choose_present_mode(&self, base: &VulkanBase) -> VkResult<vk::PresentModeKHR> {
|
|
|
|
unsafe {
|
2023-01-10 14:54:54 +11:00
|
|
|
let available_formats = self
|
|
|
|
.surface_loader
|
|
|
|
.get_physical_device_surface_present_modes(base.physical_device, self.surface)?;
|
2023-01-04 16:49:42 +11:00
|
|
|
|
2023-01-10 14:54:54 +11:00
|
|
|
Ok(
|
|
|
|
if available_formats.contains(&vk::PresentModeKHR::MAILBOX) {
|
|
|
|
vk::PresentModeKHR::MAILBOX
|
|
|
|
} else {
|
|
|
|
vk::PresentModeKHR::FIFO
|
|
|
|
},
|
|
|
|
)
|
2023-01-04 16:49:42 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-10 14:54:54 +11:00
|
|
|
pub fn choose_swapchain_extent(
|
|
|
|
&self,
|
|
|
|
base: &VulkanBase,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
) -> VkResult<vk::Extent2D> {
|
2023-01-04 16:49:42 +11:00
|
|
|
let capabilities = self.get_capabilities(base)?;
|
|
|
|
if capabilities.current_extent.width != u32::MAX {
|
|
|
|
Ok(capabilities.current_extent)
|
|
|
|
} else {
|
|
|
|
use num::clamp;
|
|
|
|
|
|
|
|
Ok(vk::Extent2D {
|
|
|
|
width: clamp(
|
|
|
|
width,
|
|
|
|
capabilities.min_image_extent.width,
|
|
|
|
capabilities.max_image_extent.width,
|
|
|
|
),
|
|
|
|
height: clamp(
|
|
|
|
height,
|
|
|
|
capabilities.min_image_extent.height,
|
|
|
|
capabilities.max_image_extent.height,
|
|
|
|
),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_capabilities(&self, base: &VulkanBase) -> VkResult<vk::SurfaceCapabilitiesKHR> {
|
|
|
|
unsafe {
|
2023-01-10 14:54:54 +11:00
|
|
|
self.surface_loader
|
|
|
|
.get_physical_device_surface_capabilities(base.physical_device, self.surface)
|
2023-01-04 16:49:42 +11:00
|
|
|
}
|
|
|
|
}
|
2023-01-03 16:55:35 +11:00
|
|
|
}
|
|
|
|
|
2023-01-04 16:49:42 +11:00
|
|
|
impl Drop for VulkanSurface {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
self.surface_loader.destroy_surface(self.surface, None);
|
|
|
|
}
|
|
|
|
}
|
2023-01-10 14:54:54 +11:00
|
|
|
}
|