use super::Instance;
use crate as vk;
use crate::load::{
CallError, Capabilities, CommandSupport, CreatedHandle, InitializationFailure, LoadError,
};
use libloading::Library;
use std::sync::Arc;
pub struct Device {
handle: vk::DeviceHandle,
fp: vk::FnDevice,
gdpa:
unsafe extern "system" fn(vk::DeviceHandle, *const std::ffi::c_char) -> vk::PFN_vkVoidFunction,
_library: Option<Arc<Library>>,
capabilities: Option<Capabilities>,
}
impl Device {
pub unsafe fn new_from_handle(
instance: &Instance,
handle: vk::DeviceHandle,
) -> Result<Self, LoadError> {
if handle.is_null() {
return Err(LoadError::NullHandle("device"));
}
let gdpa = instance
.fp()
.get_device_proc_addr
.ok_or(LoadError::MissingSymbol("vkGetDeviceProcAddr"))?;
let fp = unsafe { vk::FnDevice::new_from_resolver(gdpa, handle) };
if fp.destroy_device.is_none() {
return Err(LoadError::MissingSymbol("vkDestroyDevice"));
}
Ok(Self {
handle,
fp,
gdpa,
_library: instance.library.clone(),
capabilities: None,
})
}
pub unsafe fn new_from_handle_with_capabilities(
instance: &Instance,
handle: vk::DeviceHandle,
capabilities: Capabilities,
) -> Result<Self, LoadError> {
if !capabilities.is_device() {
return Err(LoadError::InvalidMetadata(
"device import needs device capabilities",
));
}
if let Some(parent) = instance.capabilities()
&& !capabilities.matches_instance(parent)
{
return Err(LoadError::InvalidMetadata(
"device capabilities disagree with parent instance",
));
}
let mut device = unsafe { Self::new_from_handle(instance, handle) }?;
device
.fp
.retain_enabled(|command| capabilities.support(command) == CommandSupport::Enabled);
device.capabilities = Some(capabilities);
Ok(device)
}
pub fn handle(&self) -> vk::DeviceHandle {
self.handle
}
pub fn fp(&self) -> &vk::FnDevice {
&self.fp
}
pub fn capabilities(&self) -> Option<&Capabilities> {
self.capabilities.as_ref()
}
#[doc(alias = "vkDestroyDevice")]
#[doc = "\n\n[Khronos reference: `vkDestroyDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyDevice.html)"]
pub unsafe fn destroy(self, allocator: Option<&vk::AllocationCallbacks>) {
unsafe { destroy_device(self, allocator) };
}
}
use super::command::commands;
commands! { Device, device;
#[doc(alias = "vkGetDeviceQueue")]
#[doc = "\n\n[Khronos reference: `vkGetDeviceQueue`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetDeviceQueue.html)"]
pub unsafe fn get_device_queue(
queue_family_index: u32,
queue_index: u32,
) -> Result<vk::Queue, CallError> {
let f = device
.fp
.get_device_queue
.ok_or(CallError::MissingCommand("vkGetDeviceQueue"))?;
let mut queue = vk::Queue::NULL;
unsafe { f(device.handle, queue_family_index, queue_index, &mut queue) };
Ok(queue)
}
#[doc(alias = "vkGetDeviceProcAddr")]
#[doc = "\n\n[Khronos reference: `vkGetDeviceProcAddr`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetDeviceProcAddr.html)"]
pub unsafe fn get_device_proc_addr(name: &std::ffi::CStr) -> vk::PFN_vkVoidFunction {
unsafe { (device.gdpa)(device.handle, name.as_ptr()) }
}
#[doc(alias = "vkCmdDispatch")]
#[doc = "\n\n[Khronos reference: `vkCmdDispatch`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdDispatch.html)"]
pub unsafe fn cmd_dispatch(
command_buffer: vk::CommandBuffer,
group_count_x: u32,
group_count_y: u32,
group_count_z: u32,
) -> Result<(), CallError> {
let f = device
.fp
.cmd_dispatch
.ok_or(CallError::MissingCommand("vkCmdDispatch"))?;
unsafe { f(command_buffer, group_count_x, group_count_y, group_count_z) };
Ok(())
}
#[doc(alias = "vkAllocateMemory")]
#[doc = "\n\n[Khronos reference: `vkAllocateMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkAllocateMemory.html)"]
pub unsafe fn allocate_memory(
allocate_info: &vk::MemoryAllocateInfo,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<vk::DeviceMemory, CallError> {
let f = device
.fp
.allocate_memory
.ok_or(CallError::MissingCommand("vkAllocateMemory"))?;
let mut handle = vk::DeviceMemory::NULL;
let result = unsafe {
f(
device.handle,
allocate_info,
allocator.map_or(std::ptr::null(), |a| a),
&mut handle,
)
};
if result == vk::Result::SUCCESS {
Ok(handle)
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkFreeMemory")]
#[doc = "\n\n[Khronos reference: `vkFreeMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkFreeMemory.html)"]
pub unsafe fn free_memory(
memory: vk::DeviceMemory,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<(), CallError> {
let f = device
.fp
.free_memory
.ok_or(CallError::MissingCommand("vkFreeMemory"))?;
unsafe {
f(
device.handle,
memory,
allocator.map_or(std::ptr::null(), |a| a),
)
};
Ok(())
}
#[doc(alias = "vkMapMemory")]
#[doc = "\n\n[Khronos reference: `vkMapMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkMapMemory.html)"]
pub unsafe fn map_memory(
memory: vk::DeviceMemory,
offset: vk::DeviceSize,
size: vk::DeviceSize,
flags: vk::MemoryMapFlags,
) -> Result<*mut std::ffi::c_void, CallError> {
let f = device
.fp
.map_memory
.ok_or(CallError::MissingCommand("vkMapMemory"))?;
let mut ptr = std::ptr::null_mut();
let result = unsafe { f(device.handle, memory, offset, size, flags, &mut ptr) };
if result == vk::Result::SUCCESS {
Ok(ptr)
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkUnmapMemory")]
#[doc = "\n\n[Khronos reference: `vkUnmapMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkUnmapMemory.html)"]
pub unsafe fn unmap_memory(memory: vk::DeviceMemory) -> Result<(), CallError> {
let f = device
.fp
.unmap_memory
.ok_or(CallError::MissingCommand("vkUnmapMemory"))?;
unsafe { f(device.handle, memory) };
Ok(())
}
#[doc(alias = "vkFlushMappedMemoryRanges")]
#[doc = "\n\n[Khronos reference: `vkFlushMappedMemoryRanges`](https://docs.vulkan.org/refpages/latest/refpages/source/vkFlushMappedMemoryRanges.html)"]
pub unsafe fn flush_mapped_memory_ranges(
ranges: &[vk::MappedMemoryRange],
) -> Result<(), CallError> {
let f = device
.fp
.flush_mapped_memory_ranges
.ok_or(CallError::MissingCommand("vkFlushMappedMemoryRanges"))?;
let result = unsafe {
f(
device.handle,
u32::try_from(ranges.len()).map_err(|_| CallError::CountOverflow(ranges.len()))?,
ranges.as_ptr(),
)
};
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkInvalidateMappedMemoryRanges")]
#[doc = "\n\n[Khronos reference: `vkInvalidateMappedMemoryRanges`](https://docs.vulkan.org/refpages/latest/refpages/source/vkInvalidateMappedMemoryRanges.html)"]
pub unsafe fn invalidate_mapped_memory_ranges(
ranges: &[vk::MappedMemoryRange],
) -> Result<(), CallError> {
let f = device
.fp
.invalidate_mapped_memory_ranges
.ok_or(CallError::MissingCommand("vkInvalidateMappedMemoryRanges"))?;
let result = unsafe {
f(
device.handle,
u32::try_from(ranges.len()).map_err(|_| CallError::CountOverflow(ranges.len()))?,
ranges.as_ptr(),
)
};
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkCreateBuffer")]
#[doc = "\n\n[Khronos reference: `vkCreateBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateBuffer.html)"]
pub unsafe fn create_buffer(
create_info: &vk::BufferCreateInfo,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<vk::Buffer, CallError> {
let f = device
.fp
.create_buffer
.ok_or(CallError::MissingCommand("vkCreateBuffer"))?;
let mut handle = vk::Buffer::NULL;
let result = unsafe {
f(
device.handle,
create_info,
allocator.map_or(std::ptr::null(), |a| a),
&mut handle,
)
};
if result == vk::Result::SUCCESS {
Ok(handle)
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkDestroyBuffer")]
#[doc = "\n\n[Khronos reference: `vkDestroyBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyBuffer.html)"]
pub unsafe fn destroy_buffer(
buffer: vk::Buffer,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<(), CallError> {
let f = device
.fp
.destroy_buffer
.ok_or(CallError::MissingCommand("vkDestroyBuffer"))?;
unsafe {
f(
device.handle,
buffer,
allocator.map_or(std::ptr::null(), |a| a),
)
};
Ok(())
}
#[doc(alias = "vkGetBufferMemoryRequirements")]
#[doc = "\n\n[Khronos reference: `vkGetBufferMemoryRequirements`](https://docs.vulkan.org/refpages/latest/refpages/source/vkGetBufferMemoryRequirements.html)"]
pub unsafe fn get_buffer_memory_requirements(
buffer: vk::Buffer,
) -> Result<vk::MemoryRequirements, CallError> {
let f = device
.fp
.get_buffer_memory_requirements
.ok_or(CallError::MissingCommand("vkGetBufferMemoryRequirements"))?;
let mut reqs = unsafe { std::mem::zeroed::<vk::MemoryRequirements>() };
unsafe { f(device.handle, buffer, &mut reqs) };
Ok(reqs)
}
#[doc(alias = "vkBindBufferMemory")]
#[doc = "\n\n[Khronos reference: `vkBindBufferMemory`](https://docs.vulkan.org/refpages/latest/refpages/source/vkBindBufferMemory.html)"]
pub unsafe fn bind_buffer_memory(
buffer: vk::Buffer,
memory: vk::DeviceMemory,
memory_offset: vk::DeviceSize,
) -> Result<(), CallError> {
let f = device
.fp
.bind_buffer_memory
.ok_or(CallError::MissingCommand("vkBindBufferMemory"))?;
let result = unsafe { f(device.handle, buffer, memory, memory_offset) };
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkCreateCommandPool")]
#[doc = "\n\n[Khronos reference: `vkCreateCommandPool`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateCommandPool.html)"]
pub unsafe fn create_command_pool(
create_info: &vk::CommandPoolCreateInfo,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<vk::CommandPool, CallError> {
let f = device
.fp
.create_command_pool
.ok_or(CallError::MissingCommand("vkCreateCommandPool"))?;
let mut handle = vk::CommandPool::NULL;
let result = unsafe {
f(
device.handle,
create_info,
allocator.map_or(std::ptr::null(), |a| a),
&mut handle,
)
};
if result == vk::Result::SUCCESS {
Ok(handle)
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkDestroyCommandPool")]
#[doc = "\n\n[Khronos reference: `vkDestroyCommandPool`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyCommandPool.html)"]
pub unsafe fn destroy_command_pool(
pool: vk::CommandPool,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<(), CallError> {
let f = device
.fp
.destroy_command_pool
.ok_or(CallError::MissingCommand("vkDestroyCommandPool"))?;
unsafe {
f(
device.handle,
pool,
allocator.map_or(std::ptr::null(), |a| a),
)
};
Ok(())
}
#[doc(alias = "vkAllocateCommandBuffers")]
#[doc = "\n\n[Khronos reference: `vkAllocateCommandBuffers`](https://docs.vulkan.org/refpages/latest/refpages/source/vkAllocateCommandBuffers.html)"]
pub unsafe fn allocate_command_buffers(
allocate_info: &vk::CommandBufferAllocateInfo,
) -> Result<Vec<vk::CommandBuffer>, CallError> {
let f = device
.fp
.allocate_command_buffers
.ok_or(CallError::MissingCommand("vkAllocateCommandBuffers"))?;
let count = allocate_info.command_buffer_count as usize;
let mut bufs = vec![vk::CommandBuffer::NULL; count];
let result = unsafe { f(device.handle, allocate_info, bufs.as_mut_ptr()) };
if result == vk::Result::SUCCESS {
Ok(bufs)
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkFreeCommandBuffers")]
#[doc = "\n\n[Khronos reference: `vkFreeCommandBuffers`](https://docs.vulkan.org/refpages/latest/refpages/source/vkFreeCommandBuffers.html)"]
pub unsafe fn free_command_buffers(
pool: vk::CommandPool,
buffers: &[vk::CommandBuffer],
) -> Result<(), CallError> {
let f = device
.fp
.free_command_buffers
.ok_or(CallError::MissingCommand("vkFreeCommandBuffers"))?;
unsafe {
f(
device.handle,
pool,
u32::try_from(buffers.len()).map_err(|_| CallError::CountOverflow(buffers.len()))?,
buffers.as_ptr(),
)
};
Ok(())
}
#[doc(alias = "vkBeginCommandBuffer")]
#[doc = "\n\n[Khronos reference: `vkBeginCommandBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkBeginCommandBuffer.html)"]
pub unsafe fn begin_command_buffer(
command_buffer: vk::CommandBuffer,
begin_info: &vk::CommandBufferBeginInfo,
) -> Result<(), CallError> {
let f = device
.fp
.begin_command_buffer
.ok_or(CallError::MissingCommand("vkBeginCommandBuffer"))?;
let result = unsafe { f(command_buffer, begin_info) };
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkEndCommandBuffer")]
#[doc = "\n\n[Khronos reference: `vkEndCommandBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkEndCommandBuffer.html)"]
pub unsafe fn end_command_buffer(command_buffer: vk::CommandBuffer) -> Result<(), CallError> {
let f = device
.fp
.end_command_buffer
.ok_or(CallError::MissingCommand("vkEndCommandBuffer"))?;
let result = unsafe { f(command_buffer) };
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkCmdFillBuffer")]
#[doc = "\n\n[Khronos reference: `vkCmdFillBuffer`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdFillBuffer.html)"]
pub unsafe fn cmd_fill_buffer(
command_buffer: vk::CommandBuffer,
buffer: vk::Buffer,
offset: vk::DeviceSize,
size: vk::DeviceSize,
data: u32,
) -> Result<(), CallError> {
let f = device
.fp
.cmd_fill_buffer
.ok_or(CallError::MissingCommand("vkCmdFillBuffer"))?;
unsafe { f(command_buffer, buffer, offset, size, data) };
Ok(())
}
#[doc(alias = "vkQueueSubmit")]
#[doc = "\n\n[Khronos reference: `vkQueueSubmit`](https://docs.vulkan.org/refpages/latest/refpages/source/vkQueueSubmit.html)"]
pub unsafe fn queue_submit(
queue: vk::Queue,
submits: &[vk::SubmitInfo],
fence: vk::Fence,
) -> Result<(), CallError> {
let f = device
.fp
.queue_submit
.ok_or(CallError::MissingCommand("vkQueueSubmit"))?;
let result = unsafe {
f(
queue,
u32::try_from(submits.len()).map_err(|_| CallError::CountOverflow(submits.len()))?,
submits.as_ptr(),
fence,
)
};
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkQueueWaitIdle")]
#[doc = "\n\n[Khronos reference: `vkQueueWaitIdle`](https://docs.vulkan.org/refpages/latest/refpages/source/vkQueueWaitIdle.html)"]
pub unsafe fn queue_wait_idle(queue: vk::Queue) -> Result<(), CallError> {
let f = device
.fp
.queue_wait_idle
.ok_or(CallError::MissingCommand("vkQueueWaitIdle"))?;
let result = unsafe { f(queue) };
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkCreateFence")]
#[doc = "\n\n[Khronos reference: `vkCreateFence`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateFence.html)"]
pub unsafe fn create_fence(
create_info: &vk::FenceCreateInfo,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<vk::Fence, CallError> {
let f = device
.fp
.create_fence
.ok_or(CallError::MissingCommand("vkCreateFence"))?;
let mut handle = vk::Fence::NULL;
let result = unsafe {
f(
device.handle,
create_info,
allocator.map_or(std::ptr::null(), |a| a),
&mut handle,
)
};
if result == vk::Result::SUCCESS {
Ok(handle)
} else {
Err(CallError::Vulkan(result))
}
}
#[doc(alias = "vkDestroyFence")]
#[doc = "\n\n[Khronos reference: `vkDestroyFence`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyFence.html)"]
pub unsafe fn destroy_fence(
fence: vk::Fence,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<(), CallError> {
let f = device
.fp
.destroy_fence
.ok_or(CallError::MissingCommand("vkDestroyFence"))?;
unsafe {
f(
device.handle,
fence,
allocator.map_or(std::ptr::null(), |a| a),
)
};
Ok(())
}
#[doc(alias = "vkWaitForFences")]
#[doc = "\n\n[Khronos reference: `vkWaitForFences`](https://docs.vulkan.org/refpages/latest/refpages/source/vkWaitForFences.html)"]
pub unsafe fn wait_for_fences(
fences: &[vk::Fence],
wait_all: bool,
timeout_ns: u64,
) -> Result<bool, CallError> {
let f = device
.fp
.wait_for_fences
.ok_or(CallError::MissingCommand("vkWaitForFences"))?;
let result = unsafe {
f(
device.handle,
u32::try_from(fences.len()).map_err(|_| CallError::CountOverflow(fences.len()))?,
fences.as_ptr(),
wait_all as vk::Bool32,
timeout_ns,
)
};
match result {
vk::Result::SUCCESS => Ok(true),
vk::Result::TIMEOUT => Ok(false),
other => Err(CallError::Vulkan(other)),
}
}
#[doc(alias = "vkResetFences")]
#[doc = "\n\n[Khronos reference: `vkResetFences`](https://docs.vulkan.org/refpages/latest/refpages/source/vkResetFences.html)"]
pub unsafe fn reset_fences(fences: &[vk::Fence]) -> Result<(), CallError> {
let f = device
.fp
.reset_fences
.ok_or(CallError::MissingCommand("vkResetFences"))?;
let result = unsafe {
f(
device.handle,
u32::try_from(fences.len()).map_err(|_| CallError::CountOverflow(fences.len()))?,
fences.as_ptr(),
)
};
if result == vk::Result::SUCCESS {
Ok(())
} else {
Err(CallError::Vulkan(result))
}
}
}
#[doc(alias = "vkCreateDevice")]
#[doc = "\n\n[Khronos reference: `vkCreateDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateDevice.html)"]
pub unsafe fn create_device(
instance: &Instance,
physical_device: vk::PhysicalDevice,
create_info: &vk::DeviceCreateInfo,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<Device, CallError> {
let gdpa = instance
.fp()
.get_device_proc_addr
.ok_or(CallError::MissingCommand("vkGetDeviceProcAddr"))?;
let capabilities = if let Some(parent) = instance.capabilities() {
let physical_version = if parent.api_version() == vk::API_VERSION_1_0 {
vk::API_VERSION_1_0
} else {
unsafe { instance.get_physical_device_properties(physical_device) }?.api_version
};
Some(unsafe { parent.new_from_device_create_info(create_info, physical_version) }?)
} else {
None
};
let f = instance
.fp()
.create_device
.ok_or(CallError::MissingCommand("vkCreateDevice"))?;
let allocator_ptr = allocator.map_or(std::ptr::null(), |a| a);
let mut handle = vk::DeviceHandle::NULL;
let result = unsafe { f(physical_device, create_info, allocator_ptr, &mut handle) };
if result != vk::Result::SUCCESS {
return Err(CallError::Vulkan(result));
}
if handle.is_null() {
return Err(CallError::InvalidOutput(
"vkCreateDevice returned a null handle",
));
}
let mut fp = unsafe { vk::FnDevice::new_from_resolver(gdpa, handle) };
if fp.destroy_device.is_none() {
let failure = InitializationFailure {
handle: CreatedHandle::Device(handle),
missing_command: "vkDestroyDevice",
library: instance.library.clone(),
instance: instance.handle(),
gipa: instance.gipa,
gdpa: Some(gdpa),
};
return match unsafe { failure.destroy(allocator) } {
Ok(()) => Err(CallError::MissingCommand("vkDestroyDevice")),
Err(failure) => Err(CallError::InitializationFailed(failure)),
};
}
if let Some(capabilities) = &capabilities {
fp.retain_enabled(|command| capabilities.support(command) == CommandSupport::Enabled);
}
Ok(Device {
handle,
fp,
gdpa,
_library: instance.library.clone(),
capabilities,
})
}
impl Device {
#[doc(alias = "vkCreateDevice")]
#[doc = "\n\n[Khronos reference: `vkCreateDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateDevice.html)"]
pub unsafe fn new(
instance: &Instance,
physical_device: vk::PhysicalDevice,
create_info: &vk::DeviceCreateInfo,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<Self, CallError> {
unsafe { create_device(instance, physical_device, create_info, allocator) }
}
}
impl Instance {
#[doc(alias = "vkCreateDevice")]
#[doc = "\n\n[Khronos reference: `vkCreateDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateDevice.html)"]
pub unsafe fn create_device(
&self,
physical_device: vk::PhysicalDevice,
create_info: &vk::DeviceCreateInfo,
allocator: Option<&vk::AllocationCallbacks>,
) -> Result<Device, CallError> {
unsafe { create_device(self, physical_device, create_info, allocator) }
}
}
#[doc(alias = "vkDestroyDevice")]
#[doc = "\n\n[Khronos reference: `vkDestroyDevice`](https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyDevice.html)"]
pub unsafe fn destroy_device(device: Device, allocator: Option<&vk::AllocationCallbacks>) {
unsafe {
device.fp.destroy_device.unwrap()(device.handle, allocator.map_or(std::ptr::null(), |a| a))
};
}