1use crate as vk;
3use crate::load::{
4 CallError, Capabilities, CommandSupport, CreatedHandle, Entry, InitializationFailure, LoadError,
5};
6use libloading::Library;
7use std::sync::Arc;
8
9pub struct Instance {
17 handle: vk::InstanceHandle,
18 fp: vk::FnInstance,
19 pub(super) gipa: unsafe extern "system" fn(
20 vk::InstanceHandle,
21 *const std::ffi::c_char,
22 ) -> vk::PFN_vkVoidFunction,
23 pub(crate) library: Option<Arc<Library>>,
24 pub(crate) capabilities: Option<Capabilities>,
25}
26
27impl Instance {
28 pub unsafe fn new_from_handle(
36 entry: &Entry,
37 handle: vk::InstanceHandle,
38 ) -> Result<Self, LoadError> {
39 if handle.is_null() {
40 return Err(LoadError::NullHandle("instance"));
41 }
42 let fp = unsafe { vk::FnInstance::new_from_resolver(entry.gipa, handle) };
44 if fp.destroy_instance.is_none() {
45 return Err(LoadError::MissingSymbol("vkDestroyInstance"));
46 }
47 Ok(Self {
48 handle,
49 fp,
50 gipa: entry.gipa,
51 library: entry.library.clone(),
52 capabilities: None,
53 })
54 }
55
56 pub unsafe fn new_from_handle_with_capabilities(
67 entry: &Entry,
68 handle: vk::InstanceHandle,
69 capabilities: Capabilities,
70 ) -> Result<Self, LoadError> {
71 if capabilities.is_device() {
72 return Err(LoadError::InvalidMetadata(
73 "instance import needs instance capabilities",
74 ));
75 }
76 let mut instance = unsafe { Self::new_from_handle(entry, handle) }?;
78 instance
79 .fp
80 .retain_enabled(|command| capabilities.support(command) != CommandSupport::Disabled);
81 instance.capabilities = Some(capabilities);
82 Ok(instance)
83 }
84
85 pub fn handle(&self) -> vk::InstanceHandle {
87 self.handle
88 }
89
90 pub fn fp(&self) -> &vk::FnInstance {
92 &self.fp
93 }
94
95 pub fn capabilities(&self) -> Option<&Capabilities> {
97 self.capabilities.as_ref()
98 }
99
100 #[doc(alias = "vkDestroyInstance")]
106 #[doc = "\n\n[Khronos reference: `vkDestroyInstance`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyInstance.html)"]
107 pub unsafe fn destroy(self, allocator: Option<&vk::AllocationCallbacks>) {
108 unsafe { destroy_instance(self, allocator) };
110 }
111}
112
113#[doc(alias = "vkCreateInstance")]
124#[doc = "\n\n[Khronos reference: `vkCreateInstance`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateInstance.html)"]
125pub unsafe fn create_instance(
126 entry: &Entry,
127 create_info: &vk::InstanceCreateInfo,
128 allocator: Option<&vk::AllocationCallbacks>,
129) -> Result<Instance, CallError> {
130 let mut capabilities = unsafe { Capabilities::instance(create_info) }?;
133 capabilities.limit_instance_version(entry.enumerate_instance_version()?)?;
134 let allocator_ptr = allocator.map_or(std::ptr::null(), |a| a);
135 let mut handle = vk::InstanceHandle::NULL;
136 let result =
138 unsafe { entry.fp().create_instance.unwrap()(create_info, allocator_ptr, &mut handle) };
139 if result != vk::Result::SUCCESS {
140 return Err(CallError::Vulkan(result));
141 }
142 if handle.is_null() {
143 return Err(CallError::InvalidOutput(
144 "vkCreateInstance returned a null handle",
145 ));
146 }
147 let mut fp = unsafe { vk::FnInstance::new_from_resolver(entry.gipa, handle) };
149 if fp.destroy_instance.is_none() {
150 let failure = InitializationFailure {
151 handle: CreatedHandle::Instance(handle),
152 missing_command: "vkDestroyInstance",
153 library: entry.library.clone(),
154 instance: handle,
155 gipa: entry.gipa,
156 gdpa: None,
157 };
158 return match unsafe { failure.destroy(allocator) } {
160 Ok(()) => Err(CallError::MissingCommand("vkDestroyInstance")),
161 Err(failure) => Err(CallError::InitializationFailed(failure)),
162 };
163 }
164 fp.retain_enabled(|command| capabilities.support(command) != CommandSupport::Disabled);
167 Ok(Instance {
168 handle,
169 fp,
170 gipa: entry.gipa,
171 library: entry.library.clone(),
172 capabilities: Some(capabilities),
173 })
174}
175
176impl Instance {
177 #[doc(alias = "vkCreateInstance")]
182 #[doc = "\n\n[Khronos reference: `vkCreateInstance`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateInstance.html)"]
183 pub unsafe fn new(
184 entry: &Entry,
185 create_info: &vk::InstanceCreateInfo,
186 allocator: Option<&vk::AllocationCallbacks>,
187 ) -> Result<Self, CallError> {
188 unsafe { create_instance(entry, create_info, allocator) }
190 }
191}
192
193use super::command::commands;
194commands! { Instance, instance;
195 #[doc(alias = "vkGetInstanceProcAddr")]
201 #[doc = "\n\n[Khronos reference: `vkGetInstanceProcAddr`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetInstanceProcAddr.html)"]
202 pub unsafe fn get_instance_proc_addr(name: &std::ffi::CStr) -> vk::PFN_vkVoidFunction {
203 unsafe { (instance.gipa)(instance.handle, name.as_ptr()) }
205 }
206
207 #[doc(alias = "vkEnumeratePhysicalDevices")]
212 #[doc = "\n\n[Khronos reference: `vkEnumeratePhysicalDevices`](https://docs.vulkan.org/refpages/latest/refpages/source/vkEnumeratePhysicalDevices.html)"]
213 pub unsafe fn enumerate_physical_devices() -> Result<Vec<vk::PhysicalDevice>, CallError> {
214 let f = instance
215 .fp
216 .enumerate_physical_devices
217 .ok_or(CallError::MissingCommand("vkEnumeratePhysicalDevices"))?;
218 unsafe { crate::load::enumerate::enumerate(|count, data| f(instance.handle, count, data)) }
220 }
221
222 #[doc(alias = "vkGetPhysicalDeviceProperties")]
227 #[doc = "\n\n[Khronos reference: `vkGetPhysicalDeviceProperties`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetPhysicalDeviceProperties.html)"]
228 pub unsafe fn get_physical_device_properties(
229 physical_device: vk::PhysicalDevice,
230 ) -> Result<vk::PhysicalDeviceProperties, CallError> {
231 let f = instance
232 .fp
233 .get_physical_device_properties
234 .ok_or(CallError::MissingCommand("vkGetPhysicalDeviceProperties"))?;
235 let mut props = unsafe { std::mem::zeroed::<vk::PhysicalDeviceProperties>() };
237 unsafe { f(physical_device, &mut props) };
239 Ok(props)
240 }
241
242 #[doc(alias = "vkGetPhysicalDeviceFeatures")]
247 #[doc = "\n\n[Khronos reference: `vkGetPhysicalDeviceFeatures`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetPhysicalDeviceFeatures.html)"]
248 pub unsafe fn get_physical_device_features(
249 physical_device: vk::PhysicalDevice,
250 ) -> Result<vk::PhysicalDeviceFeatures, CallError> {
251 let f = instance
252 .fp
253 .get_physical_device_features
254 .ok_or(CallError::MissingCommand("vkGetPhysicalDeviceFeatures"))?;
255 let mut features = unsafe { std::mem::zeroed::<vk::PhysicalDeviceFeatures>() };
257 unsafe { f(physical_device, &mut features) };
259 Ok(features)
260 }
261
262 #[doc(alias = "vkGetPhysicalDeviceQueueFamilyProperties")]
267 #[doc = "\n\n[Khronos reference: `vkGetPhysicalDeviceQueueFamilyProperties`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetPhysicalDeviceQueueFamilyProperties.html)"]
268 pub unsafe fn get_physical_device_queue_family_properties(
269 physical_device: vk::PhysicalDevice,
270 ) -> Result<Vec<vk::QueueFamilyProperties>, CallError> {
271 let f = instance
272 .fp
273 .get_physical_device_queue_family_properties
274 .ok_or(CallError::MissingCommand(
275 "vkGetPhysicalDeviceQueueFamilyProperties",
276 ))?;
277 unsafe { crate::load::enumerate::enumerate_void(|count, data| f(physical_device, count, data)) }
279 }
280
281 #[doc(alias = "vkEnumerateDeviceExtensionProperties")]
288 #[doc = "\n\n[Khronos reference: `vkEnumerateDeviceExtensionProperties`](https://docs.vulkan.org/refpages/latest/refpages/source/vkEnumerateDeviceExtensionProperties.html)"]
289 pub unsafe fn enumerate_device_extension_properties(
290 physical_device: vk::PhysicalDevice,
291 layer_name: Option<&std::ffi::CStr>,
292 ) -> Result<Vec<vk::ExtensionProperties>, CallError> {
293 let f = instance
294 .fp
295 .enumerate_device_extension_properties
296 .ok_or(CallError::MissingCommand(
297 "vkEnumerateDeviceExtensionProperties",
298 ))?;
299 let layer_ptr = layer_name.map_or(std::ptr::null(), |l| l.as_ptr());
300 unsafe {
302 crate::load::enumerate::enumerate(|count, data| f(physical_device, layer_ptr, count, data))
303 }
304 }
305
306 #[doc(alias = "vkGetPhysicalDeviceMemoryProperties")]
311 #[doc = "\n\n[Khronos reference: `vkGetPhysicalDeviceMemoryProperties`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetPhysicalDeviceMemoryProperties.html)"]
312 pub unsafe fn get_physical_device_memory_properties(
313 physical_device: vk::PhysicalDevice,
314 ) -> Result<vk::PhysicalDeviceMemoryProperties, CallError> {
315 let f = instance
316 .fp
317 .get_physical_device_memory_properties
318 .ok_or(CallError::MissingCommand(
319 "vkGetPhysicalDeviceMemoryProperties",
320 ))?;
321 let mut props = unsafe { std::mem::zeroed::<vk::PhysicalDeviceMemoryProperties>() };
323 unsafe { f(physical_device, &mut props) };
325 Ok(props)
326 }
327
328}
329
330#[doc(alias = "vkDestroyInstance")]
336#[doc = "\n\n[Khronos reference: `vkDestroyInstance`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyInstance.html)"]
337pub unsafe fn destroy_instance(instance: Instance, allocator: Option<&vk::AllocationCallbacks>) {
338 unsafe {
340 instance.fp.destroy_instance.unwrap()(
341 instance.handle,
342 allocator.map_or(std::ptr::null(), |a| a),
343 )
344 };
345}