Skip to content

Commit

Permalink
Change the DropGuard public API to a callback-based one. (#6164)
Browse files Browse the repository at this point in the history
This patch also unifies the behavior of the the `DropGuard`-ish
constructs in the Vulkan-based implementation.
  • Loading branch information
jerzywilczek authored Aug 27, 2024
1 parent fccd298 commit a9047c2
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 23 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ By @teoxoy [#6134](https://github.com/gfx-rs/wgpu/pull/6134).
- Reduce the amount of debug and trace logs emitted by wgpu-core and wgpu-hal. By @nical in [#6065](https://github.com/gfx-rs/wgpu/issues/6065)
- `Rg11b10Float` is renamed to `Rg11b10UFloat`. By @sagudev in [#6108](https://github.com/gfx-rs/wgpu/pull/6108)

#### HAL

- Change the inconsistent `DropGuard` based API on Vulkan and GLES to a consistent, callback-based one. By @jerzywilczek in [#6164](https://github.com/gfx-rs/wgpu/pull/6164)

### Dependency Updates

#### GLES
Expand Down
18 changes: 8 additions & 10 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,22 +110,21 @@ impl super::Device {
///
/// - `name` must be created respecting `desc`
/// - `name` must be a texture
/// - If `drop_guard` is [`None`], wgpu-hal will take ownership of the texture. If `drop_guard` is
/// [`Some`], the texture must be valid until the drop implementation
/// of the drop guard is called.
/// - If `drop_callback` is [`None`], wgpu-hal will take ownership of the texture. If
/// `drop_callback` is [`Some`], the texture must be valid until the callback is called.
#[cfg(any(native, Emscripten))]
pub unsafe fn texture_from_raw(
&self,
name: std::num::NonZeroU32,
desc: &crate::TextureDescriptor,
drop_guard: Option<crate::DropGuard>,
drop_callback: Option<crate::DropCallback>,
) -> super::Texture {
super::Texture {
inner: super::TextureInner::Texture {
raw: glow::NativeTexture(name),
target: super::Texture::get_info_from_desc(desc),
},
drop_guard,
drop_guard: crate::DropGuard::from_option(drop_callback),
mip_level_count: desc.mip_level_count,
array_layer_count: desc.array_layer_count(),
format: desc.format,
Expand All @@ -138,21 +137,20 @@ impl super::Device {
///
/// - `name` must be created respecting `desc`
/// - `name` must be a renderbuffer
/// - If `drop_guard` is [`None`], wgpu-hal will take ownership of the renderbuffer. If `drop_guard` is
/// [`Some`], the renderbuffer must be valid until the drop implementation
/// of the drop guard is called.
/// - If `drop_callback` is [`None`], wgpu-hal will take ownership of the renderbuffer. If
/// `drop_callback` is [`Some`], the renderbuffer must be valid until the callback is called.
#[cfg(any(native, Emscripten))]
pub unsafe fn texture_from_raw_renderbuffer(
&self,
name: std::num::NonZeroU32,
desc: &crate::TextureDescriptor,
drop_guard: Option<crate::DropGuard>,
drop_callback: Option<crate::DropCallback>,
) -> super::Texture {
super::Texture {
inner: super::TextureInner::Renderbuffer {
raw: glow::NativeRenderbuffer(name),
},
drop_guard,
drop_guard: crate::DropGuard::from_option(drop_callback),
mip_level_count: desc.mip_level_count,
array_layer_count: desc.array_layer_count(),
format: desc.format,
Expand Down
31 changes: 29 additions & 2 deletions wgpu-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,35 @@ pub type MemoryRange = Range<wgt::BufferAddress>;
pub type FenceValue = u64;
pub type AtomicFenceValue = std::sync::atomic::AtomicU64;

/// Drop guard to signal wgpu-hal is no longer using an externally created object.
pub type DropGuard = Box<dyn std::any::Any + Send + Sync>;
/// A callback to signal that wgpu is no longer using a resource.
#[cfg(any(gles, vulkan))]
pub type DropCallback = Box<dyn FnMut() + Send + Sync + 'static>;

#[cfg(any(gles, vulkan))]
pub struct DropGuard {
callback: DropCallback,
}

#[cfg(all(any(gles, vulkan), any(native, Emscripten)))]
impl DropGuard {
fn from_option(callback: Option<DropCallback>) -> Option<Self> {
callback.map(|callback| Self { callback })
}
}

#[cfg(any(gles, vulkan))]
impl Drop for DropGuard {
fn drop(&mut self) {
(self.callback)();
}
}

#[cfg(any(gles, vulkan))]
impl std::fmt::Debug for DropGuard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DropGuard").finish()
}
}

#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum DeviceError {
Expand Down
10 changes: 7 additions & 3 deletions wgpu-hal/src/vulkan/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1603,11 +1603,13 @@ impl super::Adapter {
/// - `raw_device` must be created from this adapter.
/// - `raw_device` must be created using `family_index`, `enabled_extensions` and `physical_device_features()`
/// - `enabled_extensions` must be a superset of `required_device_extensions()`.
/// - If `drop_callback` is [`None`], wgpu-hal will take ownership of `raw_device`. If
/// `drop_callback` is [`Some`], `raw_device` must be valid until the callback is called.
#[allow(clippy::too_many_arguments)]
pub unsafe fn device_from_raw(
&self,
raw_device: ash::Device,
handle_is_owned: bool,
drop_callback: Option<crate::DropCallback>,
enabled_extensions: &[&'static CStr],
features: wgt::Features,
memory_hints: &wgt::MemoryHints,
Expand Down Expand Up @@ -1822,12 +1824,14 @@ impl super::Adapter {
0, 0, 0, 0,
];

let drop_guard = crate::DropGuard::from_option(drop_callback);

let shared = Arc::new(super::DeviceShared {
raw: raw_device,
family_index,
queue_index,
raw_queue,
handle_is_owned,
drop_guard,
instance: Arc::clone(&self.instance),
physical_device: self.raw,
enabled_extensions: enabled_extensions.into(),
Expand Down Expand Up @@ -2015,7 +2019,7 @@ impl crate::Adapter for super::Adapter {
unsafe {
self.device_from_raw(
raw_device,
true,
None,
&enabled_extensions,
features,
memory_hints,
Expand Down
10 changes: 6 additions & 4 deletions wgpu-hal/src/vulkan/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ impl super::DeviceShared {
for &raw in self.framebuffers.lock().values() {
unsafe { self.raw.destroy_framebuffer(raw, None) };
}
if self.handle_is_owned {
if self.drop_guard.is_none() {
unsafe { self.raw.destroy_device(None) };
}
}
Expand Down Expand Up @@ -649,13 +649,13 @@ impl super::Device {
/// # Safety
///
/// - `vk_image` must be created respecting `desc`
/// - If `drop_guard` is `Some`, the application must manually destroy the image handle. This
/// can be done inside the `Drop` impl of `drop_guard`.
/// - If `drop_callback` is [`None`], wgpu-hal will take ownership of `vk_image`. If
/// `drop_callback` is [`Some`], `vk_image` must be valid until the callback is called.
/// - If the `ImageCreateFlags` does not contain `MUTABLE_FORMAT`, the `view_formats` of `desc` must be empty.
pub unsafe fn texture_from_raw(
vk_image: vk::Image,
desc: &crate::TextureDescriptor,
drop_guard: Option<crate::DropGuard>,
drop_callback: Option<crate::DropCallback>,
) -> super::Texture {
let mut raw_flags = vk::ImageCreateFlags::empty();
let mut view_formats = vec![];
Expand All @@ -674,6 +674,8 @@ impl super::Device {
raw_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT;
}

let drop_guard = crate::DropGuard::from_option(drop_callback);

super::Texture {
raw: vk_image,
drop_guard,
Expand Down
10 changes: 7 additions & 3 deletions wgpu-hal/src/vulkan/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ impl super::Instance {
/// - `extensions` must be a superset of `desired_extensions()` and must be created from the
/// same entry, `instance_api_version`` and flags.
/// - `android_sdk_version` is ignored and can be `0` for all platforms besides Android
/// - If `drop_callback` is [`None`], wgpu-hal will take ownership of `raw_instance`. If
/// `drop_callback` is [`Some`], `raw_instance` must be valid until the callback is called.
///
/// If `debug_utils_user_data` is `Some`, then the validation layer is
/// available, so create a [`vk::DebugUtilsMessengerEXT`].
Expand All @@ -323,7 +325,7 @@ impl super::Instance {
extensions: Vec<&'static CStr>,
flags: wgt::InstanceFlags,
has_nv_optimus: bool,
drop_guard: Option<crate::DropGuard>,
drop_callback: Option<crate::DropCallback>,
) -> Result<Self, crate::InstanceError> {
log::debug!("Instance version: 0x{:x}", instance_api_version);

Expand Down Expand Up @@ -364,6 +366,8 @@ impl super::Instance {
None
};

let drop_guard = crate::DropGuard::from_option(drop_callback);

Ok(Self {
shared: Arc::new(super::InstanceShared {
raw: raw_instance,
Expand Down Expand Up @@ -555,7 +559,7 @@ impl Drop for super::InstanceShared {
.destroy_debug_utils_messenger(du.messenger, None);
du
});
if let Some(_drop_guard) = self.drop_guard.take() {
if self.drop_guard.is_none() {
self.raw.destroy_instance(None);
}
}
Expand Down Expand Up @@ -829,7 +833,7 @@ impl crate::Instance for super::Instance {
extensions,
desc.flags,
has_nv_optimus,
Some(Box::new(())), // `Some` signals that wgpu-hal is in charge of destroying vk_instance
None,
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/vulkan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ struct DeviceShared {
family_index: u32,
queue_index: u32,
raw_queue: vk::Queue,
handle_is_owned: bool,
drop_guard: Option<crate::DropGuard>,
instance: Arc<InstanceShared>,
physical_device: vk::PhysicalDevice,
enabled_extensions: Vec<&'static CStr>,
Expand Down

0 comments on commit a9047c2

Please sign in to comment.