use ash::{
extensions::{ext, khr, nv},
vk,
};
pub trait Destroyable {
type Destroyer: ?Sized;
unsafe fn destroy_with(
&mut self,
destroyer: &Self::Destroyer,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
);
}
impl Destroyable for ash::Instance {
type Destroyer = ();
unsafe fn destroy_with(
&mut self,
_destroyer: &(),
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
self.destroy_instance(allocation_callbacks);
}
}
impl Destroyable for ash::Device {
type Destroyer = ();
unsafe fn destroy_with(
&mut self,
_destroyer: &(),
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
self.destroy_device(allocation_callbacks);
}
}
macro_rules! destroyable {
($destroy:ident, $Resource:ty) => {
impl Destroyable for $Resource {
type Destroyer = ash::Device;
unsafe fn destroy_with(
&mut self,
device: &ash::Device,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
device.$destroy(*self, allocation_callbacks);
}
}
};
}
destroyable!(destroy_buffer, vk::Buffer);
destroyable!(destroy_buffer_view, vk::BufferView);
destroyable!(destroy_command_pool, vk::CommandPool);
destroyable!(destroy_descriptor_pool, vk::DescriptorPool);
destroyable!(destroy_descriptor_set_layout, vk::DescriptorSetLayout);
destroyable!(free_memory, vk::DeviceMemory);
destroyable!(destroy_event, vk::Event);
destroyable!(destroy_fence, vk::Fence);
destroyable!(destroy_framebuffer, vk::Framebuffer);
destroyable!(destroy_image, vk::Image);
destroyable!(destroy_image_view, vk::ImageView);
destroyable!(destroy_pipeline, vk::Pipeline);
destroyable!(destroy_pipeline_layout, vk::PipelineLayout);
destroyable!(destroy_pipeline_cache, vk::PipelineCache);
destroyable!(destroy_query_pool, vk::QueryPool);
destroyable!(destroy_render_pass, vk::RenderPass);
destroyable!(destroy_sampler, vk::Sampler);
destroyable!(destroy_semaphore, vk::Semaphore);
destroyable!(destroy_shader_module, vk::ShaderModule);
destroyable!(
destroy_descriptor_update_template,
vk::DescriptorUpdateTemplate
);
destroyable!(destroy_sampler_ycbcr_conversion, vk::SamplerYcbcrConversion);
macro_rules! destroyable_ext {
($Destroyer:ty, $destroy:ident, $Resource:ty) => {
impl Destroyable for $Resource {
type Destroyer = $Destroyer;
unsafe fn destroy_with(
&mut self,
destroyer: &Self::Destroyer,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
destroyer.$destroy(*self, allocation_callbacks);
}
}
};
}
destroyable_ext!(
khr::AccelerationStructure,
destroy_acceleration_structure,
vk::AccelerationStructureKHR
);
destroyable_ext!(
nv::RayTracing,
destroy_acceleration_structure,
vk::AccelerationStructureNV
);
destroyable_ext!(
ext::DebugUtils,
destroy_debug_utils_messenger,
vk::DebugUtilsMessengerEXT
);
destroyable_ext!(
khr::DeferredHostOperations,
destroy_deferred_operation,
vk::DeferredOperationKHR
);
destroyable_ext!(khr::Surface, destroy_surface, vk::SurfaceKHR);
destroyable_ext!(khr::Swapchain, destroy_swapchain, vk::SwapchainKHR);
impl<Resource: Destroyable> Destroyable for Vec<Resource> {
type Destroyer = <Resource as Destroyable>::Destroyer;
unsafe fn destroy_with(
&mut self,
destroyer: &Self::Destroyer,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
for mut resource in self.drain(..) {
resource.destroy_with(destroyer, allocation_callbacks);
}
}
}
impl<Resource: Destroyable, const N: usize> Destroyable for [Resource; N] {
type Destroyer = <Resource as Destroyable>::Destroyer;
unsafe fn destroy_with(
&mut self,
destroyer: &Self::Destroyer,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
for resource in self {
resource.destroy_with(destroyer, allocation_callbacks);
}
}
}
impl<Resource: Destroyable> Destroyable for Option<Resource> {
type Destroyer = <Resource as Destroyable>::Destroyer;
unsafe fn destroy_with(
&mut self,
destroyer: &Self::Destroyer,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
if let Some(ref mut resource) = self {
resource.destroy_with(destroyer, allocation_callbacks);
}
}
}
impl<Resource: Destroyable, Error> Destroyable for Result<Resource, Error> {
type Destroyer = <Resource as Destroyable>::Destroyer;
unsafe fn destroy_with(
&mut self,
destroyer: &Self::Destroyer,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
if let Ok(ref mut resource) = self {
resource.destroy_with(destroyer, allocation_callbacks);
}
}
}