From dd02ea23cfd001470e9ac6d016f3d632bbdb15aa Mon Sep 17 00:00:00 2001 From: janis Date: Sat, 24 Oct 2026 18:11:14 +0200 Subject: [PATCH] simplify device ownership logic --- crates/renderer/src/commands.rs | 4 +- crates/renderer/src/lib.rs | 2 +- crates/renderer/src/pipeline.rs | 4 +- crates/renderer/src/rendering/mod.rs | 2 +- crates/renderer/src/swapchain.rs | 2 +- crates/renderer_device/src/device.rs | 473 +++++++------------ crates/renderer_device/src/lib.rs | 2 +- crates/renderer_device/src/pipeline_cache.rs | 16 +- crates/renderer_device/src/sync.rs | 68 ++- 9 files changed, 225 insertions(+), 348 deletions(-) diff --git a/crates/renderer/src/commands.rs b/crates/renderer/src/commands.rs index 909e538..3fe0a81 100644 --- a/crates/renderer/src/commands.rs +++ b/crates/renderer/src/commands.rs @@ -223,7 +223,7 @@ impl SingleUseCommand { pub fn end(&self) -> VkResult<()> { assert_eq!(self.state(), CommandBufferState::Recording); unsafe { - self.inner.dev().dev().end_command_buffer(self.handle())?; + self.device().dev().end_command_buffer(self.handle())?; } self.state.set_executable(); Ok(()) @@ -288,7 +288,7 @@ impl SingleUseCommand { wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>, signal: Option, ) -> crate::Result<()> { - let fence = Arc::new(sync::Fence::from_pool(&self.device().pools().fences, None)?); + let fence = Arc::new(sync::Fence::from_pool(self.device(), None)?); let future = self.submit_async(wait, signal, fence)?; future.block()?; Ok(()) diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index 399c481..e590fe2 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -460,7 +460,7 @@ impl Renderer2 { let future = cmds.submit( Some((frame.acquire, vk::PipelineStageFlags::TRANSFER)), Some(frame.release), - Arc::new(sync::Fence::from_pool(&self.device.pools().fences, None)?), + Arc::new(sync::Fence::from_pool(&self.device, None)?), )?; future.await; diff --git a/crates/renderer/src/pipeline.rs b/crates/renderer/src/pipeline.rs index ee29070..3f3293c 100644 --- a/crates/renderer/src/pipeline.rs +++ b/crates/renderer/src/pipeline.rs @@ -521,7 +521,7 @@ impl Pipeline { device .dev() .create_compute_pipelines( - device.pools().pipeline_cache.raw, + device.pools.pipeline_cache.raw, core::slice::from_ref(info), None, ) @@ -690,7 +690,7 @@ impl Pipeline { device .dev() .create_graphics_pipelines( - device.pools().pipeline_cache.raw, + device.pools.pipeline_cache.raw, core::slice::from_ref(&info), None, ) diff --git a/crates/renderer/src/rendering/mod.rs b/crates/renderer/src/rendering/mod.rs index 7c4d30d..d88d573 100644 --- a/crates/renderer/src/rendering/mod.rs +++ b/crates/renderer/src/rendering/mod.rs @@ -168,7 +168,7 @@ impl Wireframe { let future = cmd.submit_async( None, None, - Arc::new(sync::Fence::from_pool(&dev.pools().fences, None)?), + Arc::new(sync::Fence::from_pool(&dev, None)?), )?; let pipeline = Self::create_pipeline(dev.clone())?; diff --git a/crates/renderer/src/swapchain.rs b/crates/renderer/src/swapchain.rs index 52ec4f9..bd93529 100644 --- a/crates/renderer/src/swapchain.rs +++ b/crates/renderer/src/swapchain.rs @@ -542,7 +542,7 @@ impl Swapchain { tracing::trace!(frame, "acquiring image for frame {frame}"); async move { - let fence = Fence::from_pool(&self.swapchain.device().pools().fences, None)?; + let fence = Fence::from_pool(self.swapchain.device(), None)?; let acquire = self.acquire_semaphores[frame]; // spawn on threadpool because it might block. diff --git a/crates/renderer_device/src/device.rs b/crates/renderer_device/src/device.rs index f1677b3..f39bff3 100644 --- a/crates/renderer_device/src/device.rs +++ b/crates/renderer_device/src/device.rs @@ -3,13 +3,13 @@ use std::{ collections::{BTreeSet, HashMap, HashSet}, ffi::CStr, ops::{Deref, DerefMut}, - sync::Arc, + sync::{Arc, Weak}, }; use ash::{ ext, khr, prelude::VkResult, - vk::{self, Handle}, + vk, }; use parking_lot::Mutex; use raw_window_handle::RawDisplayHandle; @@ -93,12 +93,16 @@ bitflags::bitflags! { } } -struct DeviceDrop(ash::Device); +struct DeviceDrop { + device: ash::Device, + pipeline_cache: PipelineCache, +} impl Drop for DeviceDrop { fn drop(&mut self) { unsafe { - _ = self.0.device_wait_idle(); - self.0.destroy_device(None); + _ = self.device.device_wait_idle(); + self.pipeline_cache.destroy(&self.device); + self.device.destroy_device(None); } } } @@ -157,6 +161,7 @@ pub struct DeviceInner { pub queues: DeviceQueues, pub sync_threadpool: sync::SyncThreadpool, pub device_extensions: DeviceExtensions, + pub pools: DevicePools, #[allow(dead_code)] pub enabled_extensions: Vec<&'static CStr>, @@ -450,7 +455,8 @@ impl PhysicalDeviceInfo { }, })?; - let inner = DeviceInner { + let pipeline_cache = PipelineCache::new(&device, &self).unwrap(); + let shared = Arc::new_cyclic(|inner: &Weak| DeviceInner { raw: device.clone(), alloc2: Mutex::new(alloc2), instance: instance.clone(), @@ -459,14 +465,13 @@ impl PhysicalDeviceInfo { device_extensions, enabled_extensions, sync_threadpool: sync::SyncThreadpool::new(), - _drop: DeviceDrop(device), - }; - - let shared = Arc::new(inner); - Ok(Device { - pools: Arc::new(DevicePools::new(shared.clone())), - shared, - }) + pools: DevicePools::new(inner.clone(), pipeline_cache), + _drop: DeviceDrop { + device, + pipeline_cache, + }, + }); + Ok(Device(shared)) } fn required_extensions(&self, requested_extensions: &[Extension<'static>]) -> Vec<*const i8> { @@ -496,28 +501,19 @@ impl PhysicalDeviceInfo { #[derive(Debug)] pub struct DevicePools { - pub pipeline_cache: asdf::DeviceObject>, - pub fences: Arc>, + pub pipeline_cache: PipelineCache, + pub fences: Pool, pub binary_semaphores: Pool, pub timeline_semaphores: Pool, } -impl AsRef for DevicePools { - fn as_ref(&self) -> &DevicePools { - self - } -} - impl DevicePools { - pub fn new(device: Arc) -> Self { + fn new(device: Weak, pipeline_cache: PipelineCache) -> Self { Self { - fences: Arc::new(Pool::new(device.clone())), + fences: Pool::new(device.clone()), binary_semaphores: Pool::new(device.clone()), timeline_semaphores: Pool::new(device.clone()), - pipeline_cache: asdf::DeviceObject::new( - device.clone(), - PipelineCache::new(&device.raw, &device.adapter).unwrap(), - ), + pipeline_cache, } } } @@ -551,20 +547,11 @@ impl DeviceRef for &Arc { } #[derive(Clone, Debug)] -pub struct Device { - pub(crate) shared: Arc, - pools: Arc, -} - -impl Device { - pub fn pools(&self) -> &Arc { - &self.pools - } -} +pub struct Device(Arc); impl PartialEq for Device { fn eq(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.shared, &other.shared) + Arc::ptr_eq(&self.0, &other.0) } } @@ -574,7 +561,7 @@ impl core::ops::Deref for Device { type Target = DeviceInner; fn deref(&self) -> &Self::Target { - &self.shared + &self.0 } } @@ -716,75 +703,7 @@ impl DeviceInner { } } -#[derive(Clone)] -pub struct DeviceOwnedDebugObject { - pub device: Device, - pub object: T, - #[cfg(debug_assertions)] - name: Option>, -} - -impl Eq for DeviceOwnedDebugObject {} -impl PartialEq for DeviceOwnedDebugObject { - fn eq(&self, other: &Self) -> bool { - std::sync::Arc::ptr_eq(&self.device.shared, &other.device.shared) - && self.object == other.object - } -} - -impl std::fmt::Debug for DeviceOwnedDebugObject { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut fmt = f.debug_struct(core::any::type_name::()); - - fmt.field_with("device", |f| { - write!(f, "0x{:x}", self.device.raw.handle().as_raw()) - }) - .field_with("handle", |f| write!(f, "0x{:x}", &self.object.as_raw())); - - #[cfg(debug_assertions)] - { - fmt.field("name", &self.name); - } - - fmt.finish() - } -} - -impl DeviceOwnedDebugObject { - pub fn new( - device: crate::Device, - object: T, - name: Option>, - ) -> ash::prelude::VkResult - where - T: vk::Handle + Copy, - { - if let Some(name) = name.as_ref() { - unsafe { - device.debug_name_object(object, name); - } - } - - Ok(Self { - device, - object, - #[cfg(debug_assertions)] - name, - }) - } - - pub fn dev(&self) -> &crate::Device { - &self.device - } - pub fn handle(&self) -> T - where - T: Copy, - { - self.object - } -} - -pub use asdf::{DeviceObject, InnerDeviceObject}; +pub use asdf::DeviceObject; pub trait DeviceHandle { /// # Safety @@ -799,23 +718,19 @@ impl> ExternallyManagedObject for Mutex { } } -impl> ExternallyManagedObject for vk::Buffer { - unsafe fn destroy(self, device: &T) { - unsafe { - device.as_ref().raw.destroy_buffer(self, None); - } +impl ExternallyManagedObject for vk::Buffer { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_buffer(self, None) }; } } - -impl> ExternallyManagedObject for vk::Image { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_image(self, None) }; +impl ExternallyManagedObject for vk::Image { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_image(self, None) }; } } - -impl> ExternallyManagedObject for vk::ImageView { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_image_view(self, None) }; +impl ExternallyManagedObject for vk::ImageView { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_image_view(self, None) }; } } @@ -825,46 +740,46 @@ impl DeviceHandle for vk::DescriptorPool { } } -impl> ExternallyManagedObject for vk::DescriptorPool { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_descriptor_pool(self, None) }; +impl ExternallyManagedObject for vk::DescriptorPool { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_descriptor_pool(self, None) }; } } -impl> ExternallyManagedObject for vk::DescriptorSetLayout { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_descriptor_set_layout(self, None) }; +impl ExternallyManagedObject for vk::DescriptorSetLayout { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_descriptor_set_layout(self, None) }; } } -impl> ExternallyManagedObject for vk::PipelineLayout { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_pipeline_layout(self, None) }; +impl ExternallyManagedObject for vk::PipelineLayout { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_pipeline_layout(self, None) }; } } -impl> ExternallyManagedObject for vk::Sampler { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_sampler(self, None) }; +impl ExternallyManagedObject for vk::Sampler { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_sampler(self, None) }; } } -impl> ExternallyManagedObject for vk::ShaderModule { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_shader_module(self, None) }; +impl ExternallyManagedObject for vk::ShaderModule { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_shader_module(self, None) }; } } -impl> ExternallyManagedObject for vk::Pipeline { - unsafe fn destroy(self, device: &T) { - unsafe { device.as_ref().raw.destroy_pipeline(self, None) }; +impl ExternallyManagedObject for vk::Pipeline { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_pipeline(self, None) }; } } -impl> ExternallyManagedObject for vk::SwapchainKHR { - unsafe fn destroy(self, device: &T) { +impl ExternallyManagedObject for vk::SwapchainKHR { + unsafe fn destroy(self, device: &Device) { unsafe { - if let Some(swapchain) = device.as_ref().device_extensions.swapchain.as_ref() { + if let Some(swapchain) = device.device_extensions.swapchain.as_ref() { swapchain.destroy_swapchain(self, None) } } @@ -880,17 +795,22 @@ pub trait Pooled: Sized { fn create_from_pool(pool: &Pool) -> Result; } +/// A pooled handle which knows how to return itself to its pool. +pub trait Recycle: Sized { + fn recycle(self, device: &Device); +} + #[derive(Debug)] pub struct Pool { pub pool: Mutex>, - pub device: Arc, + device: Weak, } impl Pool { pub fn push(&self, item: T) { self.pool.lock().push(item); } - pub fn new(device: Arc) -> Self { + pub fn new(device: Weak) -> Self { Self { pool: Mutex::new(Vec::new()), device, @@ -899,6 +819,10 @@ impl Pool { pub fn pop(&self) -> Option { self.pool.lock().pop() } + + pub fn device(&self) -> Arc { + self.device.upgrade().expect("pool outlived its device") + } } impl AsRef> for Pool { @@ -907,7 +831,43 @@ impl AsRef> for Pool { } } -pub type PoolObject>> = asdf::ExternallyManagedObject; +pub struct PoolObject { + inner: std::mem::ManuallyDrop, + device: Device, +} + +impl PoolObject { + pub fn new(inner: T, device: Device) -> Self { + Self { + inner: std::mem::ManuallyDrop::new(inner), + device, + } + } + + pub fn device(&self) -> &Device { + &self.device + } +} + +impl Deref for PoolObject { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for PoolObject { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl Drop for PoolObject { + fn drop(&mut self) { + let inner = unsafe { std::mem::ManuallyDrop::take(&mut self.inner) }; + inner.recycle(&self.device); + } +} impl Pool { pub fn get(&self) -> Result { @@ -929,7 +889,8 @@ impl Pool { #[cfg(debug_assertions)] { let name = name.map(Into::into).unwrap_or_default(); - ::debug_name(&obj, &self.device, &name); + let device = self.device(); + ::debug_name(&obj, &device, &name); } Ok(obj) @@ -946,7 +907,7 @@ macro_rules! define_device_owned_handle { } $(=> |$this:ident| $dtor:stmt)?) => { $(#[$attr])* $ty_vis struct $ty { - inner: $crate::device::DeviceOwnedDebugObject<$handle>, + inner: $crate::device::DeviceObject<$handle>, $( $(#[$field_attr])* $field_vis $field_name: $field_ty, @@ -955,10 +916,10 @@ macro_rules! define_device_owned_handle { impl $crate::device::DeviceOwned<$handle> for $ty { fn device(&self) -> &$crate::device::Device { - self.inner.dev() + self.inner.device() } fn handle(&self) -> $handle { - self.inner.handle() + *self.inner } } @@ -971,11 +932,11 @@ macro_rules! define_device_owned_handle { $($field_name: $field_ty,)* ) -> ::ash::prelude::VkResult { Ok(Self { - inner: $crate::device::DeviceOwnedDebugObject::new( + inner: $crate::device::DeviceObject::new_debug_named( device, handle, name, - )?, + ), $($field_name,)* }) } @@ -993,19 +954,17 @@ macro_rules! define_device_owned_handle { }; } -// This module is an experiment in a more generic way to manage device-owned resources. -// #[cfg(false)] pub mod asdf { use std::{ - mem::{ManuallyDrop, MaybeUninit}, + mem::ManuallyDrop, ops::{Deref, DerefMut}, - sync::Arc, }; use ash::vk; use ash::vk::Handle; use crate::device::{DebugName, DeviceInner}; + use crate::Device; pub mod traits { /// A trait describing an object owned by some manager-type, which is @@ -1050,45 +1009,6 @@ pub mod asdf { owner, } } - pub fn owner(&self) -> &O { - &self.owner - } - - pub fn map_inner(self, f: impl FnOnce(T) -> U) -> ExternallyManagedObject - where - U: traits::ExternallyManagedObject, - { - unsafe { - let mut this = MaybeUninit::new(self); - let inner = ManuallyDrop::take(&mut this.assume_init_mut().inner); - let owner = core::ptr::read(&raw const this.assume_init_mut().owner); - - let new_inner = f(inner); - - ExternallyManagedObject { - inner: ManuallyDrop::new(new_inner), - owner, - } - } - } - - pub fn map_owner(self, f: impl FnOnce(O) -> U) -> ExternallyManagedObject - where - T: traits::ExternallyManagedObject, - { - unsafe { - let mut this = MaybeUninit::new(self); - let inner = ManuallyDrop::take(&mut this.assume_init_mut().inner); - - // get the old owner without calling `Self::drop` - let owner = core::ptr::read(&raw const this.assume_init_mut().owner); - - ExternallyManagedObject { - inner: ManuallyDrop::new(inner), - owner: f(owner), - } - } - } } impl Drop for ExternallyManagedObject @@ -1103,95 +1023,56 @@ pub mod asdf { } } - pub type InnerDeviceObject = DeviceObject>; - /// A wrapper for vulkan types which are owned by the device, taking care of destruction. - pub struct DeviceObject< - T: traits::ExternallyManagedObject, - O: AsRef = super::Device, - > { - inner: ExternallyManagedObject, + pub struct DeviceObject> { + inner: ExternallyManagedObject, #[allow(dead_code)] name: Option, } - impl< - T: traits::ExternallyManagedObject + traits::DebugNameable, - O: AsRef, - > DeviceObject - { - pub fn new_debug_named(owner: O, inner: T, name: Option>) -> Self { + impl + traits::DebugNameable> DeviceObject { + pub fn new_debug_named( + device: Device, + inner: T, + name: Option>, + ) -> Self { let name = name.map(Into::into); if let Some(ref name) = name { - traits::DebugNameable::debug_name(&inner, owner.as_ref(), name); + traits::DebugNameable::debug_name(&inner, &device, name); } - let obj = ExternallyManagedObject::new(inner, owner); + let obj = ExternallyManagedObject::new(inner, device); Self { inner: obj, name } } } - impl, O: AsRef> DeviceObject { - pub fn new(owner: O, inner: T) -> Self { - let inner = ExternallyManagedObject::new(inner, owner); + impl> DeviceObject { + pub fn new(device: Device, inner: T) -> Self { + let inner = ExternallyManagedObject::new(inner, device); Self { inner, name: None } } - pub fn new_debug_named_with( - owner: O, - inner: T, - name: Option>, - debug_namable: impl FnOnce(&T) -> D, - ) -> Self - where - D: traits::DebugNameable, - { - let name = name.map(Into::into); - if let Some(ref name) = name { - traits::DebugNameable::debug_name(&debug_namable(&inner), owner.as_ref(), name); - } - - let obj = ExternallyManagedObject::new(inner, owner); - - Self { inner: obj, name } + pub fn device(&self) -> &Device { + &self.inner.owner } - pub fn device(&self) -> &O { - self.inner.owner() + pub fn handle(&self) -> T + where + T: Copy, + { + *Deref::deref(self) } pub fn name(&self) -> Option<&str> { - self.name.as_ref().map(|n| &**n) - } - - pub fn map_inner(self, f: impl FnOnce(T) -> U) -> DeviceObject - where - U: traits::ExternallyManagedObject, - { - DeviceObject { - inner: self.inner.map_inner(f), - name: self.name, - } - } - - pub fn map_owner(self, f: impl FnOnce(O) -> U) -> DeviceObject - where - T: traits::ExternallyManagedObject, - U: AsRef, - { - DeviceObject { - inner: self.inner.map_owner(f), - name: self.name, - } + self.name.as_deref() } } - impl std::fmt::Debug for DeviceObject + impl std::fmt::Debug for DeviceObject where - T: std::fmt::Debug + traits::ExternallyManagedObject, - O: AsRef, + T: std::fmt::Debug + traits::ExternallyManagedObject, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut fmt = f.debug_struct(core::any::type_name::()); @@ -1200,8 +1081,7 @@ pub mod asdf { fmt.field_with("device", |f| { write!( f, - "0x{:x}", - self.inner.owner().as_ref().raw.handle().as_raw() + "0x{:x}", self.inner.owner.raw.handle().as_raw() ) }) .field_with("handle", |f| write!(f, "{inner:?}")) @@ -1211,10 +1091,9 @@ pub mod asdf { } } - impl Deref for DeviceObject + impl Deref for DeviceObject where - T: traits::ExternallyManagedObject, - O: AsRef, + T: traits::ExternallyManagedObject, { type Target = T; @@ -1223,10 +1102,9 @@ pub mod asdf { } } - impl DerefMut for DeviceObject + impl DerefMut for DeviceObject where - T: traits::ExternallyManagedObject, - O: AsRef, + T: traits::ExternallyManagedObject, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner @@ -1234,29 +1112,39 @@ pub mod asdf { } mod impls { - use crate::device::{DeviceInner, DevicePools, GpuAllocation}; + use crate::device::GpuAllocation; use super::*; - impl> traits::ExternallyManagedObject for vk::Semaphore { - unsafe fn destroy(self, device: &T) { - unsafe { - device.as_ref().raw.destroy_semaphore(self, None); - } + impl traits::ExternallyManagedObject for vk::Semaphore { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_semaphore(self, None) }; } } - impl> traits::ExternallyManagedObject for GpuAllocation { - unsafe fn destroy(self, device: &T) { - _ = device.as_ref().alloc2.lock().free(self); + impl traits::ExternallyManagedObject for GpuAllocation { + unsafe fn destroy(self, device: &Device) { + _ = device.alloc2.lock().free(self); } } - impl traits::ExternallyManagedObject for vk::Semaphore { - unsafe fn destroy(self, owner: &DevicePools) { - owner - .binary_semaphores - .push(crate::sync::BinarySemaphore(self)); + impl traits::ExternallyManagedObject for vk::CommandBuffer { + unsafe fn destroy(self, _: &Device) {} + } + + impl traits::ExternallyManagedObject for vk::CommandPool { + unsafe fn destroy(self, _: &Device) {} + } + + impl crate::device::DeviceOwned for DeviceObject + where + T: vk::Handle + Copy + traits::ExternallyManagedObject, + { + fn device(&self) -> &Device { + self.device() + } + fn handle(&self) -> T { + self.handle() } } @@ -1275,30 +1163,27 @@ pub mod asdf { #[allow(dead_code)] #[cfg(test)] fn asdf() { - use crate::device::{DevicePools, GpuAllocation}; + use crate::device::GpuAllocation; fn summon() -> T { unimplemented!() } - let _inner_ref: DeviceObject = DeviceObject::new_debug_named( - summon::<&DeviceInner>(), + let _inner_ref: DeviceObject = DeviceObject::new_debug_named( + summon::(), summon::(), Some("my semaphore"), ); - let _device_owned: DeviceObject = - DeviceObject::new_debug_named( - summon::(), - summon::(), - Some("my other semaphore"), - ); - - let _allocation: DeviceObject> = DeviceObject::new( - summon::>(), - summon::(), + let _device_owned: DeviceObject = DeviceObject::new_debug_named( + summon::(), + summon::(), + Some("my other semaphore"), ); - let _pool_owned: ExternallyManagedObject = - ExternallyManagedObject::new(summon::(), summon::()); + let _allocation: DeviceObject = + DeviceObject::new(summon::(), summon::()); + + let _pool_owned: DeviceObject = + DeviceObject::new(summon::(), summon::()); } } diff --git a/crates/renderer_device/src/lib.rs b/crates/renderer_device/src/lib.rs index 288dbe9..90e5161 100644 --- a/crates/renderer_device/src/lib.rs +++ b/crates/renderer_device/src/lib.rs @@ -38,7 +38,7 @@ mod device_ref_derive_tests { } #[derive(renderer_macros::DeviceRef)] - struct GenericWrapper { + struct GenericWrapper { #[device] device: D, tag: &'static str, diff --git a/crates/renderer_device/src/pipeline_cache.rs b/crates/renderer_device/src/pipeline_cache.rs index 3dc14d1..dc1c97f 100644 --- a/crates/renderer_device/src/pipeline_cache.rs +++ b/crates/renderer_device/src/pipeline_cache.rs @@ -1,23 +1,19 @@ -use std::sync::Arc; - use ash::vk; use ash::Device; use crate::PhysicalDeviceInfo; -use crate::device::DeviceInner; - -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct PipelineCache { #[allow(dead_code)] key: u128, pub raw: vk::PipelineCache, } -impl crate::device::asdf::traits::ExternallyManagedObject> for PipelineCache { - unsafe fn destroy(self, owner: &Arc) { +impl PipelineCache { + pub(crate) unsafe fn destroy(self, device: &ash::Device) { tracing::info!("destroying pipeline cache with key {:x}", self.key); - if let Ok(data) = self.export(&owner.raw) { + if let Ok(data) = self.export(device) { tracing::info!( "exported pipeline cache with key {:x} and size {} bytes", self.key, @@ -27,11 +23,9 @@ impl crate::device::asdf::traits::ExternallyManagedObject> for tracing::error!("failed to write pipeline cache to disk: {err}"); }); } - unsafe { owner.raw.destroy_pipeline_cache(self.raw, None) }; + unsafe { device.destroy_pipeline_cache(self.raw, None) }; } -} -impl PipelineCache { const MAGIC: [u8; 4] = *b"VYPC"; const KEY_VERSION: u32 = 1; const PATH: &'static str = "pipeline_cache.bin"; diff --git a/crates/renderer_device/src/sync.rs b/crates/renderer_device/src/sync.rs index 86f10f5..a38eaea 100644 --- a/crates/renderer_device/src/sync.rs +++ b/crates/renderer_device/src/sync.rs @@ -6,9 +6,9 @@ use std::{ }; use crate::device::{ - DevicePools, Pool, PoolObject, Pooled, + Pool, PoolObject, Pooled, Recycle, asdf::{ - DeviceObject, InnerDeviceObject, + DeviceObject, traits::ExternallyManagedObject as ExternallyManagedObjectTrait, }, }; @@ -160,17 +160,17 @@ impl SyncThreadpool { pub enum Fence { Dedicated { - fence: InnerDeviceObject, + fence: DeviceObject, }, Pooled { - fence: PoolObject>>, + fence: PoolObject, }, } impl Pooled for vk::Fence { fn create_from_pool(pool: &Pool) -> Result { let fence = unsafe { - pool.device + pool.device() .raw .create_fence(&vk::FenceCreateInfo::default(), None)? }; @@ -179,17 +179,15 @@ impl Pooled for vk::Fence { } } -impl ExternallyManagedObjectTrait>> for vk::Fence { - unsafe fn destroy(self, pool: &Arc>) { - pool.push(self); +impl Recycle for vk::Fence { + fn recycle(self, device: &Device) { + device.pools.fences.push(self); } } -impl> ExternallyManagedObjectTrait for vk::Fence { - unsafe fn destroy(self, device: &T) { - unsafe { - device.as_ref().raw.destroy_fence(self, None); - } +impl ExternallyManagedObjectTrait for vk::Fence { + unsafe fn destroy(self, device: &Device) { + unsafe { device.raw.destroy_fence(self, None) }; } } @@ -207,14 +205,14 @@ impl Fence { .create_fence(&vk::FenceCreateInfo::default(), None)? }; Ok(Self::Dedicated { - fence: DeviceObject::new_debug_named(device.shared.clone(), fence, name), + fence: DeviceObject::new_debug_named(device, fence, name), }) } - pub fn from_pool(pool: &Arc>, name: Option<&'static str>) -> Result { - let fence = pool.get_debug_named(name)?; + pub fn from_pool(device: &Device, name: Option<&'static str>) -> Result { + let fence = device.pools.fences.get_debug_named(name)?; Ok(Self::Pooled { - fence: PoolObject::new(fence, pool.clone()), + fence: PoolObject::new(fence, device.clone()), }) } @@ -225,10 +223,10 @@ impl Fence { } } - fn device(&self) -> &Arc { + fn device(&self) -> &Device { match self { - Fence::Dedicated { fence } => &fence.device(), - Fence::Pooled { fence } => &fence.owner().device, + Fence::Dedicated { fence } => fence.device(), + Fence::Pooled { fence } => fence.device(), } } @@ -278,21 +276,21 @@ pub enum SemaphoreInner { Timeline(vk::Semaphore), } -impl ExternallyManagedObjectTrait> for SemaphoreInner { - unsafe fn destroy(self, owner: &Arc) { +impl Recycle for SemaphoreInner { + fn recycle(self, owner: &Device) { match self { SemaphoreInner::Binary(semaphore) => { - owner.binary_semaphores.push(BinarySemaphore(semaphore)) + owner.pools.binary_semaphores.push(BinarySemaphore(semaphore)) } SemaphoreInner::Timeline(semaphore) => { - owner.timeline_semaphores.push(TimelineSemaphore(semaphore)) + owner.pools.timeline_semaphores.push(TimelineSemaphore(semaphore)) } } } } -impl ExternallyManagedObjectTrait> for SemaphoreInner { - unsafe fn destroy(self, owner: &Arc) { +impl ExternallyManagedObjectTrait for SemaphoreInner { + unsafe fn destroy(self, owner: &Device) { match self { SemaphoreInner::Binary(semaphore) | SemaphoreInner::Timeline(semaphore) => { unsafe { owner.raw.destroy_semaphore(semaphore, None) }; @@ -336,11 +334,11 @@ impl From for SemaphoreInner { pub enum Semaphore { Dedicated { - semaphore: InnerDeviceObject, + semaphore: DeviceObject, }, Pooled { #[allow(private_interfaces)] - semaphore: PoolObject>, + semaphore: PoolObject, }, } @@ -379,7 +377,7 @@ impl Pooled for BinarySemaphore { let mut type_info = vk::SemaphoreTypeCreateInfo::default().semaphore_type(vk::SemaphoreType::BINARY); let create_info = vk::SemaphoreCreateInfo::default().push_next(&mut type_info); - let inner = unsafe { pool.device.raw.create_semaphore(&create_info, None)? }; + let inner = unsafe { pool.device().raw.create_semaphore(&create_info, None)? }; Ok(Self(inner)) } } @@ -390,7 +388,7 @@ impl Pooled for TimelineSemaphore { .semaphore_type(vk::SemaphoreType::TIMELINE) .initial_value(0); let create_info = vk::SemaphoreCreateInfo::default().push_next(&mut type_info); - let inner = unsafe { pool.device.raw.create_semaphore(&create_info, None)? }; + let inner = unsafe { pool.device().raw.create_semaphore(&create_info, None)? }; Ok(Self(inner)) } } @@ -421,7 +419,7 @@ impl Semaphore { }; Ok(Self::Dedicated { - semaphore: DeviceObject::new_debug_named(device.shared.clone(), inner, name), + semaphore: DeviceObject::new_debug_named(device, inner, name), }) } @@ -433,12 +431,12 @@ impl Semaphore { let semaphore = match semaphore_type { SemaphoreType::Binary => { let semaphore: SemaphoreInner = - device.pools().binary_semaphores.get_debug_named(name)?.into(); - PoolObject::new(semaphore, device.pools().clone()) + device.pools.binary_semaphores.get_debug_named(name)?.into(); + PoolObject::new(semaphore, device) } SemaphoreType::Timeline(value) => { let semaphore: SemaphoreInner = device - .pools() + .pools .timeline_semaphores .get_debug_named(name)? .into(); @@ -450,7 +448,7 @@ impl Semaphore { device.raw.signal_semaphore(&info)?; } - PoolObject::new(semaphore, device.pools().clone()) + PoolObject::new(semaphore, device) } };