use super::instance::InstanceInner;
use super::physical::PhysicalDevice;
use super::{Error, Instance, Result, check};
use crate::raw::bindings::*;
use std::sync::Arc;
pub struct Surface {
pub(crate) handle: VkSurfaceKHR,
pub(crate) instance: Arc<InstanceInner>,
}
unsafe impl Send for Surface {}
unsafe impl Sync for Surface {}
impl Surface {
pub unsafe fn from_win32(
instance: &Instance,
hinstance: *mut std::ffi::c_void,
hwnd: *mut std::ffi::c_void,
) -> Result<Self> {
let create = instance
.inner
.dispatch
.vkCreateWin32SurfaceKHR
.ok_or(Error::MissingFunction("vkCreateWin32SurfaceKHR"))?;
let info = VkWin32SurfaceCreateInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
hinstance,
hwnd,
..Default::default()
};
let mut handle: VkSurfaceKHR = 0;
check(unsafe { create(instance.inner.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
instance: Arc::clone(&instance.inner),
})
}
pub unsafe fn from_wayland(
instance: &Instance,
display: *mut std::ffi::c_void,
surface: *mut std::ffi::c_void,
) -> Result<Self> {
let create = instance
.inner
.dispatch
.vkCreateWaylandSurfaceKHR
.ok_or(Error::MissingFunction("vkCreateWaylandSurfaceKHR"))?;
let info = VkWaylandSurfaceCreateInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
display: display as *mut _,
surface: surface as *mut _,
..Default::default()
};
let mut handle: VkSurfaceKHR = 0;
check(unsafe { create(instance.inner.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
instance: Arc::clone(&instance.inner),
})
}
pub unsafe fn from_xlib(
instance: &Instance,
display: *mut std::ffi::c_void,
window: std::ffi::c_ulong,
) -> Result<Self> {
let create = instance
.inner
.dispatch
.vkCreateXlibSurfaceKHR
.ok_or(Error::MissingFunction("vkCreateXlibSurfaceKHR"))?;
let info = VkXlibSurfaceCreateInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
dpy: display as *mut _,
window,
..Default::default()
};
let mut handle: VkSurfaceKHR = 0;
check(unsafe { create(instance.inner.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
instance: Arc::clone(&instance.inner),
})
}
pub unsafe fn from_xcb(
instance: &Instance,
connection: *mut std::ffi::c_void,
window: u32,
) -> Result<Self> {
let create = instance
.inner
.dispatch
.vkCreateXcbSurfaceKHR
.ok_or(Error::MissingFunction("vkCreateXcbSurfaceKHR"))?;
let info = VkXcbSurfaceCreateInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
connection: connection as *mut _,
window,
..Default::default()
};
let mut handle: VkSurfaceKHR = 0;
check(unsafe { create(instance.inner.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
instance: Arc::clone(&instance.inner),
})
}
pub unsafe fn from_metal(
instance: &Instance,
metal_layer: *const std::ffi::c_void,
) -> Result<Self> {
let create = instance
.inner
.dispatch
.vkCreateMetalSurfaceEXT
.ok_or(Error::MissingFunction("vkCreateMetalSurfaceEXT"))?;
let info = VkMetalSurfaceCreateInfoEXT {
sType: VkStructureType::STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
pLayer: metal_layer as *const _,
..Default::default()
};
let mut handle: VkSurfaceKHR = 0;
check(unsafe { create(instance.inner.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
instance: Arc::clone(&instance.inner),
})
}
pub fn raw(&self) -> VkSurfaceKHR {
self.handle
}
pub fn supports_present(&self, physical: &PhysicalDevice, queue_family: u32) -> bool {
let Some(get) = self.instance.dispatch.vkGetPhysicalDeviceSurfaceSupportKHR else {
return false;
};
let mut supported: VkBool32 = 0;
let res = unsafe { get(physical.raw(), queue_family, self.handle, &mut supported) };
res == VkResult::SUCCESS && supported != 0
}
pub fn capabilities(&self, physical: &PhysicalDevice) -> Result<SurfaceCapabilities> {
let get = self
.instance
.dispatch
.vkGetPhysicalDeviceSurfaceCapabilitiesKHR
.ok_or(Error::MissingFunction(
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
))?;
let mut raw: VkSurfaceCapabilitiesKHR = unsafe { std::mem::zeroed() };
check(unsafe { get(physical.raw(), self.handle, &mut raw) })?;
Ok(SurfaceCapabilities { raw })
}
pub fn formats(&self, physical: &PhysicalDevice) -> Result<Vec<SurfaceFormat>> {
let get = self
.instance
.dispatch
.vkGetPhysicalDeviceSurfaceFormatsKHR
.ok_or(Error::MissingFunction(
"vkGetPhysicalDeviceSurfaceFormatsKHR",
))?;
let mut count: u32 = 0;
check(unsafe {
get(
physical.raw(),
self.handle,
&mut count,
std::ptr::null_mut(),
)
})?;
let mut raw: Vec<VkSurfaceFormatKHR> = vec![unsafe { std::mem::zeroed() }; count as usize];
check(unsafe { get(physical.raw(), self.handle, &mut count, raw.as_mut_ptr()) })?;
Ok(raw.into_iter().map(|r| SurfaceFormat { raw: r }).collect())
}
pub fn present_modes(&self, physical: &PhysicalDevice) -> Result<Vec<PresentMode>> {
let get = self
.instance
.dispatch
.vkGetPhysicalDeviceSurfacePresentModesKHR
.ok_or(Error::MissingFunction(
"vkGetPhysicalDeviceSurfacePresentModesKHR",
))?;
let mut count: u32 = 0;
check(unsafe {
get(
physical.raw(),
self.handle,
&mut count,
std::ptr::null_mut(),
)
})?;
let mut raw: Vec<VkPresentModeKHR> =
vec![VkPresentModeKHR::PRESENT_MODE_FIFO_KHR; count as usize];
check(unsafe { get(physical.raw(), self.handle, &mut count, raw.as_mut_ptr()) })?;
Ok(raw.into_iter().map(PresentMode).collect())
}
}
impl Drop for Surface {
fn drop(&mut self) {
if let Some(destroy) = self.instance.dispatch.vkDestroySurfaceKHR {
unsafe { destroy(self.instance.handle, self.handle, std::ptr::null()) };
}
}
}
#[derive(Clone)]
pub struct SurfaceCapabilities {
pub(crate) raw: VkSurfaceCapabilitiesKHR,
}
impl std::fmt::Debug for SurfaceCapabilities {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SurfaceCapabilities")
.field("min_image_count", &self.min_image_count())
.field("max_image_count", &self.max_image_count())
.field("current_extent", &self.current_extent())
.field("min_image_extent", &self.min_image_extent())
.field("max_image_extent", &self.max_image_extent())
.field("supported_usage_flags", &self.supported_usage_flags())
.field("supported_transforms", &self.supported_transforms())
.field("current_transform", &self.current_transform())
.field(
"supported_composite_alpha",
&self.supported_composite_alpha(),
)
.finish()
}
}
impl SurfaceCapabilities {
pub fn min_image_count(&self) -> u32 {
self.raw.minImageCount
}
pub fn max_image_count(&self) -> u32 {
self.raw.maxImageCount
}
pub fn current_extent(&self) -> (u32, u32) {
(self.raw.currentExtent.width, self.raw.currentExtent.height)
}
pub fn min_image_extent(&self) -> (u32, u32) {
(
self.raw.minImageExtent.width,
self.raw.minImageExtent.height,
)
}
pub fn max_image_extent(&self) -> (u32, u32) {
(
self.raw.maxImageExtent.width,
self.raw.maxImageExtent.height,
)
}
pub fn supported_usage_flags(&self) -> u32 {
self.raw.supportedUsageFlags
}
pub fn supported_transforms(&self) -> u32 {
self.raw.supportedTransforms
}
pub fn current_transform(&self) -> u32 {
self.raw.currentTransform
}
pub fn supported_composite_alpha(&self) -> u32 {
self.raw.supportedCompositeAlpha
}
}
#[derive(Clone, Copy)]
pub struct SurfaceFormat {
pub(crate) raw: VkSurfaceFormatKHR,
}
impl std::fmt::Debug for SurfaceFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SurfaceFormat")
.field("format", &self.format())
.field("color_space", &self.color_space())
.finish()
}
}
impl SurfaceFormat {
pub fn format(&self) -> super::Format {
super::Format(self.raw.format)
}
pub fn color_space(&self) -> VkColorSpaceKHR {
self.raw.colorSpace
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PresentMode(pub VkPresentModeKHR);
impl PresentMode {
pub const FIFO: Self = Self(VkPresentModeKHR::PRESENT_MODE_FIFO_KHR);
pub const FIFO_RELAXED: Self = Self(VkPresentModeKHR::PRESENT_MODE_FIFO_RELAXED_KHR);
pub const IMMEDIATE: Self = Self(VkPresentModeKHR::PRESENT_MODE_IMMEDIATE_KHR);
pub const MAILBOX: Self = Self(VkPresentModeKHR::PRESENT_MODE_MAILBOX_KHR);
}