device handle experiment

This commit is contained in:
janis 2026-04-04 16:24:42 +02:00
parent cf7f5152bc
commit 7503a73a57

View file

@ -952,3 +952,178 @@ macro_rules! define_device_owned_handle {
)? )?
}; };
} }
// This module is an experiment in a more generic way to manage device-owned resources.
#[cfg(false)]
mod asdf {
use std::{
ops::{Deref, DerefMut},
sync::Arc,
};
use ash::vk;
use crate::{
device::{DeviceInner, GpuAllocation},
util::DebugName,
};
mod traits {
pub trait ExternallyManagedObject<T> {
/// # Safety
/// The caller must ensure this function is only called once for a given object.
unsafe fn destroy(&mut self, owner: &T);
}
pub trait DebugNameable {
fn debug_name(&self, device: &super::DeviceInner, name: &str);
}
}
struct ExternallyManagedObject<T: traits::ExternallyManagedObject<O>, O> {
inner: T,
owner: O,
}
impl<T: traits::ExternallyManagedObject<O>, O> Deref for ExternallyManagedObject<T, O> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: traits::ExternallyManagedObject<O>, O> DerefMut for ExternallyManagedObject<T, O> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<T: traits::ExternallyManagedObject<O>, O> ExternallyManagedObject<T, O> {
fn new(inner: T, owner: O) -> Self {
Self { inner, owner }
}
fn owner(&self) -> &O {
&self.owner
}
}
impl<T, O> Drop for ExternallyManagedObject<T, O>
where
T: traits::ExternallyManagedObject<O>,
{
fn drop(&mut self) {
unsafe {
self.inner.destroy(&self.owner);
}
}
}
struct DeviceObject<T: traits::ExternallyManagedObject<O>, O: AsRef<super::DeviceInner>> {
inner: ExternallyManagedObject<T, O>,
name: Option<DebugName>,
}
impl<
T: traits::ExternallyManagedObject<O> + traits::DebugNameable,
O: AsRef<super::DeviceInner>,
> DeviceObject<T, O>
{
fn new_debug_named(owner: O, inner: T, name: Option<impl Into<DebugName>>) -> Self {
let name = name.map(Into::into);
if let Some(ref name) = name {
traits::DebugNameable::debug_name(&inner, owner.as_ref(), name);
}
let obj = ExternallyManagedObject::new(inner, owner);
Self { inner: obj, name }
}
}
impl<T: traits::ExternallyManagedObject<O>, O: AsRef<super::DeviceInner>> DeviceObject<T, O> {
fn new(owner: O, inner: T) -> Self {
let inner = ExternallyManagedObject::new(inner, owner);
Self { inner, name: None }
}
fn device(&self) -> &O {
self.inner.owner()
}
}
impl<T, O> Deref for DeviceObject<T, O>
where
T: traits::ExternallyManagedObject<O>,
O: AsRef<super::DeviceInner>,
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
mod impls {
use crate::device::{DeviceInner, GpuAllocation};
use super::*;
impl<T: AsRef<DeviceInner>> traits::ExternallyManagedObject<T> for ash::vk::Semaphore {
unsafe fn destroy(&mut self, device: &T) {
unsafe {
device.as_ref().raw.destroy_semaphore(*self, None);
}
}
}
impl<T: AsRef<DeviceInner>> traits::ExternallyManagedObject<T> for GpuAllocation {
unsafe fn destroy(&mut self, device: &T) {
let mut swapped = GpuAllocation::default();
std::mem::swap(self, &mut swapped);
_ = device.as_ref().alloc2.lock().free(swapped);
}
}
impl AsRef<DeviceInner> for DeviceInner {
fn as_ref(&self) -> &DeviceInner {
self
}
}
impl<T> traits::DebugNameable for T
where
T: vk::Handle + Copy,
{
fn debug_name(&self, device: &super::DeviceInner, name: &str) {
unsafe {
device.debug_name_object(*self, name);
}
}
}
}
fn summon<T>() -> T {
unimplemented!()
}
fn asdf() {
let inner_ref: DeviceObject<vk::Semaphore, &DeviceInner> = DeviceObject::new_debug_named(
summon::<&DeviceInner>(),
summon::<vk::Semaphore>(),
Some("my semaphore"),
);
let device_owned: DeviceObject<vk::Semaphore, super::Device> =
DeviceObject::new_debug_named(
summon::<super::Device>(),
summon::<vk::Semaphore>(),
Some("my other semaphore"),
);
let allocation: DeviceObject<GpuAllocation, Arc<super::DeviceInner>> = DeviceObject::new(
summon::<Arc<super::DeviceInner>>(),
summon::<GpuAllocation>(),
);
}
}