// SPDX-License-Identifier: LGPL-2.1-or-later // Copyright 2018 Jacob Lifshay use api; use api_impl::{Device, Instance, PhysicalDevice, Queue}; use buffer::{Buffer, BufferView}; use descriptor_set::{DescriptorPool, DescriptorSet, DescriptorSetLayout}; use device_memory::DeviceMemory; use image::{Image, ImageView}; use pipeline::{Pipeline, PipelineLayout}; use render_pass::RenderPass; use sampler::Sampler; use sampler::SamplerYcbcrConversion; use shader_module::ShaderModule; use std::fmt; use std::marker::PhantomData; use std::mem; use std::ops::Deref; use std::ops::DerefMut; use std::ptr::null_mut; use std::ptr::NonNull; use swapchain::Swapchain; #[repr(C)] pub struct DispatchableType { loader_dispatch_ptr: usize, value: T, } impl From for DispatchableType { fn from(v: T) -> Self { Self { loader_dispatch_ptr: api::ICD_LOADER_MAGIC as usize, value: v, } } } impl Deref for DispatchableType { type Target = T; fn deref(&self) -> &T { &self.value } } impl DerefMut for DispatchableType { fn deref_mut(&mut self) -> &mut T { &mut self.value } } pub trait HandleAllocFree: Handle { unsafe fn allocate>(v: T) -> Self { Self::new(Some(NonNull::new_unchecked(Box::into_raw(Box::new( v.into(), ))))) } unsafe fn free(self) { Box::from_raw(self.get().unwrap().as_ptr()); } } pub trait Handle: Copy + Eq + fmt::Debug { type Value; fn get(&self) -> Option>; fn new(v: Option>) -> Self; fn null() -> Self { Self::new(None) } fn is_null(&self) -> bool { self.get().is_none() } fn take(&mut self) -> Self { let retval = *self; *self = Self::null(); retval } } #[repr(transparent)] pub struct DispatchableHandle(Option>, PhantomData<*mut DispatchableType>); impl Clone for DispatchableHandle { fn clone(&self) -> Self { DispatchableHandle(self.0, PhantomData) } } impl Copy for DispatchableHandle {} impl Eq for DispatchableHandle {} impl PartialEq for DispatchableHandle { fn eq(&self, rhs: &Self) -> bool { self.0 == rhs.0 } } impl fmt::Debug for DispatchableHandle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("DispatchableHandle") .field( &self .get() .map(|v| v.as_ptr()) .unwrap_or(null_mut::<*mut ()>() as *mut _), ) .finish() } } impl Handle for DispatchableHandle { type Value = DispatchableType; fn get(&self) -> Option>> { unsafe { mem::transmute(self.0) } } fn new(v: Option>>) -> Self { unsafe { DispatchableHandle(mem::transmute(v), PhantomData) } } } #[repr(transparent)] pub struct NondispatchableHandle(u64, PhantomData>>); impl Clone for NondispatchableHandle { fn clone(&self) -> Self { NondispatchableHandle(self.0, PhantomData) } } impl Copy for NondispatchableHandle {} impl Eq for NondispatchableHandle {} impl PartialEq for NondispatchableHandle { fn eq(&self, rhs: &Self) -> bool { self.0 == rhs.0 } } impl fmt::Debug for NondispatchableHandle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("NondispatchableHandle") .field(&self.get().map(|v| v.as_ptr()).unwrap_or(null_mut())) .finish() } } impl Handle for NondispatchableHandle { type Value = T; fn get(&self) -> Option> { NonNull::new(self.0 as *mut T) } fn new(v: Option>) -> Self { NondispatchableHandle( v.map(|v| v.as_ptr()).unwrap_or(null_mut()) as u64, PhantomData, ) } } #[repr(transparent)] pub struct OwnedHandle(NonNull); impl OwnedHandle { pub fn new>(v: I) -> Self { unsafe { OwnedHandle(T::allocate(v).get().unwrap()) } } pub unsafe fn from(v: T) -> Option { v.get().map(OwnedHandle) } pub unsafe fn take(self) -> T { let retval = self.0; mem::forget(self); T::new(Some(retval)) } pub unsafe fn get_handle(&self) -> T { T::new(Some(self.0)) } } impl Deref for OwnedHandle { type Target = T::Value; fn deref(&self) -> &T::Value { unsafe { &*self.0.as_ptr() } } } impl DerefMut for OwnedHandle { fn deref_mut(&mut self) -> &mut T::Value { unsafe { &mut *self.0.as_ptr() } } } impl Drop for OwnedHandle { fn drop(&mut self) { unsafe { T::new(Some(self.0)).free(); } } } impl fmt::Debug for OwnedHandle where T::Value: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("OwnedHandle").field((*self).deref()).finish() } } #[repr(transparent)] pub struct SharedHandle(NonNull); impl Copy for SharedHandle {} impl Clone for SharedHandle { fn clone(&self) -> Self { SharedHandle(self.0) } } impl SharedHandle { pub unsafe fn from(v: T) -> Option { v.get().map(SharedHandle) } #[allow(dead_code)] pub unsafe fn take(self) -> T { T::new(Some(self.0)) } pub unsafe fn get_handle(self) -> T { T::new(Some(self.0)) } pub fn into_nonnull(self) -> NonNull { self.0 } } impl Deref for SharedHandle { type Target = T::Value; fn deref(&self) -> &T::Value { unsafe { &*self.0.as_ptr() } } } impl fmt::Debug for SharedHandle where T::Value: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("SharedHandle") .field((*self).deref()) .finish() } } #[repr(transparent)] pub struct MutHandle(NonNull); impl MutHandle { pub unsafe fn from(v: T) -> Option { v.get().map(MutHandle) } #[allow(dead_code)] pub unsafe fn take(self) -> T { T::new(Some(self.0)) } #[allow(dead_code)] pub unsafe fn get_handle(&self) -> T { T::new(Some(self.0)) } #[allow(dead_code)] pub fn into_nonnull(self) -> NonNull { self.0 } } impl Deref for MutHandle { type Target = T::Value; fn deref(&self) -> &T::Value { unsafe { &*self.0.as_ptr() } } } impl DerefMut for MutHandle { fn deref_mut(&mut self) -> &mut T::Value { unsafe { &mut *self.0.as_ptr() } } } impl fmt::Debug for MutHandle where T::Value: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("MutHandle").field((*self).deref()).finish() } } pub type VkInstance = DispatchableHandle; impl HandleAllocFree for VkInstance {} pub type VkPhysicalDevice = DispatchableHandle; impl HandleAllocFree for VkPhysicalDevice {} pub type VkDevice = DispatchableHandle; impl HandleAllocFree for VkDevice {} pub type VkQueue = DispatchableHandle; impl HandleAllocFree for VkQueue {} pub struct CommandBuffer {} pub type VkCommandBuffer = DispatchableHandle; impl HandleAllocFree for VkCommandBuffer {} pub struct Semaphore {} pub type VkSemaphore = NondispatchableHandle; impl HandleAllocFree for VkSemaphore {} pub struct Fence {} pub type VkFence = NondispatchableHandle; impl HandleAllocFree for VkFence {} pub type VkDeviceMemory = NondispatchableHandle; impl HandleAllocFree for VkDeviceMemory {} pub type VkBuffer = NondispatchableHandle; impl HandleAllocFree for VkBuffer {} pub type VkImage = NondispatchableHandle; impl HandleAllocFree for VkImage {} pub struct Event {} pub type VkEvent = NondispatchableHandle; impl HandleAllocFree for VkEvent {} pub struct QueryPool {} pub type VkQueryPool = NondispatchableHandle; impl HandleAllocFree for VkQueryPool {} pub type VkBufferView = NondispatchableHandle; impl HandleAllocFree for VkBufferView {} pub type VkImageView = NondispatchableHandle; impl HandleAllocFree for VkImageView {} pub type VkShaderModule = NondispatchableHandle; impl HandleAllocFree for VkShaderModule {} pub struct PipelineCache {} pub type VkPipelineCache = NondispatchableHandle; impl HandleAllocFree for VkPipelineCache {} pub type VkPipelineLayout = NondispatchableHandle; impl HandleAllocFree for VkPipelineLayout {} pub type VkRenderPass = NondispatchableHandle; impl HandleAllocFree for VkRenderPass {} pub type VkPipeline = NondispatchableHandle; impl HandleAllocFree for VkPipeline {} pub type VkDescriptorSetLayout = NondispatchableHandle; impl HandleAllocFree for VkDescriptorSetLayout {} pub type VkSampler = NondispatchableHandle; impl HandleAllocFree for VkSampler {} pub type VkDescriptorPool = NondispatchableHandle; impl HandleAllocFree for VkDescriptorPool {} pub type VkDescriptorSet = NondispatchableHandle; impl HandleAllocFree for VkDescriptorSet {} pub struct Framebuffer {} pub type VkFramebuffer = NondispatchableHandle; impl HandleAllocFree for VkFramebuffer {} pub struct CommandPool {} pub type VkCommandPool = NondispatchableHandle; impl HandleAllocFree for VkCommandPool {} pub type VkSamplerYcbcrConversion = NondispatchableHandle; impl HandleAllocFree for VkSamplerYcbcrConversion {} pub struct DescriptorUpdateTemplate {} pub type VkDescriptorUpdateTemplate = NondispatchableHandle; impl HandleAllocFree for VkDescriptorUpdateTemplate {} pub type VkSurfaceKHR = NondispatchableHandle; // HandleAllocFree specifically not implemented for VkSurfaceKHR pub type VkSwapchainKHR = NondispatchableHandle>; impl HandleAllocFree for VkSwapchainKHR {} pub struct DisplayKHR {} pub type VkDisplayKHR = NondispatchableHandle; impl HandleAllocFree for VkDisplayKHR {} pub struct DisplayModeKHR {} pub type VkDisplayModeKHR = NondispatchableHandle; impl HandleAllocFree for VkDisplayModeKHR {} pub struct DebugReportCallbackEXT {} pub type VkDebugReportCallbackEXT = NondispatchableHandle; impl HandleAllocFree for VkDebugReportCallbackEXT {} pub struct DebugUtilsMessengerEXT {} pub type VkDebugUtilsMessengerEXT = NondispatchableHandle; impl HandleAllocFree for VkDebugUtilsMessengerEXT {} pub struct ValidationCacheEXT {} pub type VkValidationCacheEXT = NondispatchableHandle; impl HandleAllocFree for VkValidationCacheEXT {}