librashader/librashader-runtime-vk/src/hello_triangle/surface.rs

134 lines
4.3 KiB
Rust
Raw Normal View History

2023-01-10 14:54:54 +11:00
use crate::hello_triangle::vulkan_base::VulkanBase;
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,
}
impl VulkanSurface {
2023-01-10 14:54:54 +11:00
pub fn new(base: &VulkanBase, window: &winit::window::Window) -> VkResult<VulkanSurface> {
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
.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();
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-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-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
}