mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
webgpu: Implement device lost (#32354)
* device lost promise should be init at creation of device object * device lost impl * lock for device poll workaround for wgpu deadlocks * expect * Less lost reason reasoning in script
This commit is contained in:
parent
3381f2a704
commit
cbc9304c20
9 changed files with 224 additions and 5628 deletions
|
@ -169,7 +169,7 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'GPUDevice': {
|
||||
'inRealms': ['PopErrorScope', 'GetLost', 'CreateComputePipelineAsync', 'CreateRenderPipelineAsync'],
|
||||
'inRealms': ['PopErrorScope', 'CreateComputePipelineAsync', 'CreateRenderPipelineAsync'],
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,8 +56,9 @@ use script_traits::{
|
|||
};
|
||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||
use uuid::Uuid;
|
||||
use webgpu::WebGPUDevice;
|
||||
use webgpu::{DeviceLostReason, WebGPUDevice};
|
||||
|
||||
use super::bindings::codegen::Bindings::WebGPUBinding::GPUDeviceLostReason;
|
||||
use super::bindings::trace::HashMapTracedValues;
|
||||
use crate::dom::bindings::cell::{DomRefCell, RefMut};
|
||||
use crate::dom::bindings::codegen::Bindings::BroadcastChannelBinding::BroadcastChannelMethods;
|
||||
|
@ -3093,16 +3094,25 @@ impl GlobalScope {
|
|||
.insert(device.id(), Dom::from_ref(device));
|
||||
}
|
||||
|
||||
pub fn remove_gpu_device(&self, device: WebGPUDevice) {
|
||||
let _ = self.gpu_devices.borrow_mut().remove(&device);
|
||||
pub fn gpu_device_lost(&self, device: WebGPUDevice, reason: DeviceLostReason, msg: String) {
|
||||
let reason = match reason {
|
||||
DeviceLostReason::Unknown => GPUDeviceLostReason::Unknown,
|
||||
DeviceLostReason::Destroyed => GPUDeviceLostReason::Destroyed,
|
||||
};
|
||||
let _ac = enter_realm(&*self);
|
||||
self.gpu_devices
|
||||
.borrow_mut()
|
||||
.remove(&device)
|
||||
.expect("GPUDevice should still exists")
|
||||
.lose(reason, msg);
|
||||
}
|
||||
|
||||
pub fn handle_uncaptured_gpu_error(&self, device: WebGPUDevice, error: webgpu::Error) {
|
||||
self.gpu_devices
|
||||
.borrow()
|
||||
.get(&device)
|
||||
.expect("GPUDevice not found")
|
||||
.fire_uncaptured_error(error);
|
||||
if let Some(gpu_device) = self.gpu_devices.borrow().get(&device) {
|
||||
gpu_device.fire_uncaptured_error(error);
|
||||
} else {
|
||||
warn!("Recived error for lost GPUDevice!")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_gamepad_event(&self, gamepad_event: GamepadEvent) {
|
||||
|
|
|
@ -84,8 +84,9 @@ pub struct GPUDevice {
|
|||
#[no_trace]
|
||||
device: webgpu::WebGPUDevice,
|
||||
default_queue: Dom<GPUQueue>,
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-lost>
|
||||
#[ignore_malloc_size_of = "promises are hard"]
|
||||
lost_promise: DomRefCell<Option<Rc<Promise>>>,
|
||||
lost_promise: DomRefCell<Rc<Promise>>,
|
||||
valid: Cell<bool>,
|
||||
}
|
||||
|
||||
|
@ -100,6 +101,7 @@ impl GPUDevice {
|
|||
device: webgpu::WebGPUDevice,
|
||||
queue: &GPUQueue,
|
||||
label: String,
|
||||
lost_promise: Rc<Promise>,
|
||||
) -> Self {
|
||||
Self {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
|
@ -111,7 +113,7 @@ impl GPUDevice {
|
|||
label: DomRefCell::new(USVString::from(label)),
|
||||
device,
|
||||
default_queue: Dom::from_ref(queue),
|
||||
lost_promise: DomRefCell::new(None),
|
||||
lost_promise: DomRefCell::new(lost_promise),
|
||||
valid: Cell::new(true),
|
||||
}
|
||||
}
|
||||
|
@ -131,9 +133,18 @@ impl GPUDevice {
|
|||
let queue = GPUQueue::new(global, channel.clone(), queue);
|
||||
let limits = GPUSupportedLimits::new(global, limits);
|
||||
let features = GPUSupportedFeatures::Constructor(global, None, features).unwrap();
|
||||
let lost_promise = Promise::new(global);
|
||||
let device = reflect_dom_object(
|
||||
Box::new(GPUDevice::new_inherited(
|
||||
channel, adapter, extensions, &features, &limits, device, &queue, label,
|
||||
channel,
|
||||
adapter,
|
||||
extensions,
|
||||
&features,
|
||||
&limits,
|
||||
device,
|
||||
&queue,
|
||||
label,
|
||||
lost_promise,
|
||||
)),
|
||||
global,
|
||||
);
|
||||
|
@ -206,18 +217,11 @@ impl GPUDevice {
|
|||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#lose-the-device>
|
||||
pub fn lose(&self, reason: GPUDeviceLostReason) {
|
||||
if let Some(ref lost_promise) = *self.lost_promise.borrow() {
|
||||
let global = &self.global();
|
||||
let msg = match reason {
|
||||
GPUDeviceLostReason::Unknown => "Unknown reason for your device loss.",
|
||||
GPUDeviceLostReason::Destroyed => {
|
||||
"Device self-destruction sequence activated successfully!"
|
||||
},
|
||||
};
|
||||
let lost = GPUDeviceLostInfo::new(global, msg.into(), reason);
|
||||
lost_promise.resolve_native(&*lost);
|
||||
}
|
||||
pub fn lose(&self, reason: GPUDeviceLostReason, msg: String) {
|
||||
let ref lost_promise = *self.lost_promise.borrow();
|
||||
let global = &self.global();
|
||||
let lost = GPUDeviceLostInfo::new(global, msg.into(), reason);
|
||||
lost_promise.resolve_native(&*lost);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,10 +252,8 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-lost>
|
||||
fn GetLost(&self, comp: InRealm) -> Fallible<Rc<Promise>> {
|
||||
let promise = Promise::new_in_current_realm(comp);
|
||||
*self.lost_promise.borrow_mut() = Some(promise.clone());
|
||||
Ok(promise)
|
||||
fn Lost(&self) -> Rc<Promise> {
|
||||
self.lost_promise.borrow().clone()
|
||||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer>
|
||||
|
@ -1000,8 +1002,6 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
if self.valid.get() {
|
||||
self.valid.set(false);
|
||||
|
||||
self.lose(GPUDeviceLostReason::Destroyed);
|
||||
|
||||
if let Err(e) = self
|
||||
.channel
|
||||
.0
|
||||
|
|
|
@ -1075,14 +1075,13 @@ enum GPUDeviceLostReason {
|
|||
"destroyed",
|
||||
};
|
||||
|
||||
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
|
||||
[Exposed=(Window, Worker), Pref="dom.webgpu.enabled"]
|
||||
interface GPUDeviceLostInfo {
|
||||
readonly attribute GPUDeviceLostReason reason;
|
||||
readonly attribute DOMString message;
|
||||
};
|
||||
|
||||
partial interface GPUDevice {
|
||||
[Throws]
|
||||
readonly attribute Promise<GPUDeviceLostInfo> lost;
|
||||
};
|
||||
|
||||
|
|
|
@ -2424,12 +2424,14 @@ impl ScriptThread {
|
|||
WebGPUMsg::FreeTexture(id) => self.gpu_id_hub.lock().kill_texture_id(id),
|
||||
WebGPUMsg::FreeTextureView(id) => self.gpu_id_hub.lock().kill_texture_view_id(id),
|
||||
WebGPUMsg::Exit => *self.webgpu_port.borrow_mut() = None,
|
||||
WebGPUMsg::CleanDevice {
|
||||
WebGPUMsg::DeviceLost {
|
||||
pipeline_id,
|
||||
device,
|
||||
reason,
|
||||
msg,
|
||||
} => {
|
||||
let global = self.documents.borrow().find_global(pipeline_id).unwrap();
|
||||
global.remove_gpu_device(device);
|
||||
global.gpu_device_lost(device, reason, msg);
|
||||
},
|
||||
WebGPUMsg::UncapturedError {
|
||||
device,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue