- Revision
- 291365
- Author
- [email protected]
- Date
- 2022-03-16 14:06:26 -0700 (Wed, 16 Mar 2022)
Log Message
[WebGPU] Create a path of Ref<>s between Instance and Queue
https://bugs.webkit.org/show_bug.cgi?id=237864
Reviewed by Kimmo Kinnunen.
The ownership model of WebGPU is that there is a tree of objects, and _javascript_ has references
to the leaves of the tree. The leaves are therefore allowed to reference their parents, all the
way up the tree. Therefore, Buffer can have a Ref to Device, which can have a Ref to Instance.
Device has to be in the chain eventually, because of the "valid to use with" check:
https://gpuweb.github.io/gpuweb/#abstract-opdef-valid-to-use-with, so we might as well add it in
to the chain now.
The one exception from this ownership model is Queue, which needs to be owned by Device, so
Device::getQueue() can return the same object when called multiple times (see
https://bugs.webkit.org/show_bug.cgi?id=237861). So, Queue has a raw C++ reference to its owning
Device.
Queue needs to be able to run asynchronous work, becuase Queue will need to add completedHandlers
to all command buffers committed, in order to perform its own internal bookkeeping. So, Queue
uses its C++ reference to its owning Device, which uses its Ref to its Instance, in order to use
Instance's facilities for running asynchronous work. This patch adds the necessesary Ref<>s to
make that happen.
* WebGPU/Adapter.h:
(WebGPU::Adapter::create):
* WebGPU/Adapter.mm:
(WebGPU::Adapter::Adapter):
(WebGPU::Adapter::requestDevice):
(WebGPU::Adapter::scheduleWork):
* WebGPU/Device.h:
(WebGPU::Device::create):
* WebGPU/Device.mm:
(WebGPU::createDefaultQueue):
(WebGPU::Device::Device):
(WebGPU::Device::scheduleWork):
(WebGPU::Device::create): Deleted.
* WebGPU/Instance.mm:
(WebGPU::Instance::requestAdapter):
* WebGPU/Queue.h:
(WebGPU::Queue::create):
* WebGPU/Queue.mm:
(WebGPU::Queue::Queue):
(WebGPU::Queue::scheduleWork):
Modified Paths
Diff
Modified: trunk/Source/WebGPU/ChangeLog (291364 => 291365)
--- trunk/Source/WebGPU/ChangeLog 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/ChangeLog 2022-03-16 21:06:26 UTC (rev 291365)
@@ -1,3 +1,49 @@
+2022-03-16 Myles C. Maxfield <[email protected]>
+
+ [WebGPU] Create a path of Ref<>s between Instance and Queue
+ https://bugs.webkit.org/show_bug.cgi?id=237864
+
+ Reviewed by Kimmo Kinnunen.
+
+ The ownership model of WebGPU is that there is a tree of objects, and _javascript_ has references
+ to the leaves of the tree. The leaves are therefore allowed to reference their parents, all the
+ way up the tree. Therefore, Buffer can have a Ref to Device, which can have a Ref to Instance.
+ Device has to be in the chain eventually, because of the "valid to use with" check:
+ https://gpuweb.github.io/gpuweb/#abstract-opdef-valid-to-use-with, so we might as well add it in
+ to the chain now.
+
+ The one exception from this ownership model is Queue, which needs to be owned by Device, so
+ Device::getQueue() can return the same object when called multiple times (see
+ https://bugs.webkit.org/show_bug.cgi?id=237861). So, Queue has a raw C++ reference to its owning
+ Device.
+
+ Queue needs to be able to run asynchronous work, becuase Queue will need to add completedHandlers
+ to all command buffers committed, in order to perform its own internal bookkeeping. So, Queue
+ uses its C++ reference to its owning Device, which uses its Ref to its Instance, in order to use
+ Instance's facilities for running asynchronous work. This patch adds the necessesary Ref<>s to
+ make that happen.
+
+ * WebGPU/Adapter.h:
+ (WebGPU::Adapter::create):
+ * WebGPU/Adapter.mm:
+ (WebGPU::Adapter::Adapter):
+ (WebGPU::Adapter::requestDevice):
+ (WebGPU::Adapter::scheduleWork):
+ * WebGPU/Device.h:
+ (WebGPU::Device::create):
+ * WebGPU/Device.mm:
+ (WebGPU::createDefaultQueue):
+ (WebGPU::Device::Device):
+ (WebGPU::Device::scheduleWork):
+ (WebGPU::Device::create): Deleted.
+ * WebGPU/Instance.mm:
+ (WebGPU::Instance::requestAdapter):
+ * WebGPU/Queue.h:
+ (WebGPU::Queue::create):
+ * WebGPU/Queue.mm:
+ (WebGPU::Queue::Queue):
+ (WebGPU::Queue::scheduleWork):
+
2022-03-15 Myles C. Maxfield <[email protected]>
[WebGPU] Migrate from WTF::Function to WTF::CompletionHandler
Modified: trunk/Source/WebGPU/WebGPU/Adapter.h (291364 => 291365)
--- trunk/Source/WebGPU/WebGPU/Adapter.h 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/WebGPU/Adapter.h 2022-03-16 21:06:26 UTC (rev 291365)
@@ -34,13 +34,14 @@
namespace WebGPU {
class Device;
+class Instance;
class Adapter : public RefCounted<Adapter> {
WTF_MAKE_FAST_ALLOCATED;
public:
- static Ref<Adapter> create(id<MTLDevice> device)
+ static Ref<Adapter> create(id<MTLDevice> device, Instance& instance)
{
- return adoptRef(*new Adapter(device));
+ return adoptRef(*new Adapter(device, instance));
}
~Adapter();
@@ -52,9 +53,10 @@
void requestDevice(const WGPUDeviceDescriptor&, CompletionHandler<void(WGPURequestDeviceStatus, RefPtr<Device>&&, const char*)>&& callback);
private:
- Adapter(id<MTLDevice>);
+ Adapter(id<MTLDevice>, Instance&);
id<MTLDevice> m_device { nil };
+ Ref<Instance> m_instance;
};
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Adapter.mm (291364 => 291365)
--- trunk/Source/WebGPU/WebGPU/Adapter.mm 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/WebGPU/Adapter.mm 2022-03-16 21:06:26 UTC (rev 291365)
@@ -27,12 +27,14 @@
#import "Adapter.h"
#import "Device.h"
+#import "Instance.h"
#import <wtf/StdLibExtras.h>
namespace WebGPU {
-Adapter::Adapter(id<MTLDevice> device)
+Adapter::Adapter(id<MTLDevice> device, Instance& instance)
: m_device(device)
+ , m_instance(instance)
{
}
@@ -120,7 +122,7 @@
return;
}
- callback(WGPURequestDeviceStatus_Success, Device::create(m_device, descriptor.label), nullptr);
+ callback(WGPURequestDeviceStatus_Success, Device::create(m_device, descriptor.label, m_instance), nullptr);
}
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Device.h (291364 => 291365)
--- trunk/Source/WebGPU/WebGPU/Device.h 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/WebGPU/Device.h 2022-03-16 21:06:26 UTC (rev 291365)
@@ -40,6 +40,7 @@
class Buffer;
class CommandEncoder;
class ComputePipeline;
+class Instance;
class PipelineLayout;
class QuerySet;
class RenderBundleEncoder;
@@ -53,7 +54,7 @@
class Device : public RefCounted<Device> {
WTF_MAKE_FAST_ALLOCATED;
public:
- static RefPtr<Device> create(id<MTLDevice>, const char* deviceLabel);
+ static RefPtr<Device> create(id<MTLDevice>, const char* deviceLabel, Instance&);
~Device();
@@ -83,11 +84,14 @@
void setUncapturedErrorCallback(Function<void(WGPUErrorType, const char*)>&&);
void setLabel(const char*);
+ Instance& instance() { return m_instance; }
+
private:
- Device(id<MTLDevice>, Ref<Queue>&&);
+ Device(id<MTLDevice>, id<MTLCommandQueue> defaultQueue, Instance&);
id<MTLDevice> m_device { nil };
Ref<Queue> m_defaultQueue;
+ Ref<Instance> m_instance;
};
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Device.mm (291364 => 291365)
--- trunk/Source/WebGPU/WebGPU/Device.mm 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/WebGPU/Device.mm 2022-03-16 21:06:26 UTC (rev 291365)
@@ -45,12 +45,11 @@
namespace WebGPU {
-RefPtr<Device> Device::create(id<MTLDevice> device, const char* deviceLabel)
+RefPtr<Device> Device::create(id<MTLDevice> device, const char* deviceLabel, Instance& instance)
{
id<MTLCommandQueue> commandQueue = [device newCommandQueue];
if (!commandQueue)
return nullptr;
- auto queue = Queue::create(commandQueue);
// See the comment in Device::setLabel() about why we're not setting the label on the MTLDevice here.
@@ -58,12 +57,13 @@
if (deviceLabel && deviceLabel[0] != '\0')
commandQueue.label = [NSString stringWithFormat:@"Default queue for device %s", deviceLabel];
- return adoptRef(*new Device(device, WTFMove(queue)));
+ return adoptRef(*new Device(device, commandQueue, instance));
}
-Device::Device(id<MTLDevice> device, Ref<Queue>&& queue)
+Device::Device(id<MTLDevice> device, id<MTLCommandQueue> defaultQueue, Instance& instance)
: m_device(device)
- , m_defaultQueue(WTFMove(queue))
+ , m_defaultQueue(Queue::create(defaultQueue, *this))
+ , m_instance(instance)
{
}
Modified: trunk/Source/WebGPU/WebGPU/Instance.mm (291364 => 291365)
--- trunk/Source/WebGPU/WebGPU/Instance.mm 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/WebGPU/Instance.mm 2022-03-16 21:06:26 UTC (rev 291365)
@@ -165,7 +165,7 @@
return;
}
- callback(WGPURequestAdapterStatus_Success, Adapter::create(sortedDevices[0]), nullptr);
+ callback(WGPURequestAdapterStatus_Success, Adapter::create(sortedDevices[0], *this), nullptr);
}
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Queue.h (291364 => 291365)
--- trunk/Source/WebGPU/WebGPU/Queue.h 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/WebGPU/Queue.h 2022-03-16 21:06:26 UTC (rev 291365)
@@ -25,10 +25,11 @@
#pragma once
+#import "Instance.h"
#import <wtf/CompletionHandler.h>
#import <wtf/FastMalloc.h>
#import <wtf/Ref.h>
-#import <wtf/RefCounted.h>
+#import <wtf/ThreadSafeRefCounted.h>
#import <wtf/Vector.h>
namespace WebGPU {
@@ -35,13 +36,14 @@
class Buffer;
class CommandBuffer;
+class Device;
-class Queue : public RefCounted<Queue> {
+class Queue : public ThreadSafeRefCounted<Queue> {
WTF_MAKE_FAST_ALLOCATED;
public:
- static Ref<Queue> create(id<MTLCommandQueue> commandQueue)
+ static Ref<Queue> create(id<MTLCommandQueue> commandQueue, Device& device)
{
- return adoptRef(*new Queue(commandQueue));
+ return adoptRef(*new Queue(commandQueue, device));
}
~Queue();
@@ -53,9 +55,13 @@
void setLabel(const char*);
private:
- Queue(id<MTLCommandQueue>);
+ Queue(id<MTLCommandQueue>, Device&);
+ // This can be called on a background thread.
+ void scheduleWork(Instance::WorkItem&&);
+
id<MTLCommandQueue> m_commandQueue { nil };
+ Device& m_device; // The only kind of queues that exist right now are default queues, which are owned by Devices.
};
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Queue.mm (291364 => 291365)
--- trunk/Source/WebGPU/WebGPU/Queue.mm 2022-03-16 20:52:19 UTC (rev 291364)
+++ trunk/Source/WebGPU/WebGPU/Queue.mm 2022-03-16 21:06:26 UTC (rev 291365)
@@ -28,11 +28,13 @@
#import "Buffer.h"
#import "CommandBuffer.h"
+#import "Device.h"
namespace WebGPU {
-Queue::Queue(id<MTLCommandQueue> commandQueue)
+Queue::Queue(id<MTLCommandQueue> commandQueue, Device& device)
: m_commandQueue(commandQueue)
+ , m_device(device)
{
}
@@ -71,6 +73,11 @@
m_commandQueue.label = [NSString stringWithCString:label encoding:NSUTF8StringEncoding];
}
+void Queue::scheduleWork(Instance::WorkItem&& workItem)
+{
+ m_device.instance().scheduleWork(WTFMove(workItem));
+}
+
} // namespace WebGPU
void wgpuQueueRelease(WGPUQueue queue)