Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wgpu-core] simplify callbacks #6624

Merged
merged 8 commits into from
Nov 26, 2024
68 changes: 3 additions & 65 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::{

use arrayvec::ArrayVec;
use smallvec::SmallVec;
use std::os::raw::c_char;
use thiserror::Error;
use wgt::{BufferAddress, DeviceLostReason, TextureFormat};

Expand Down Expand Up @@ -183,83 +182,22 @@ impl UserClosures {
closure();
}
for invocation in self.device_lost_invocations {
invocation
.closure
.call(invocation.reason, invocation.message);
(invocation.closure)(invocation.reason, invocation.message);
}
}
}

#[cfg(send_sync)]
pub type DeviceLostCallback = Box<dyn FnOnce(DeviceLostReason, String) + Send + 'static>;
pub type DeviceLostClosure = Box<dyn FnOnce(DeviceLostReason, String) + Send + 'static>;
#[cfg(not(send_sync))]
pub type DeviceLostCallback = Box<dyn FnOnce(DeviceLostReason, String) + 'static>;

pub struct DeviceLostClosureRust {
pub callback: DeviceLostCallback,
}

#[repr(C)]
pub struct DeviceLostClosureC {
pub callback: unsafe extern "C" fn(user_data: *mut u8, reason: u8, message: *const c_char),
pub user_data: *mut u8,
}

#[cfg(send_sync)]
unsafe impl Send for DeviceLostClosureC {}

pub struct DeviceLostClosure {
// We wrap this so creating the enum in the C variant can be unsafe,
// allowing our call function to be safe.
inner: DeviceLostClosureInner,
}
pub type DeviceLostClosure = Box<dyn FnOnce(DeviceLostReason, String) + 'static>;

pub struct DeviceLostInvocation {
closure: DeviceLostClosure,
reason: DeviceLostReason,
message: String,
}

enum DeviceLostClosureInner {
Rust { inner: DeviceLostClosureRust },
C { inner: DeviceLostClosureC },
}

impl DeviceLostClosure {
pub fn from_rust(callback: DeviceLostCallback) -> Self {
let inner = DeviceLostClosureRust { callback };
Self {
inner: DeviceLostClosureInner::Rust { inner },
}
}

/// # Safety
///
/// - The callback pointer must be valid to call with the provided `user_data`
/// pointer.
///
/// - Both pointers must point to `'static` data, as the callback may happen at
/// an unspecified time.
pub unsafe fn from_c(inner: DeviceLostClosureC) -> Self {
Self {
inner: DeviceLostClosureInner::C { inner },
}
}

pub(crate) fn call(self, reason: DeviceLostReason, message: String) {
match self.inner {
DeviceLostClosureInner::Rust { inner } => (inner.callback)(reason, message),
// SAFETY: the contract of the call to from_c says that this unsafe is sound.
DeviceLostClosureInner::C { inner } => unsafe {
// Ensure message is structured as a null-terminated C string. It only
// needs to live as long as the callback invocation.
let message = std::ffi::CString::new(message).unwrap();
(inner.callback)(inner.user_data, reason as u8, message.as_ptr())
},
}
}
}

pub(crate) fn map_buffer(
buffer: &Buffer,
offset: BufferAddress,
Expand Down
2 changes: 1 addition & 1 deletion wgpu-core/src/device/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3600,7 +3600,7 @@ impl Device {

// 1) Resolve the GPUDevice device.lost promise.
if let Some(device_lost_closure) = self.device_lost_closure.lock().take() {
device_lost_closure.call(DeviceLostReason::Unknown, message.to_string());
device_lost_closure(DeviceLostReason::Unknown, message.to_string());
}

// 2) Complete any outstanding mapAsync() steps.
Expand Down
5 changes: 2 additions & 3 deletions wgpu/src/backend/wgpu_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::{
sync::Arc,
};
use wgc::error::ContextErrorSource;
use wgc::{command::bundle_ffi::*, device::DeviceLostClosure, pipeline::CreateShaderModuleError};
use wgc::{command::bundle_ffi::*, pipeline::CreateShaderModuleError};
use wgt::WasmNotSendSync;

pub struct ContextWgpuCore(wgc::global::Global);
Expand Down Expand Up @@ -1352,9 +1352,8 @@ impl crate::Context for ContextWgpuCore {
device_data: &Self::DeviceData,
device_lost_callback: crate::context::DeviceLostCallback,
) {
let device_lost_closure = DeviceLostClosure::from_rust(device_lost_callback);
self.0
.device_set_device_lost_closure(device_data.id, device_lost_closure);
.device_set_device_lost_closure(device_data.id, device_lost_callback);
teoxoy marked this conversation as resolved.
Show resolved Hide resolved
}
fn device_destroy(&self, device_data: &Self::DeviceData) {
self.0.device_destroy(device_data.id);
Expand Down