Skip to content

Commit

Permalink
[WebGPU] Device lost promise takes too long to resolve
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=269019
<radar://122582535>

Reviewed by Dan Glastonbury.

We weren't resolving onSubmittedWorkDone in a timely fashion
when the device was lost, leading to perceived hang running
api,validation,state,detroy,* tests.

* Source/WebGPU/WebGPU/Device.mm:
(WebGPU::Device::loseTheDevice):
* Source/WebGPU/WebGPU/Queue.h:
(WebGPU::Queue::makeInvalid): Deleted.
* Source/WebGPU/WebGPU/Queue.mm:
(WebGPU::Queue::makeInvalid):
(WebGPU::Queue::onSubmittedWorkDone):
(WebGPU::Queue::onSubmittedWorkScheduled):

Canonical link: https://commits.webkit.org/274482@main
  • Loading branch information
mwyrzykowski committed Feb 12, 2024
1 parent 52ba501 commit dd3938f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
6 changes: 1 addition & 5 deletions Source/WebGPU/WebGPU/Device.mm
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ static void captureFrame(id<MTLDevice> captureObject)

void Device::loseTheDevice(WGPUDeviceLostReason reason)
{
// https://gpuweb.github.io/gpuweb/#lose-the-device
m_device = nil;

m_adapter->makeInvalid();

Expand All @@ -233,11 +233,7 @@ static void captureFrame(id<MTLDevice> captureObject)
m_deviceLostCallback = nullptr;
}

// FIXME: The spec doesn't actually say to do this, but it's pretty important because
// the total number of command queues alive at a time is limited to a pretty low limit.
// We should make sure either that this is unobservable or that the spec says to do this.
m_defaultQueue->makeInvalid();

m_isLost = true;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/WebGPU/WebGPU/Queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Queue : public WGPUQueueImpl, public ThreadSafeRefCounted<Queue> {
void onSubmittedWorkScheduled(CompletionHandler<void()>&&);

bool isValid() const { return m_commandQueue; }
void makeInvalid() { m_commandQueue = nil; }
void makeInvalid();

const Device& device() const;
void waitUntilIdle();
Expand Down
26 changes: 26 additions & 0 deletions Source/WebGPU/WebGPU/Queue.mm
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,30 @@
return buffer;
}

void Queue::makeInvalid()
{
m_commandQueue = nil;
for (auto& [_, callbackVector] : m_onSubmittedWorkScheduledCallbacks) {
for (auto& callback : callbackVector)
callback();
}
for (auto& [_, callbackVector] : m_onSubmittedWorkDoneCallbacks) {
for (auto& callback : callbackVector)
callback(WGPUQueueWorkDoneStatus_DeviceLost);
}

m_onSubmittedWorkScheduledCallbacks.clear();
m_onSubmittedWorkDoneCallbacks.clear();
}

void Queue::onSubmittedWorkDone(CompletionHandler<void(WGPUQueueWorkDoneStatus)>&& callback)
{
// https://gpuweb.github.io/gpuweb/#dom-gpuqueue-onsubmittedworkdone
auto devicePtr = m_device.get();
if (!devicePtr || !devicePtr->isValid() || devicePtr->isLost()) {
callback(WGPUQueueWorkDoneStatus_DeviceLost);
return;
}

ASSERT(m_submittedCommandBufferCount >= m_completedCommandBufferCount);

Expand All @@ -143,6 +164,11 @@
void Queue::onSubmittedWorkScheduled(CompletionHandler<void()>&& completionHandler)
{
ASSERT(m_submittedCommandBufferCount >= m_scheduledCommandBufferCount);
auto devicePtr = m_device.get();
if (!devicePtr || !devicePtr->isValid() || devicePtr->isLost()) {
completionHandler();
return;
}

finalizeBlitCommandEncoder();

Expand Down

0 comments on commit dd3938f

Please sign in to comment.