use std::ops::Deref;
use anyhow::Result;
use ash::vk;
use crate::{AppSettings, Error, Instance, PhysicalDevice, WindowInterface};
#[derive(Derivative)]
#[derivative(Debug)]
pub struct Surface {
handle: vk::SurfaceKHR,
capabilities: vk::SurfaceCapabilitiesKHR,
formats: Vec<vk::SurfaceFormatKHR>,
present_modes: Vec<vk::PresentModeKHR>,
#[derivative(Debug = "ignore")]
functions: ash::extensions::khr::Surface,
}
impl Surface {
pub fn new<Window: WindowInterface>(
instance: &Instance,
settings: &AppSettings<Window>,
) -> Result<Self> {
if let Some(window) = settings.window {
let functions =
ash::extensions::khr::Surface::new(unsafe { instance.loader() }, instance);
let handle = unsafe {
ash_window::create_surface(
instance.loader(),
instance,
window.raw_display_handle(),
window.raw_window_handle(),
None,
)?
};
#[cfg(feature = "log-objects")]
trace!("Created new VkSurfaceKHR {handle:p}");
Ok(Surface {
handle,
functions,
capabilities: Default::default(),
formats: vec![],
present_modes: vec![],
})
} else {
Err(anyhow::Error::from(Error::NoWindow))
}
}
pub fn query_details(&mut self, physical_device: &PhysicalDevice) -> Result<()> {
unsafe {
self.capabilities = self
.get_physical_device_surface_capabilities(physical_device.handle(), self.handle)?;
self.formats =
self.get_physical_device_surface_formats(physical_device.handle(), self.handle)?;
self.present_modes = self
.get_physical_device_surface_present_modes(physical_device.handle(), self.handle)?;
}
Ok(())
}
pub unsafe fn handle(&self) -> vk::SurfaceKHR {
self.handle
}
pub fn capabilities(&self) -> &vk::SurfaceCapabilitiesKHR {
&self.capabilities
}
pub fn formats(&self) -> &[vk::SurfaceFormatKHR] {
self.formats.as_slice()
}
pub fn present_modes(&self) -> &[vk::PresentModeKHR] {
self.present_modes.as_slice()
}
}
impl Deref for Surface {
type Target = ash::extensions::khr::Surface;
fn deref(&self) -> &Self::Target {
&self.functions
}
}
impl Drop for Surface {
fn drop(&mut self) {
#[cfg(feature = "log-objects")]
trace!("Destroying VkSurfaceKHR {:p}", self.handle);
unsafe {
self.functions.destroy_surface(self.handle, None);
}
}
}