1use crate::core 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 {
11 handle: vk::InstanceHandle,
12 fp: vk::FnInstance,
13 pub(super) gipa: unsafe extern "system" fn(
14 vk::InstanceHandle,
15 *const std::ffi::c_char,
16 ) -> vk::PFN_vkVoidFunction,
17 pub(crate) library: Option<Arc<Library>>,
18 pub(crate) capabilities: Option<Capabilities>,
19}
20
21impl Instance {
22 pub unsafe fn new_from_handle(
30 entry: &Entry,
31 handle: vk::InstanceHandle,
32 ) -> Result<Self, LoadError> {
33 if handle.is_null() {
34 return Err(LoadError::NullHandle("instance"));
35 }
36 let fp = unsafe { vk::FnInstance::new_from_resolver(entry.gipa, handle) };
38 if fp.destroy_instance.is_none() {
39 return Err(LoadError::MissingSymbol("vkDestroyInstance"));
40 }
41 Ok(Self {
42 handle,
43 fp,
44 gipa: entry.gipa,
45 library: entry.library.clone(),
46 capabilities: None,
47 })
48 }
49
50 pub unsafe fn new_from_handle_with_capabilities(
61 entry: &Entry,
62 handle: vk::InstanceHandle,
63 capabilities: Capabilities,
64 ) -> Result<Self, LoadError> {
65 if capabilities.is_device() {
66 return Err(LoadError::InvalidMetadata(
67 "instance import needs instance capabilities",
68 ));
69 }
70 let mut instance = unsafe { Self::new_from_handle(entry, handle) }?;
72 instance
73 .fp
74 .retain_enabled(|command| capabilities.support(command) != CommandSupport::Disabled);
75 instance.capabilities = Some(capabilities);
76 Ok(instance)
77 }
78
79 pub fn handle(&self) -> vk::InstanceHandle {
81 self.handle
82 }
83
84 pub fn fp(&self) -> &vk::FnInstance {
86 &self.fp
87 }
88
89 pub fn capabilities(&self) -> Option<&Capabilities> {
91 self.capabilities.as_ref()
92 }
93
94 pub unsafe fn destroy(self, allocator: Option<&vk::AllocationCallbacks>) {
100 unsafe { destroy_instance(self, allocator) };
102 }
103}
104
105pub unsafe fn create_instance(
116 entry: &Entry,
117 create_info: &vk::InstanceCreateInfo,
118 allocator: Option<&vk::AllocationCallbacks>,
119) -> Result<Instance, CallError> {
120 let mut capabilities = unsafe { Capabilities::instance(create_info) }?;
123 capabilities.limit_instance_version(entry.enumerate_instance_version()?)?;
124 let allocator_ptr = allocator.map_or(std::ptr::null(), |a| a);
125 let mut handle = vk::InstanceHandle::NULL;
126 let result =
128 unsafe { entry.fp().create_instance.unwrap()(create_info, allocator_ptr, &mut handle) };
129 if result != vk::Result::SUCCESS {
130 return Err(CallError::Vulkan(result));
131 }
132 if handle.is_null() {
133 return Err(CallError::InvalidOutput(
134 "vkCreateInstance returned a null handle",
135 ));
136 }
137 let mut fp = unsafe { vk::FnInstance::new_from_resolver(entry.gipa, handle) };
139 if fp.destroy_instance.is_none() {
140 let failure = InitializationFailure {
141 handle: CreatedHandle::Instance(handle),
142 missing_command: "vkDestroyInstance",
143 library: entry.library.clone(),
144 instance: handle,
145 gipa: entry.gipa,
146 gdpa: None,
147 };
148 return match unsafe { failure.destroy(allocator) } {
150 Ok(()) => Err(CallError::MissingCommand("vkDestroyInstance")),
151 Err(failure) => Err(CallError::InitializationFailed(failure)),
152 };
153 }
154 fp.retain_enabled(|command| capabilities.support(command) != CommandSupport::Disabled);
157 Ok(Instance {
158 handle,
159 fp,
160 gipa: entry.gipa,
161 library: entry.library.clone(),
162 capabilities: Some(capabilities),
163 })
164}
165
166impl Instance {
167 pub unsafe fn new(
172 entry: &Entry,
173 create_info: &vk::InstanceCreateInfo,
174 allocator: Option<&vk::AllocationCallbacks>,
175 ) -> Result<Self, CallError> {
176 unsafe { create_instance(entry, create_info, allocator) }
178 }
179}
180
181use super::command::commands;
182commands! { Instance, instance;
183 pub unsafe fn get_instance_proc_addr(name: &std::ffi::CStr) -> vk::PFN_vkVoidFunction {
189 unsafe { (instance.gipa)(instance.handle, name.as_ptr()) }
191 }
192
193 pub unsafe fn enumerate_physical_devices() -> Result<Vec<vk::PhysicalDevice>, CallError> {
198 let f = instance
199 .fp
200 .enumerate_physical_devices
201 .ok_or(CallError::MissingCommand("vkEnumeratePhysicalDevices"))?;
202 unsafe { crate::load::enumerate::enumerate(|count, data| f(instance.handle, count, data)) }
204 }
205
206 pub unsafe fn get_physical_device_properties(
211 physical_device: vk::PhysicalDevice,
212 ) -> Result<vk::PhysicalDeviceProperties, CallError> {
213 let f = instance
214 .fp
215 .get_physical_device_properties
216 .ok_or(CallError::MissingCommand("vkGetPhysicalDeviceProperties"))?;
217 let mut props = unsafe { std::mem::zeroed::<vk::PhysicalDeviceProperties>() };
219 unsafe { f(physical_device, &mut props) };
221 Ok(props)
222 }
223
224 pub unsafe fn get_physical_device_features(
229 physical_device: vk::PhysicalDevice,
230 ) -> Result<vk::PhysicalDeviceFeatures, CallError> {
231 let f = instance
232 .fp
233 .get_physical_device_features
234 .ok_or(CallError::MissingCommand("vkGetPhysicalDeviceFeatures"))?;
235 let mut features = unsafe { std::mem::zeroed::<vk::PhysicalDeviceFeatures>() };
237 unsafe { f(physical_device, &mut features) };
239 Ok(features)
240 }
241
242 pub unsafe fn get_physical_device_queue_family_properties(
247 physical_device: vk::PhysicalDevice,
248 ) -> Result<Vec<vk::QueueFamilyProperties>, CallError> {
249 let f = instance
250 .fp
251 .get_physical_device_queue_family_properties
252 .ok_or(CallError::MissingCommand(
253 "vkGetPhysicalDeviceQueueFamilyProperties",
254 ))?;
255 unsafe { crate::load::enumerate::enumerate_void(|count, data| f(physical_device, count, data)) }
257 }
258
259 pub unsafe fn enumerate_device_extension_properties(
266 physical_device: vk::PhysicalDevice,
267 layer_name: Option<&std::ffi::CStr>,
268 ) -> Result<Vec<vk::ExtensionProperties>, CallError> {
269 let f = instance
270 .fp
271 .enumerate_device_extension_properties
272 .ok_or(CallError::MissingCommand(
273 "vkEnumerateDeviceExtensionProperties",
274 ))?;
275 let layer_ptr = layer_name.map_or(std::ptr::null(), |l| l.as_ptr());
276 unsafe {
278 crate::load::enumerate::enumerate(|count, data| f(physical_device, layer_ptr, count, data))
279 }
280 }
281
282 pub unsafe fn get_physical_device_memory_properties(
287 physical_device: vk::PhysicalDevice,
288 ) -> Result<vk::PhysicalDeviceMemoryProperties, CallError> {
289 let f = instance
290 .fp
291 .get_physical_device_memory_properties
292 .ok_or(CallError::MissingCommand(
293 "vkGetPhysicalDeviceMemoryProperties",
294 ))?;
295 let mut props = unsafe { std::mem::zeroed::<vk::PhysicalDeviceMemoryProperties>() };
297 unsafe { f(physical_device, &mut props) };
299 Ok(props)
300 }
301
302}
303
304pub unsafe fn destroy_instance(instance: Instance, allocator: Option<&vk::AllocationCallbacks>) {
310 unsafe {
312 instance.fp.destroy_instance.unwrap()(
313 instance.handle,
314 allocator.map_or(std::ptr::null(), |a| a),
315 )
316 };
317}