1use super::Instance;
3use crate as vk;
4use crate::load::{
5 CallError, Capabilities, CommandSupport, CreatedHandle, InitializationFailure, LoadError,
6};
7use libloading::Library;
8use std::sync::Arc;
9
10pub struct Device {
18 handle: vk::DeviceHandle,
19 fp: vk::FnDevice,
20 gdpa:
21 unsafe extern "system" fn(vk::DeviceHandle, *const std::ffi::c_char) -> vk::PFN_vkVoidFunction,
22 _library: Option<Arc<Library>>,
23 capabilities: Option<Capabilities>,
24}
25
26impl Device {
27 pub unsafe fn new_from_handle(
35 instance: &Instance,
36 handle: vk::DeviceHandle,
37 ) -> Result<Self, LoadError> {
38 if handle.is_null() {
39 return Err(LoadError::NullHandle("device"));
40 }
41 let gdpa = instance
42 .fp()
43 .get_device_proc_addr
44 .ok_or(LoadError::MissingSymbol("vkGetDeviceProcAddr"))?;
45 let fp = unsafe { vk::FnDevice::new_from_resolver(gdpa, handle) };
47 if fp.destroy_device.is_none() {
48 return Err(LoadError::MissingSymbol("vkDestroyDevice"));
49 }
50 Ok(Self {
51 handle,
52 fp,
53 gdpa,
54 _library: instance.library.clone(),
55 capabilities: None,
56 })
57 }
58
59 pub unsafe fn new_from_handle_with_capabilities(
71 instance: &Instance,
72 handle: vk::DeviceHandle,
73 capabilities: Capabilities,
74 ) -> Result<Self, LoadError> {
75 if !capabilities.is_device() {
76 return Err(LoadError::InvalidMetadata(
77 "device import needs device capabilities",
78 ));
79 }
80 if let Some(parent) = instance.capabilities()
81 && !capabilities.matches_instance(parent)
82 {
83 return Err(LoadError::InvalidMetadata(
84 "device capabilities disagree with parent instance",
85 ));
86 }
87 let mut device = unsafe { Self::new_from_handle(instance, handle) }?;
89 device
90 .fp
91 .retain_enabled(|command| capabilities.support(command) == CommandSupport::Enabled);
92 device.capabilities = Some(capabilities);
93 Ok(device)
94 }
95
96 pub fn handle(&self) -> vk::DeviceHandle {
98 self.handle
99 }
100
101 pub fn fp(&self) -> &vk::FnDevice {
103 &self.fp
104 }
105
106 pub fn capabilities(&self) -> Option<&Capabilities> {
108 self.capabilities.as_ref()
109 }
110
111 #[doc(alias = "vkDestroyDevice")]
117 #[doc = "\n\n[Khronos reference: `vkDestroyDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyDevice.html)"]
118 pub unsafe fn destroy(self, allocator: Option<&vk::AllocationCallbacks>) {
119 unsafe { destroy_device(self, allocator) };
121 }
122}
123
124use super::command::commands;
125commands! { Device, device;
126 #[doc(alias = "vkGetDeviceQueue")]
132 #[doc = "\n\n[Khronos reference: `vkGetDeviceQueue`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetDeviceQueue.html)"]
133 pub unsafe fn get_device_queue(
134 queue_family_index: u32,
135 queue_index: u32,
136 ) -> Result<vk::Queue, CallError> {
137 let f = device
138 .fp
139 .get_device_queue
140 .ok_or(CallError::MissingCommand("vkGetDeviceQueue"))?;
141 let mut queue = vk::Queue::NULL;
142 unsafe { f(device.handle, queue_family_index, queue_index, &mut queue) };
144 Ok(queue)
145 }
146
147 #[doc(alias = "vkGetDeviceProcAddr")]
155 #[doc = "\n\n[Khronos reference: `vkGetDeviceProcAddr`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetDeviceProcAddr.html)"]
156 pub unsafe fn get_device_proc_addr(name: &std::ffi::CStr) -> vk::PFN_vkVoidFunction {
157 unsafe { (device.gdpa)(device.handle, name.as_ptr()) }
159 }
160
161 #[doc(alias = "vkCmdDispatch")]
171 #[doc = "\n\n[Khronos reference: `vkCmdDispatch`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdDispatch.html)"]
172 pub unsafe fn cmd_dispatch(
173 command_buffer: vk::CommandBuffer,
174 group_count_x: u32,
175 group_count_y: u32,
176 group_count_z: u32,
177 ) -> Result<(), CallError> {
178 let f = device
179 .fp
180 .cmd_dispatch
181 .ok_or(CallError::MissingCommand("vkCmdDispatch"))?;
182 unsafe { f(command_buffer, group_count_x, group_count_y, group_count_z) };
184 Ok(())
185 }
186
187 #[doc(alias = "vkAllocateMemory")]
196 #[doc = "\n\n[Khronos reference: `vkAllocateMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkAllocateMemory.html)"]
197 pub unsafe fn allocate_memory(
198 allocate_info: &vk::MemoryAllocateInfo,
199 allocator: Option<&vk::AllocationCallbacks>,
200 ) -> Result<vk::DeviceMemory, CallError> {
201 let f = device
202 .fp
203 .allocate_memory
204 .ok_or(CallError::MissingCommand("vkAllocateMemory"))?;
205 let mut handle = vk::DeviceMemory::NULL;
206 let result = unsafe {
207 f(
208 device.handle,
209 allocate_info,
210 allocator.map_or(std::ptr::null(), |a| a),
211 &mut handle,
212 )
213 };
214 if result == vk::Result::SUCCESS {
215 Ok(handle)
216 } else {
217 Err(CallError::Vulkan(result))
218 }
219 }
220
221 #[doc(alias = "vkFreeMemory")]
227 #[doc = "\n\n[Khronos reference: `vkFreeMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkFreeMemory.html)"]
228 pub unsafe fn free_memory(
229 memory: vk::DeviceMemory,
230 allocator: Option<&vk::AllocationCallbacks>,
231 ) -> Result<(), CallError> {
232 let f = device
233 .fp
234 .free_memory
235 .ok_or(CallError::MissingCommand("vkFreeMemory"))?;
236 unsafe {
237 f(
238 device.handle,
239 memory,
240 allocator.map_or(std::ptr::null(), |a| a),
241 )
242 };
243 Ok(())
244 }
245
246 #[doc(alias = "vkMapMemory")]
254 #[doc = "\n\n[Khronos reference: `vkMapMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkMapMemory.html)"]
255 pub unsafe fn map_memory(
256 memory: vk::DeviceMemory,
257 offset: vk::DeviceSize,
258 size: vk::DeviceSize,
259 flags: vk::MemoryMapFlags,
260 ) -> Result<*mut std::ffi::c_void, CallError> {
261 let f = device
262 .fp
263 .map_memory
264 .ok_or(CallError::MissingCommand("vkMapMemory"))?;
265 let mut ptr = std::ptr::null_mut();
266 let result = unsafe { f(device.handle, memory, offset, size, flags, &mut ptr) };
267 if result == vk::Result::SUCCESS {
268 Ok(ptr)
269 } else {
270 Err(CallError::Vulkan(result))
271 }
272 }
273
274 #[doc(alias = "vkUnmapMemory")]
280 #[doc = "\n\n[Khronos reference: `vkUnmapMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkUnmapMemory.html)"]
281 pub unsafe fn unmap_memory(memory: vk::DeviceMemory) -> Result<(), CallError> {
282 let f = device
283 .fp
284 .unmap_memory
285 .ok_or(CallError::MissingCommand("vkUnmapMemory"))?;
286 unsafe { f(device.handle, memory) };
287 Ok(())
288 }
289
290 #[doc(alias = "vkFlushMappedMemoryRanges")]
297 #[doc = "\n\n[Khronos reference: `vkFlushMappedMemoryRanges`](https://docs.vulkan.org/refpages/latest/refpages/source/vkFlushMappedMemoryRanges.html)"]
298 pub unsafe fn flush_mapped_memory_ranges(
299 ranges: &[vk::MappedMemoryRange],
300 ) -> Result<(), CallError> {
301 let f = device
302 .fp
303 .flush_mapped_memory_ranges
304 .ok_or(CallError::MissingCommand("vkFlushMappedMemoryRanges"))?;
305 let result = unsafe {
306 f(
307 device.handle,
308 u32::try_from(ranges.len()).map_err(|_| CallError::CountOverflow(ranges.len()))?,
309 ranges.as_ptr(),
310 )
311 };
312 if result == vk::Result::SUCCESS {
313 Ok(())
314 } else {
315 Err(CallError::Vulkan(result))
316 }
317 }
318
319 #[doc(alias = "vkInvalidateMappedMemoryRanges")]
326 #[doc = "\n\n[Khronos reference: `vkInvalidateMappedMemoryRanges`](https://docs.vulkan.org/refpages/latest/refpages/source/vkInvalidateMappedMemoryRanges.html)"]
327 pub unsafe fn invalidate_mapped_memory_ranges(
328 ranges: &[vk::MappedMemoryRange],
329 ) -> Result<(), CallError> {
330 let f = device
331 .fp
332 .invalidate_mapped_memory_ranges
333 .ok_or(CallError::MissingCommand("vkInvalidateMappedMemoryRanges"))?;
334 let result = unsafe {
335 f(
336 device.handle,
337 u32::try_from(ranges.len()).map_err(|_| CallError::CountOverflow(ranges.len()))?,
338 ranges.as_ptr(),
339 )
340 };
341 if result == vk::Result::SUCCESS {
342 Ok(())
343 } else {
344 Err(CallError::Vulkan(result))
345 }
346 }
347
348 #[doc(alias = "vkCreateBuffer")]
353 #[doc = "\n\n[Khronos reference: `vkCreateBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateBuffer.html)"]
354 pub unsafe fn create_buffer(
355 create_info: &vk::BufferCreateInfo,
356 allocator: Option<&vk::AllocationCallbacks>,
357 ) -> Result<vk::Buffer, CallError> {
358 let f = device
359 .fp
360 .create_buffer
361 .ok_or(CallError::MissingCommand("vkCreateBuffer"))?;
362 let mut handle = vk::Buffer::NULL;
363 let result = unsafe {
364 f(
365 device.handle,
366 create_info,
367 allocator.map_or(std::ptr::null(), |a| a),
368 &mut handle,
369 )
370 };
371 if result == vk::Result::SUCCESS {
372 Ok(handle)
373 } else {
374 Err(CallError::Vulkan(result))
375 }
376 }
377
378 #[doc(alias = "vkDestroyBuffer")]
383 #[doc = "\n\n[Khronos reference: `vkDestroyBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyBuffer.html)"]
384 pub unsafe fn destroy_buffer(
385 buffer: vk::Buffer,
386 allocator: Option<&vk::AllocationCallbacks>,
387 ) -> Result<(), CallError> {
388 let f = device
389 .fp
390 .destroy_buffer
391 .ok_or(CallError::MissingCommand("vkDestroyBuffer"))?;
392 unsafe {
393 f(
394 device.handle,
395 buffer,
396 allocator.map_or(std::ptr::null(), |a| a),
397 )
398 };
399 Ok(())
400 }
401
402 #[doc(alias = "vkGetBufferMemoryRequirements")]
407 #[doc = "\n\n[Khronos reference: `vkGetBufferMemoryRequirements`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetBufferMemoryRequirements.html)"]
408 pub unsafe fn get_buffer_memory_requirements(
409 buffer: vk::Buffer,
410 ) -> Result<vk::MemoryRequirements, CallError> {
411 let f = device
412 .fp
413 .get_buffer_memory_requirements
414 .ok_or(CallError::MissingCommand("vkGetBufferMemoryRequirements"))?;
415 let mut reqs = unsafe { std::mem::zeroed::<vk::MemoryRequirements>() };
416 unsafe { f(device.handle, buffer, &mut reqs) };
417 Ok(reqs)
418 }
419
420 #[doc(alias = "vkBindBufferMemory")]
426 #[doc = "\n\n[Khronos reference: `vkBindBufferMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkBindBufferMemory.html)"]
427 pub unsafe fn bind_buffer_memory(
428 buffer: vk::Buffer,
429 memory: vk::DeviceMemory,
430 memory_offset: vk::DeviceSize,
431 ) -> Result<(), CallError> {
432 let f = device
433 .fp
434 .bind_buffer_memory
435 .ok_or(CallError::MissingCommand("vkBindBufferMemory"))?;
436 let result = unsafe { f(device.handle, buffer, memory, memory_offset) };
437 if result == vk::Result::SUCCESS {
438 Ok(())
439 } else {
440 Err(CallError::Vulkan(result))
441 }
442 }
443
444 #[doc(alias = "vkCreateCommandPool")]
449 #[doc = "\n\n[Khronos reference: `vkCreateCommandPool`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateCommandPool.html)"]
450 pub unsafe fn create_command_pool(
451 create_info: &vk::CommandPoolCreateInfo,
452 allocator: Option<&vk::AllocationCallbacks>,
453 ) -> Result<vk::CommandPool, CallError> {
454 let f = device
455 .fp
456 .create_command_pool
457 .ok_or(CallError::MissingCommand("vkCreateCommandPool"))?;
458 let mut handle = vk::CommandPool::NULL;
459 let result = unsafe {
460 f(
461 device.handle,
462 create_info,
463 allocator.map_or(std::ptr::null(), |a| a),
464 &mut handle,
465 )
466 };
467 if result == vk::Result::SUCCESS {
468 Ok(handle)
469 } else {
470 Err(CallError::Vulkan(result))
471 }
472 }
473
474 #[doc(alias = "vkDestroyCommandPool")]
479 #[doc = "\n\n[Khronos reference: `vkDestroyCommandPool`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyCommandPool.html)"]
480 pub unsafe fn destroy_command_pool(
481 pool: vk::CommandPool,
482 allocator: Option<&vk::AllocationCallbacks>,
483 ) -> Result<(), CallError> {
484 let f = device
485 .fp
486 .destroy_command_pool
487 .ok_or(CallError::MissingCommand("vkDestroyCommandPool"))?;
488 unsafe {
489 f(
490 device.handle,
491 pool,
492 allocator.map_or(std::ptr::null(), |a| a),
493 )
494 };
495 Ok(())
496 }
497
498 #[doc(alias = "vkAllocateCommandBuffers")]
503 #[doc = "\n\n[Khronos reference: `vkAllocateCommandBuffers`](https://docs.vulkan.org/refpages/latest/refpages/source/vkAllocateCommandBuffers.html)"]
504 pub unsafe fn allocate_command_buffers(
505 allocate_info: &vk::CommandBufferAllocateInfo,
506 ) -> Result<Vec<vk::CommandBuffer>, CallError> {
507 let f = device
508 .fp
509 .allocate_command_buffers
510 .ok_or(CallError::MissingCommand("vkAllocateCommandBuffers"))?;
511 let count = allocate_info.command_buffer_count as usize;
512 let mut bufs = vec![vk::CommandBuffer::NULL; count];
513 let result = unsafe { f(device.handle, allocate_info, bufs.as_mut_ptr()) };
514 if result == vk::Result::SUCCESS {
515 Ok(bufs)
516 } else {
517 Err(CallError::Vulkan(result))
518 }
519 }
520
521 #[doc(alias = "vkFreeCommandBuffers")]
526 #[doc = "\n\n[Khronos reference: `vkFreeCommandBuffers`](https://docs.vulkan.org/refpages/latest/refpages/source/vkFreeCommandBuffers.html)"]
527 pub unsafe fn free_command_buffers(
528 pool: vk::CommandPool,
529 buffers: &[vk::CommandBuffer],
530 ) -> Result<(), CallError> {
531 let f = device
532 .fp
533 .free_command_buffers
534 .ok_or(CallError::MissingCommand("vkFreeCommandBuffers"))?;
535 unsafe {
536 f(
537 device.handle,
538 pool,
539 u32::try_from(buffers.len()).map_err(|_| CallError::CountOverflow(buffers.len()))?,
540 buffers.as_ptr(),
541 )
542 };
543 Ok(())
544 }
545
546 #[doc(alias = "vkBeginCommandBuffer")]
551 #[doc = "\n\n[Khronos reference: `vkBeginCommandBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkBeginCommandBuffer.html)"]
552 pub unsafe fn begin_command_buffer(
553 command_buffer: vk::CommandBuffer,
554 begin_info: &vk::CommandBufferBeginInfo,
555 ) -> Result<(), CallError> {
556 let f = device
557 .fp
558 .begin_command_buffer
559 .ok_or(CallError::MissingCommand("vkBeginCommandBuffer"))?;
560 let result = unsafe { f(command_buffer, begin_info) };
561 if result == vk::Result::SUCCESS {
562 Ok(())
563 } else {
564 Err(CallError::Vulkan(result))
565 }
566 }
567
568 #[doc(alias = "vkEndCommandBuffer")]
573 #[doc = "\n\n[Khronos reference: `vkEndCommandBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkEndCommandBuffer.html)"]
574 pub unsafe fn end_command_buffer(command_buffer: vk::CommandBuffer) -> Result<(), CallError> {
575 let f = device
576 .fp
577 .end_command_buffer
578 .ok_or(CallError::MissingCommand("vkEndCommandBuffer"))?;
579 let result = unsafe { f(command_buffer) };
580 if result == vk::Result::SUCCESS {
581 Ok(())
582 } else {
583 Err(CallError::Vulkan(result))
584 }
585 }
586
587 #[doc(alias = "vkCmdFillBuffer")]
593 #[doc = "\n\n[Khronos reference: `vkCmdFillBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdFillBuffer.html)"]
594 pub unsafe fn cmd_fill_buffer(
595 command_buffer: vk::CommandBuffer,
596 buffer: vk::Buffer,
597 offset: vk::DeviceSize,
598 size: vk::DeviceSize,
599 data: u32,
600 ) -> Result<(), CallError> {
601 let f = device
602 .fp
603 .cmd_fill_buffer
604 .ok_or(CallError::MissingCommand("vkCmdFillBuffer"))?;
605 unsafe { f(command_buffer, buffer, offset, size, data) };
606 Ok(())
607 }
608
609 #[doc(alias = "vkQueueSubmit")]
615 #[doc = "\n\n[Khronos reference: `vkQueueSubmit`](https://docs.vulkan.org/refpages/latest/refpages/source/vkQueueSubmit.html)"]
616 pub unsafe fn queue_submit(
617 queue: vk::Queue,
618 submits: &[vk::SubmitInfo],
619 fence: vk::Fence,
620 ) -> Result<(), CallError> {
621 let f = device
622 .fp
623 .queue_submit
624 .ok_or(CallError::MissingCommand("vkQueueSubmit"))?;
625 let result = unsafe {
626 f(
627 queue,
628 u32::try_from(submits.len()).map_err(|_| CallError::CountOverflow(submits.len()))?,
629 submits.as_ptr(),
630 fence,
631 )
632 };
633 if result == vk::Result::SUCCESS {
634 Ok(())
635 } else {
636 Err(CallError::Vulkan(result))
637 }
638 }
639
640 #[doc(alias = "vkQueueWaitIdle")]
645 #[doc = "\n\n[Khronos reference: `vkQueueWaitIdle`](https://docs.vulkan.org/refpages/latest/refpages/source/vkQueueWaitIdle.html)"]
646 pub unsafe fn queue_wait_idle(queue: vk::Queue) -> Result<(), CallError> {
647 let f = device
648 .fp
649 .queue_wait_idle
650 .ok_or(CallError::MissingCommand("vkQueueWaitIdle"))?;
651 let result = unsafe { f(queue) };
652 if result == vk::Result::SUCCESS {
653 Ok(())
654 } else {
655 Err(CallError::Vulkan(result))
656 }
657 }
658
659 #[doc(alias = "vkCreateFence")]
664 #[doc = "\n\n[Khronos reference: `vkCreateFence`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateFence.html)"]
665 pub unsafe fn create_fence(
666 create_info: &vk::FenceCreateInfo,
667 allocator: Option<&vk::AllocationCallbacks>,
668 ) -> Result<vk::Fence, CallError> {
669 let f = device
670 .fp
671 .create_fence
672 .ok_or(CallError::MissingCommand("vkCreateFence"))?;
673 let mut handle = vk::Fence::NULL;
674 let result = unsafe {
675 f(
676 device.handle,
677 create_info,
678 allocator.map_or(std::ptr::null(), |a| a),
679 &mut handle,
680 )
681 };
682 if result == vk::Result::SUCCESS {
683 Ok(handle)
684 } else {
685 Err(CallError::Vulkan(result))
686 }
687 }
688
689 #[doc(alias = "vkDestroyFence")]
694 #[doc = "\n\n[Khronos reference: `vkDestroyFence`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyFence.html)"]
695 pub unsafe fn destroy_fence(
696 fence: vk::Fence,
697 allocator: Option<&vk::AllocationCallbacks>,
698 ) -> Result<(), CallError> {
699 let f = device
700 .fp
701 .destroy_fence
702 .ok_or(CallError::MissingCommand("vkDestroyFence"))?;
703 unsafe {
704 f(
705 device.handle,
706 fence,
707 allocator.map_or(std::ptr::null(), |a| a),
708 )
709 };
710 Ok(())
711 }
712
713 #[doc(alias = "vkWaitForFences")]
721 #[doc = "\n\n[Khronos reference: `vkWaitForFences`](https://docs.vulkan.org/refpages/latest/refpages/source/vkWaitForFences.html)"]
722 pub unsafe fn wait_for_fences(
723 fences: &[vk::Fence],
724 wait_all: bool,
725 timeout_ns: u64,
726 ) -> Result<bool, CallError> {
727 let f = device
728 .fp
729 .wait_for_fences
730 .ok_or(CallError::MissingCommand("vkWaitForFences"))?;
731 let result = unsafe {
732 f(
733 device.handle,
734 u32::try_from(fences.len()).map_err(|_| CallError::CountOverflow(fences.len()))?,
735 fences.as_ptr(),
736 wait_all as vk::Bool32,
737 timeout_ns,
738 )
739 };
740 match result {
741 vk::Result::SUCCESS => Ok(true),
742 vk::Result::TIMEOUT => Ok(false),
743 other => Err(CallError::Vulkan(other)),
744 }
745 }
746
747 #[doc(alias = "vkResetFences")]
752 #[doc = "\n\n[Khronos reference: `vkResetFences`](https://docs.vulkan.org/refpages/latest/refpages/source/vkResetFences.html)"]
753 pub unsafe fn reset_fences(fences: &[vk::Fence]) -> Result<(), CallError> {
754 let f = device
755 .fp
756 .reset_fences
757 .ok_or(CallError::MissingCommand("vkResetFences"))?;
758 let result = unsafe {
759 f(
760 device.handle,
761 u32::try_from(fences.len()).map_err(|_| CallError::CountOverflow(fences.len()))?,
762 fences.as_ptr(),
763 )
764 };
765 if result == vk::Result::SUCCESS {
766 Ok(())
767 } else {
768 Err(CallError::Vulkan(result))
769 }
770 }
771
772}
773
774#[doc(alias = "vkCreateDevice")]
785#[doc = "\n\n[Khronos reference: `vkCreateDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateDevice.html)"]
786pub unsafe fn create_device(
787 instance: &Instance,
788 physical_device: vk::PhysicalDevice,
789 create_info: &vk::DeviceCreateInfo,
790 allocator: Option<&vk::AllocationCallbacks>,
791) -> Result<Device, CallError> {
792 let gdpa = instance
794 .fp()
795 .get_device_proc_addr
796 .ok_or(CallError::MissingCommand("vkGetDeviceProcAddr"))?;
797 let capabilities = if let Some(parent) = instance.capabilities() {
798 let physical_version = if parent.api_version() == vk::API_VERSION_1_0 {
801 vk::API_VERSION_1_0
802 } else {
803 unsafe { instance.get_physical_device_properties(physical_device) }?.api_version
805 };
806 Some(unsafe { parent.new_from_device_create_info(create_info, physical_version) }?)
808 } else {
809 None
810 };
811 let f = instance
812 .fp()
813 .create_device
814 .ok_or(CallError::MissingCommand("vkCreateDevice"))?;
815 let allocator_ptr = allocator.map_or(std::ptr::null(), |a| a);
816 let mut handle = vk::DeviceHandle::NULL;
817 let result = unsafe { f(physical_device, create_info, allocator_ptr, &mut handle) };
819 if result != vk::Result::SUCCESS {
820 return Err(CallError::Vulkan(result));
821 }
822 if handle.is_null() {
823 return Err(CallError::InvalidOutput(
824 "vkCreateDevice returned a null handle",
825 ));
826 }
827 let mut fp = unsafe { vk::FnDevice::new_from_resolver(gdpa, handle) };
829 if fp.destroy_device.is_none() {
830 let failure = InitializationFailure {
831 handle: CreatedHandle::Device(handle),
832 missing_command: "vkDestroyDevice",
833 library: instance.library.clone(),
834 instance: instance.handle(),
835 gipa: instance.gipa,
836 gdpa: Some(gdpa),
837 };
838 return match unsafe { failure.destroy(allocator) } {
840 Ok(()) => Err(CallError::MissingCommand("vkDestroyDevice")),
841 Err(failure) => Err(CallError::InitializationFailed(failure)),
842 };
843 }
844 if let Some(capabilities) = &capabilities {
845 fp.retain_enabled(|command| capabilities.support(command) == CommandSupport::Enabled);
846 }
847 Ok(Device {
848 handle,
849 fp,
850 gdpa,
851 _library: instance.library.clone(),
852 capabilities,
853 })
854}
855
856impl Device {
857 #[doc(alias = "vkCreateDevice")]
861 #[doc = "\n\n[Khronos reference: `vkCreateDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateDevice.html)"]
862 pub unsafe fn new(
863 instance: &Instance,
864 physical_device: vk::PhysicalDevice,
865 create_info: &vk::DeviceCreateInfo,
866 allocator: Option<&vk::AllocationCallbacks>,
867 ) -> Result<Self, CallError> {
868 unsafe { create_device(instance, physical_device, create_info, allocator) }
870 }
871}
872
873impl Instance {
874 #[doc(alias = "vkCreateDevice")]
878 #[doc = "\n\n[Khronos reference: `vkCreateDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateDevice.html)"]
879 pub unsafe fn create_device(
880 &self,
881 physical_device: vk::PhysicalDevice,
882 create_info: &vk::DeviceCreateInfo,
883 allocator: Option<&vk::AllocationCallbacks>,
884 ) -> Result<Device, CallError> {
885 unsafe { create_device(self, physical_device, create_info, allocator) }
887 }
888}
889
890#[doc(alias = "vkDestroyDevice")]
896#[doc = "\n\n[Khronos reference: `vkDestroyDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyDevice.html)"]
897pub unsafe fn destroy_device(device: Device, allocator: Option<&vk::AllocationCallbacks>) {
898 unsafe {
900 device.fp.destroy_device.unwrap()(device.handle, allocator.map_or(std::ptr::null(), |a| a))
901 };
902}