1
2use crate::prelude::*;
3use std::{
4 fmt::{self, Debug, Formatter},
5 ptr::{null, null_mut},
6 sync::Arc,
7};
8
9pub struct VulkanSurface {
11 pub(crate) vkcore: Arc<VkCore>,
13
14 surface: VkSurfaceKHR,
16
17 format: VkSurfaceFormatKHR,
19}
20
21unsafe impl Send for VulkanSurface {}
22unsafe impl Sync for VulkanSurface {}
23
24impl VulkanSurface {
25 pub fn new_from(vkcore: Arc<VkCore>, surface: VkSurfaceKHR, format: VkSurfaceFormatKHR) -> Self {
27 Self {
28 vkcore,
29 surface,
30 format,
31 }
32 }
33 #[allow(dead_code)]
35 fn new_from_ci<T>(function_name: &'static str, vkcore: Arc<VkCore>, device: &VulkanDevice, vk_create_surface: fn(VkInstance, &T, *const VkAllocationCallbacks, *mut VkSurfaceKHR) -> VkResult, surface_ci: &T) -> Result<Self, VulkanError> {
36 let gpu_info = device.get_gpu();
37 let mut surface: VkSurfaceKHR = null();
38 vk_result_conv(function_name, vk_create_surface(vkcore.get_instance(), surface_ci, null(), &mut surface))?;
39 let surface = ResourceGuard::new(surface, |&s|{let vkcore = vkcore.clone(); vkcore.vkDestroySurfaceKHR(vkcore.get_instance(), s, null()).unwrap()});
40
41 let queue_families = gpu_info.get_queue_families();
42 let mut supported = Vec::<bool>::with_capacity(queue_families.len());
43 for i in 0..queue_families.len() {
44 supported.push(device.get_supported_by_surface(i, *surface)?);
45 }
46 let mut graphics_queue_node_index = u32::MAX;
47 let mut present_queue_node_index = u32::MAX;
48 for (i, queue_family) in queue_families.iter().enumerate() {
49 if (queue_family.queueFlags & VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT as VkQueueFlags) == VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT as VkQueueFlags {
50 graphics_queue_node_index = i as u32;
51 if supported[i] {
52 present_queue_node_index = i as u32;
53 break;
54 }
55 }
56 }
57 if present_queue_node_index == u32::MAX {
58 for (i, s) in supported.iter().enumerate() {
59 if *s {
60 present_queue_node_index = i as u32;
61 break;
62 }
63 }
64 }
65 if graphics_queue_node_index == u32::MAX && present_queue_node_index == u32::MAX {
66 return Err(VulkanError::NoGoodQueueForSurface("Could not find a graphics and/or presenting queue!"));
67 }
68 if graphics_queue_node_index != present_queue_node_index {
69 return Err(VulkanError::NoGoodQueueForSurface("Separate graphics and presenting queues are not supported yet!"));
70 }
71 let mut num_formats: u32 = 0;
72 vkcore.vkGetPhysicalDeviceSurfaceFormatsKHR(gpu_info.get_vk_physical_device(), *surface, &mut num_formats, null_mut())?;
73 let mut formats = Vec::<VkSurfaceFormatKHR>::with_capacity(num_formats as usize);
74 vkcore.vkGetPhysicalDeviceSurfaceFormatsKHR(gpu_info.get_vk_physical_device(), *surface, &mut num_formats, formats.as_mut_ptr())?;
75 unsafe {formats.set_len(num_formats as usize)};
76
77 let mut selected_format = formats[0];
78
79 const PREFERRED_FORMAT: [VkFormat; 3] = [
80 VkFormat::VK_FORMAT_B8G8R8A8_UNORM,
81 VkFormat::VK_FORMAT_R8G8B8A8_UNORM,
82 VkFormat::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
83 ];
84
85 'find_format: {
86 for pf in PREFERRED_FORMAT.iter() {
87 for f in formats.iter() {
88 if f.format == *pf {
89 selected_format = *f;
90 break 'find_format;
91 }
92 }
93 }
94 }
95 let surface = surface.release();
96 Ok(Self::new_from(vkcore, surface, selected_format))
97 }
98 #[cfg(any(feature = "glfw", test))]
100 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, window: &glfw::PWindow) -> Result<Self, VulkanError> {
101 Self::new_from_ci("vkCreateWindowSurfaceGLFW", vkcore, device, vkCreateWindowSurfaceGLFW, window)
102 }
103 #[cfg(feature = "win32_khr")]
105 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, hwnd: HWND, hinstance: HINSTANCE) -> Result<Self, VulkanError> {
106 let surface_ci = VkWin32SurfaceCreateInfoKHR {
107 sType: VkStructureType::VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
108 pNext: null(),
109 flags: 0,
110 hinstance,
111 hwnd,
112 };
113 Self::new_from_ci("vkCreateWin32SurfaceKHR", vkcore, device, vkCreateWin32SurfaceKHR, &surface_ci)
114 }
115 #[cfg(feature = "android_khr")]
117 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, window: *const ANativeWindow) -> Result<Self, VulkanError> {
118 let surface_ci = VkAndroidSurfaceCreateInfoKHR {
119 sType: VkStructureType::VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
120 pNext: null(),
121 flags: 0,
122 window,
123 };
124 Self::new_from_ci("vkCreateAndroidSurfaceKHR", vkcore, device, vkCreateAndroidSurfaceKHR, &surface_ci)
125 }
126 #[cfg(feature = "ios_mvk")]
128 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, view: *const c_void) -> Result<Self, VulkanError> {
129 let surface_ci = VkIOSSurfaceCreateInfoMVK {
130 sType: VkStructureType::VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK,
131 pNext: null(),
132 flags: 0,
133 pView: view,
134 };
135 Self::new_from_ci("vkCreateIOSSurfaceMVK", vkcore, device, vkCreateIOSSurfaceMVK, &surface_ci)
136 }
137 #[cfg(feature = "macos_mvk")]
139 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, view: *const c_void) -> Result<Self, VulkanError> {
140 let surface_ci = VkMacOSSurfaceCreateInfoMVK {
141 sType: VkStructureType::VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
142 pNext: null(),
143 flags: 0,
144 pView: view,
145 };
146 Self::new_from_ci("vkCreateMacOSSurfaceMVK", vkcore, device, vkCreateMacOSSurfaceMVK, &surface_ci)
147 }
148 #[cfg(feature = "metal_ext")]
150 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, metal_layer: *const CAMetalLayer) -> Result<Self, VulkanError> {
151 let surface_ci = VkMetalSurfaceCreateInfoEXT {
152 sType: VkStructureType::VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
153 pNext: null(),
154 flags: 0,
155 pLayer: metal_layer,
156 };
157 Self::new_from_ci("vkCreateMetalSurfaceEXT", vkcore, device, vkCreateMetalSurfaceEXT, &surface_ci)
158 }
159 #[cfg(feature = "wayland_khr")]
161 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, display: *const c_void, surface: *const c_void) -> Result<Self, VulkanError> {
162 let surface_ci = VkWaylandSurfaceCreateInfoKHR {
163 sType: VkStructureType::VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
164 pNext: null(),
165 flags: 0,
166 display,
167 surface,
168 };
169 Self::new_from_ci("vkCreateWaylandSurfaceKHR", vkcore, device, vkCreateWaylandSurfaceKHR, &surface_ci)
170 }
171 #[cfg(feature = "xcb_khr")]
173 pub fn new(vkcore: Arc<VkCore>, device: &VulkanDevice, connection: *const c_void, window: xcb_window_t) -> Result<Self, VulkanError> {
174 let surface_ci = VkXcbSurfaceCreateInfoKHR {
175 sType: VkStructureType::VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
176 pNext: null(),
177 flags: 0,
178 connection,
179 window,
180 };
181 Self::new_from_ci("vkCreateXcbSurfaceKHR", vkcore, device, vkCreateXcbSurfaceKHR, &surface_ci)
182 }
183
184 pub(crate) fn get_vk_surface(&self) -> VkSurfaceKHR {
186 self.surface
187 }
188
189 pub(crate) fn get_vk_surface_format(&self) -> &VkSurfaceFormatKHR {
191 &self.format
192 }
193}
194
195impl Debug for VulkanSurface {
196 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
197 f.debug_struct("VulkanSurface")
198 .field("surface", &self.surface)
199 .field("format", &self.format)
200 .finish()
201 }
202}
203
204impl Drop for VulkanSurface {
205 fn drop(&mut self) {
206 self.vkcore.vkDestroySurfaceKHR(self.vkcore.get_instance(), self.surface, null()).unwrap();
207 }
208}