[dawn][emscripten] Implements create*PipelineAsync future entry points
- Also some minor re-ordering of the file to keep alphabetical order.
Bug: 369443752
Change-Id: I6fe252228a93abd1bd4f4639b91f2f6d41e46d27
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/207614
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/third_party/emdawnwebgpu/library_webgpu.js b/third_party/emdawnwebgpu/library_webgpu.js
index 0165702..2fc6219 100644
--- a/third_party/emdawnwebgpu/library_webgpu.js
+++ b/third_party/emdawnwebgpu/library_webgpu.js
@@ -1449,33 +1449,28 @@
return ptr;
},
- wgpuDeviceCreateComputePipelineAsync__deps: ['$callUserCallback', '$stringToUTF8OnStack', 'emwgpuCreateComputePipeline'],
- wgpuDeviceCreateComputePipelineAsync: (devicePtr, descriptor, callback, userdata) => {
+ emwgpuDeviceCreateComputePipelineAsync__i53abi:false,
+ emwgpuDeviceCreateComputePipelineAsync__deps: ['$stringToUTF8OnStack', 'emwgpuCreateComputePipeline', 'emwgpuOnDeviceCreateComputePipelineCompleted'],
+ emwgpuDeviceCreateComputePipelineAsync: (devicePtr, futureIdL, futureIdH, descriptor) => {
var desc = WebGPU.makeComputePipelineDesc(descriptor);
var device = WebGPU._tableGet(devicePtr);
{{{ runtimeKeepalivePush() }}}
- device.createComputePipelineAsync(desc).then((pipeline) => {
+ WebGPU._futureInsert(futureIdL, futureIdH, device.createComputePipelineAsync(desc).then((pipeline) => {
{{{ runtimeKeepalivePop() }}}
- callUserCallback(() => {
- var ptr = _emwgpuCreateComputePipeline();
- WebGPU._tableInsert(ptr, pipeline);
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Success }}}, ptr, 0, userdata);
- });
+ var pipelinePtr = _emwgpuCreateComputePipeline();
+ WebGPU._tableInsert(pipelinePtr, pipeline);
+ _emwgpuOnDeviceCreateComputePipelineCompleted(futureIdL, futureIdH, {{{ gpu.CreatePipelineAsyncStatus.Success }}}, pipelinePtr, 0);
}, (pipelineError) => {
{{{ runtimeKeepalivePop() }}}
- callUserCallback(() => {
- var sp = stackSave();
- var messagePtr = stringToUTF8OnStack(pipelineError.message);
- if (pipelineError.reason === 'validation') {
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.ValidationError }}}, 0, messagePtr, userdata);
- } else if (pipelineError.reason === 'internal') {
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.InternalError }}}, 0, messagePtr, userdata);
- } else {
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Unknown }}}, 0, messagePtr, userdata);
- }
- stackRestore(sp);
- });
- });
+ var sp = stackSave();
+ var messagePtr = stringToUTF8OnStack(pipelineError.message);
+ var status =
+ pipeline.reason === 'validation' ? {{{ gpu.CreatePipelineAsyncStatus.ValidationError }}} :
+ pipeline.reason === 'internal' ? {{{ gpu.CreatePipelineAsyncStatus.InternalError }}} :
+ {{{ gpu.CreatePipelineAsyncStatus.Unknown }}};
+ _emwgpuOnDeviceCreateComputePipelineCompleted(futureIdL, futureIdH, status, 0, messagePtr);
+ stackRestore(sp);
+ }));
},
wgpuDeviceCreatePipelineLayout__deps: ['emwgpuCreatePipelineLayout'],
@@ -1564,33 +1559,28 @@
return ptr;
},
- wgpuDeviceCreateRenderPipelineAsync__deps: ['$callUserCallback', '$stringToUTF8OnStack', 'emwgpuCreateRenderPipeline'],
- wgpuDeviceCreateRenderPipelineAsync: (devicePtr, descriptor, callback, userdata) => {
+ emwgpuDeviceCreateRenderPipelineAsync__i53abi:false,
+ emwgpuDeviceCreateRenderPipelineAsync__deps: ['$stringToUTF8OnStack', 'emwgpuCreateRenderPipeline', 'emwgpuOnDeviceCreateRenderPipelineCompleted'],
+ emwgpuDeviceCreateRenderPipelineAsync: (devicePtr, futureIdL, futureIdH, descriptor) => {
var desc = WebGPU.makeRenderPipelineDesc(descriptor);
var device = WebGPU._tableGet(devicePtr);
{{{ runtimeKeepalivePush() }}}
- device.createRenderPipelineAsync(desc).then((pipeline) => {
+ WebGPU._futureInsert(futureIdL, futureIdH, device.createRenderPipelineAsync(desc).then((pipeline) => {
{{{ runtimeKeepalivePop() }}}
- callUserCallback(() => {
- var ptr = _emwgpuCreateRenderPipeline();
- WebGPU._tableInsert(ptr, pipeline);
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Success }}}, ptr, 0, userdata);
- });
+ var pipelinePtr = _emwgpuCreateRenderPipeline();
+ WebGPU._tableInsert(pipelinePtr, pipeline);
+ _emwgpuOnDeviceCreateRenderPipelineCompleted(futureIdL, futureIdH, {{{ gpu.CreatePipelineAsyncStatus.Success }}}, pipelinePtr, 0);
}, (pipelineError) => {
{{{ runtimeKeepalivePop() }}}
- callUserCallback(() => {
- var sp = stackSave();
- var messagePtr = stringToUTF8OnStack(pipelineError.message);
- if (pipelineError.reason === 'validation') {
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.ValidationError }}}, 0, messagePtr, userdata);
- } else if (pipelineError.reason === 'internal') {
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.InternalError }}}, 0, messagePtr, userdata);
- } else {
- {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Unknown }}}, 0, messagePtr, userdata);
- }
- stackRestore(sp);
- });
- });
+ var sp = stackSave();
+ var messagePtr = stringToUTF8OnStack(pipelineError.message);
+ var status =
+ pipeline.reason === 'validation' ? {{{ gpu.CreatePipelineAsyncStatus.ValidationError }}} :
+ pipeline.reason === 'internal' ? {{{ gpu.CreatePipelineAsyncStatus.InternalError }}} :
+ {{{ gpu.CreatePipelineAsyncStatus.Unknown }}};
+ _emwgpuOnDeviceCreateRenderPipelineCompleted(futureIdL, futureIdH, status, 0, messagePtr);
+ stackRestore(sp);
+ }));
},
wgpuDeviceCreateSampler__deps: ['emwgpuCreateSampler'],
@@ -1917,14 +1907,12 @@
_emwgpuOnRequestAdapterCompleted(futureIdL, futureIdH, {{{ gpu.RequestAdapterStatus.Unavailable }}}, 0, messagePtr);
stackRestore(sp);
}
- return;
}, (ex) => {
{{{ runtimeKeepalivePop() }}}
var sp = stackSave();
var messagePtr = stringToUTF8OnStack(ex.message);
_emwgpuOnRequestAdapterCompleted(futureIdL, futureIdH, {{{ gpu.RequestAdapterStatus.Error }}}, 0, messagePtr);
stackRestore(sp);
- return;
}));
},
diff --git a/third_party/emdawnwebgpu/webgpu.cpp b/third_party/emdawnwebgpu/webgpu.cpp
index 9933fe7..850b4a6 100644
--- a/third_party/emdawnwebgpu/webgpu.cpp
+++ b/third_party/emdawnwebgpu/webgpu.cpp
@@ -47,6 +47,14 @@
WGPUDevice device,
WGPUQueue queue,
const WGPUDeviceDescriptor* descriptor);
+void emwgpuDeviceCreateComputePipelineAsync(
+ WGPUDevice device,
+ FutureID futureId,
+ const WGPUComputePipelineDescriptor* descriptor);
+void emwgpuDeviceCreateRenderPipelineAsync(
+ WGPUDevice device,
+ FutureID futureId,
+ const WGPURenderPipelineDescriptor* descriptor);
void emwgpuInstanceRequestAdapter(WGPUInstance instance,
FutureID futureId,
const WGPURequestAdapterOptions* options);
@@ -281,6 +289,8 @@
Shutdown,
};
enum class EventType {
+ CreateComputePipeline,
+ CreateRenderPipeline,
DeviceLost,
RequestAdapter,
RequestDevice,
@@ -569,21 +579,6 @@
struct WGPU##Name##Impl final : public RefCounted {};
WGPU_PASSTHROUGH_OBJECTS(DEFINE_WGPU_DEFAULT_STRUCT)
-// Instance is specially implemented in order to handle Futures implementation.
-struct WGPUInstanceImpl final : public RefCounted, public EventSource {
- public:
- WGPUInstanceImpl();
- ~WGPUInstanceImpl();
-
- void ProcessEvents();
- WGPUWaitStatus WaitAny(size_t count,
- WGPUFutureWaitInfo* infos,
- uint64_t timeoutNS);
-
- private:
- static InstanceID GetNextInstanceId();
-};
-
struct WGPUAdapterImpl final : public RefCounted, public EventSource {
public:
WGPUAdapterImpl(const EventSource* source);
@@ -614,10 +609,81 @@
FutureID mDeviceLostFutureId = kNullFutureId;
};
+// Instance is specially implemented in order to handle Futures implementation.
+struct WGPUInstanceImpl final : public RefCounted, public EventSource {
+ public:
+ WGPUInstanceImpl();
+ ~WGPUInstanceImpl();
+
+ void ProcessEvents();
+ WGPUWaitStatus WaitAny(size_t count,
+ WGPUFutureWaitInfo* infos,
+ uint64_t timeoutNS);
+
+ private:
+ static InstanceID GetNextInstanceId();
+};
+
// ----------------------------------------------------------------------------
// Future events.
// ----------------------------------------------------------------------------
+template <typename Pipeline, EventType Type, typename CallbackInfo>
+class CreatePipelineEventBase final : public TrackedEvent {
+ public:
+ static constexpr EventType kType = Type;
+
+ CreatePipelineEventBase(InstanceID instance, const CallbackInfo& callbackInfo)
+ : TrackedEvent(instance, callbackInfo.mode),
+ mCallback(callbackInfo.callback),
+ mUserdata1(callbackInfo.userdata1),
+ mUserdata2(callbackInfo.userdata2) {}
+
+ EventType GetType() override { return kType; }
+
+ void ReadyHook(WGPUCreatePipelineAsyncStatus status,
+ Pipeline pipeline,
+ const char* message) {
+ mStatus = status;
+ mPipeline.Acquire(pipeline);
+ if (message) {
+ mMessage = message;
+ }
+ }
+
+ void Complete(FutureID, EventCompletionType type) override {
+ if (type == EventCompletionType::Shutdown) {
+ mStatus = WGPUCreatePipelineAsyncStatus_InstanceDropped;
+ mMessage = "A valid external Instance reference no longer exists.";
+ }
+ if (mCallback) {
+ mCallback(mStatus,
+ mStatus == WGPUCreatePipelineAsyncStatus_Success
+ ? ReturnToAPI(std::move(mPipeline))
+ : nullptr,
+ mMessage ? mMessage->c_str() : nullptr, mUserdata1, mUserdata2);
+ }
+ }
+
+ private:
+ using Callback = decltype(std::declval<CallbackInfo>().callback);
+ Callback mCallback = nullptr;
+ void* mUserdata1 = nullptr;
+ void* mUserdata2 = nullptr;
+
+ WGPUCreatePipelineAsyncStatus mStatus = WGPUCreatePipelineAsyncStatus_Success;
+ Ref<Pipeline> mPipeline;
+ std::optional<std::string> mMessage = std::nullopt;
+};
+using CreateComputePipelineEvent =
+ CreatePipelineEventBase<WGPUComputePipeline,
+ EventType::CreateComputePipeline,
+ WGPUCreateComputePipelineAsyncCallbackInfo2>;
+using CreateRenderPipelineEvent =
+ CreatePipelineEventBase<WGPURenderPipeline,
+ EventType::CreateRenderPipeline,
+ WGPUCreateRenderPipelineAsyncCallbackInfo2>;
+
class DeviceLostEvent final : public TrackedEvent {
public:
static constexpr EventType kType = EventType::DeviceLost;
@@ -773,32 +839,6 @@
: EventSource(source->GetInstanceId()) {}
// ----------------------------------------------------------------------------
-// WGPUInstanceImpl implementations.
-// ----------------------------------------------------------------------------
-
-WGPUInstanceImpl::WGPUInstanceImpl() : EventSource(GetNextInstanceId()) {
- GetEventManager().RegisterInstance(GetInstanceId());
-}
-WGPUInstanceImpl::~WGPUInstanceImpl() {
- GetEventManager().UnregisterInstance(GetInstanceId());
-}
-
-void WGPUInstanceImpl::ProcessEvents() {
- GetEventManager().ProcessEvents(GetInstanceId());
-}
-
-WGPUWaitStatus WGPUInstanceImpl::WaitAny(size_t count,
- WGPUFutureWaitInfo* infos,
- uint64_t timeoutNS) {
- return GetEventManager().WaitAny(GetInstanceId(), count, infos, timeoutNS);
-}
-
-InstanceID WGPUInstanceImpl::GetNextInstanceId() {
- static std::atomic<InstanceID> kNextInstanceId = 1;
- return kNextInstanceId++;
-}
-
-// ----------------------------------------------------------------------------
// WGPUDeviceImpl implementations.
// ----------------------------------------------------------------------------
@@ -848,6 +888,32 @@
}
// ----------------------------------------------------------------------------
+// WGPUInstanceImpl implementations.
+// ----------------------------------------------------------------------------
+
+WGPUInstanceImpl::WGPUInstanceImpl() : EventSource(GetNextInstanceId()) {
+ GetEventManager().RegisterInstance(GetInstanceId());
+}
+WGPUInstanceImpl::~WGPUInstanceImpl() {
+ GetEventManager().UnregisterInstance(GetInstanceId());
+}
+
+void WGPUInstanceImpl::ProcessEvents() {
+ GetEventManager().ProcessEvents(GetInstanceId());
+}
+
+WGPUWaitStatus WGPUInstanceImpl::WaitAny(size_t count,
+ WGPUFutureWaitInfo* infos,
+ uint64_t timeoutNS) {
+ return GetEventManager().WaitAny(GetInstanceId(), count, infos, timeoutNS);
+}
+
+InstanceID WGPUInstanceImpl::GetNextInstanceId() {
+ static std::atomic<InstanceID> kNextInstanceId = 1;
+ return kNextInstanceId++;
+}
+
+// ----------------------------------------------------------------------------
// Definitions for C++ emwgpu functions (callable from library_webgpu.js)
// ----------------------------------------------------------------------------
extern "C" {
@@ -869,6 +935,22 @@
}
// Future event callbacks.
+void emwgpuOnDeviceCreateComputePipelineCompleted(
+ FutureID futureId,
+ WGPUCreatePipelineAsyncStatus status,
+ WGPUComputePipeline pipeline,
+ const char* message) {
+ GetEventManager().SetFutureReady<CreateComputePipelineEvent>(
+ futureId, status, pipeline, message);
+}
+void emwgpuOnDeviceCreateRenderPipelineCompleted(
+ FutureID futureId,
+ WGPUCreatePipelineAsyncStatus status,
+ WGPURenderPipeline pipeline,
+ const char* message) {
+ GetEventManager().SetFutureReady<CreateRenderPipelineEvent>(
+ futureId, status, pipeline, message);
+}
void emwgpuOnDeviceLostCompleted(FutureID futureId,
WGPUDeviceLostReason reason,
const char* message) {
@@ -1037,6 +1119,73 @@
// Methods of Device
// ----------------------------------------------------------------------------
+void wgpuDeviceCreateComputePipelineAsync(
+ WGPUDevice device,
+ const WGPUComputePipelineDescriptor* descriptor,
+ WGPUCreateComputePipelineAsyncCallback callback,
+ void* userdata) {
+ WGPUCreateComputePipelineAsyncCallbackInfo2 callbackInfo = {};
+ callbackInfo.mode = WGPUCallbackMode_AllowSpontaneous;
+ callbackInfo.callback = [](WGPUCreatePipelineAsyncStatus status,
+ WGPUComputePipeline pipeline, char const* message,
+ void* callback, void* userdata) {
+ auto cb =
+ reinterpret_cast<WGPUCreateComputePipelineAsyncCallback>(callback);
+ cb(status, pipeline, message, userdata);
+ };
+ callbackInfo.userdata1 = reinterpret_cast<void*>(callback);
+ callbackInfo.userdata2 = userdata;
+ wgpuDeviceCreateComputePipelineAsync2(device, descriptor, callbackInfo);
+}
+
+WGPUFuture wgpuDeviceCreateComputePipelineAsync2(
+ WGPUDevice device,
+ const WGPUComputePipelineDescriptor* descriptor,
+ WGPUCreateComputePipelineAsyncCallbackInfo2 callbackInfo) {
+ auto [futureId, tracked] =
+ GetEventManager().TrackEvent(std::make_unique<CreateComputePipelineEvent>(
+ device->GetInstanceId(), callbackInfo));
+ if (!tracked) {
+ return WGPUFuture{kNullFutureId};
+ }
+
+ emwgpuDeviceCreateComputePipelineAsync(device, futureId, descriptor);
+ return WGPUFuture{futureId};
+}
+
+void wgpuDeviceCreateRenderPipelineAsync(
+ WGPUDevice device,
+ const WGPURenderPipelineDescriptor* descriptor,
+ WGPUCreateRenderPipelineAsyncCallback callback,
+ void* userdata) {
+ WGPUCreateRenderPipelineAsyncCallbackInfo2 callbackInfo = {};
+ callbackInfo.mode = WGPUCallbackMode_AllowSpontaneous;
+ callbackInfo.callback = [](WGPUCreatePipelineAsyncStatus status,
+ WGPURenderPipeline pipeline, char const* message,
+ void* callback, void* userdata) {
+ auto cb = reinterpret_cast<WGPUCreateRenderPipelineAsyncCallback>(callback);
+ cb(status, pipeline, message, userdata);
+ };
+ callbackInfo.userdata1 = reinterpret_cast<void*>(callback);
+ callbackInfo.userdata2 = userdata;
+ wgpuDeviceCreateRenderPipelineAsync2(device, descriptor, callbackInfo);
+}
+
+WGPUFuture wgpuDeviceCreateRenderPipelineAsync2(
+ WGPUDevice device,
+ const WGPURenderPipelineDescriptor* descriptor,
+ WGPUCreateRenderPipelineAsyncCallbackInfo2 callbackInfo) {
+ auto [futureId, tracked] =
+ GetEventManager().TrackEvent(std::make_unique<CreateRenderPipelineEvent>(
+ device->GetInstanceId(), callbackInfo));
+ if (!tracked) {
+ return WGPUFuture{kNullFutureId};
+ }
+
+ emwgpuDeviceCreateRenderPipelineAsync(device, futureId, descriptor);
+ return WGPUFuture{futureId};
+}
+
WGPUQueue wgpuDeviceGetQueue(WGPUDevice device) {
return device->GetQueue();
}