Bug 1838694: fix(webgpu): impl. correct GPUError types r=jgilbert,webgpu-reviewers,webidl,peterv

Differential Revision: https://phabricator.services.mozilla.com/D181690
This commit is contained in:
Erich Gubler 2023-07-06 20:50:52 +00:00
parent fdd9df03d3
commit 260a0b100c
16 changed files with 203 additions and 68 deletions

View file

@ -1440,6 +1440,12 @@ DOMInterfaces = {
'GPUDeviceLostInfo': { 'GPUDeviceLostInfo': {
'nativeType': 'mozilla::webgpu::DeviceLostInfo', 'nativeType': 'mozilla::webgpu::DeviceLostInfo',
}, },
'GPUError': {
'nativeType': 'mozilla::webgpu::Error',
},
'GPUInternalError': {
'nativeType': 'mozilla::webgpu::InternalError',
},
'GPUOutOfMemoryError': { 'GPUOutOfMemoryError': {
'nativeType': 'mozilla::webgpu::OutOfMemoryError', 'nativeType': 'mozilla::webgpu::OutOfMemoryError',
}, },

View file

@ -514,6 +514,10 @@ let interfaceNamesInGlobalScope = [
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "GPUDeviceLostInfo", nightly: true }, { name: "GPUDeviceLostInfo", nightly: true },
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "GPUError", nightly: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "GPUInternalError", nightly: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "GPUMapMode", nightly: true }, { name: "GPUMapMode", nightly: true },
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "GPUOutOfMemoryError", nightly: true }, { name: "GPUOutOfMemoryError", nightly: true },

View file

@ -8,6 +8,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/WebGPUBinding.h" #include "mozilla/dom/WebGPUBinding.h"
#include "Device.h" #include "Device.h"
@ -18,6 +19,7 @@
#include "Buffer.h" #include "Buffer.h"
#include "ComputePipeline.h" #include "ComputePipeline.h"
#include "DeviceLostInfo.h" #include "DeviceLostInfo.h"
#include "InternalError.h"
#include "OutOfMemoryError.h" #include "OutOfMemoryError.h"
#include "PipelineLayout.h" #include "PipelineLayout.h"
#include "Queue.h" #include "Queue.h"
@ -358,7 +360,7 @@ already_AddRefed<dom::Promise> Device::PopErrorScope(ErrorResult& aRv) {
errorPromise->Then( errorPromise->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}, promise](const PopErrorScopeResult& aResult) { [self = RefPtr{this}, promise](const PopErrorScopeResult& aResult) {
dom::OwningGPUOutOfMemoryErrorOrGPUValidationError error; RefPtr<Error> error;
switch (aResult.resultType) { switch (aResult.resultType) {
case PopErrorScopeResultType::NoError: case PopErrorScopeResultType::NoError:
@ -377,21 +379,18 @@ already_AddRefed<dom::Promise> Device::PopErrorScope(ErrorResult& aRv) {
return; return;
case PopErrorScopeResultType::OutOfMemory: case PopErrorScopeResultType::OutOfMemory:
error.SetAsGPUOutOfMemoryError() = new OutOfMemoryError(self); error =
new OutOfMemoryError(self->GetParentObject(), aResult.message);
break; break;
case PopErrorScopeResultType::ValidationError: case PopErrorScopeResultType::ValidationError:
error.SetAsGPUValidationError() = error =
new ValidationError(self->GetParentObject(), aResult.message); new ValidationError(self->GetParentObject(), aResult.message);
break; break;
case PopErrorScopeResultType::InternalError: case PopErrorScopeResultType::InternalError:
MOZ_CRASH("TODO"); error = new InternalError(self->GetParentObject(), aResult.message);
/*
error.SetAsGPUInternalError() = new InternalError(
self->GetParentObject(), aResult.message);
break; break;
*/
} }
promise->MaybeResolve(std::move(error)); promise->MaybeResolve(std::move(error));
}, },

20
dom/webgpu/Error.cpp Normal file
View file

@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Error.h"
namespace mozilla::webgpu {
GPU_IMPL_CYCLE_COLLECTION(Error, mGlobal)
Error::Error(nsIGlobalObject* const aGlobal, const nsACString& aMessage)
: mGlobal(aGlobal) {
CopyUTF8toUTF16(aMessage, mMessage);
}
Error::Error(nsIGlobalObject* const aGlobal, const nsAString& aMessage)
: mGlobal(aGlobal), mMessage(aMessage) {}
} // namespace mozilla::webgpu

46
dom/webgpu/Error.h Normal file
View file

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GPU_Error_H_
#define GPU_Error_H_
#include "js/Value.h"
#include "mozilla/WeakPtr.h"
#include "nsIGlobalObject.h"
#include "nsString.h"
#include "ObjectModel.h"
namespace mozilla {
class ErrorResult;
namespace dom {
class GlobalObject;
} // namespace dom
namespace webgpu {
class Error : public nsWrapperCache, public SupportsWeakPtr {
protected:
nsCOMPtr<nsIGlobalObject> mGlobal;
nsString mMessage;
public:
GPU_DECL_CYCLE_COLLECTION(Error)
Error(nsIGlobalObject* const aGlobal, const nsAString& aMessage);
Error(nsIGlobalObject* const aGlobal, const nsACString& aMessage);
protected:
virtual ~Error() = default;
virtual void Cleanup() {}
public:
void GetMessage(nsAString& aMessage) const { aMessage = mMessage; }
nsIGlobalObject* GetParentObject() const { return mGlobal; }
virtual JSObject* WrapObject(JSContext*, JS::Handle<JSObject*>) = 0;
};
} // namespace webgpu
} // namespace mozilla
#endif // GPU_Error_H_

View file

@ -0,0 +1,21 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "InternalError.h"
#include "mozilla/dom/WebGPUBinding.h"
namespace mozilla::webgpu {
GPU_IMPL_JS_WRAP(InternalError)
already_AddRefed<InternalError> InternalError::Constructor(
const dom::GlobalObject& aGlobal, const nsAString& aString,
ErrorResult& aRv) {
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_RELEASE_ASSERT(global);
return MakeAndAddRef<InternalError>(global, aString);
}
} // namespace mozilla::webgpu

View file

@ -0,0 +1,40 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GPU_InternalError_H_
#define GPU_InternalError_H_
#include "Error.h"
namespace mozilla {
class ErrorResult;
namespace dom {
class GlobalObject;
} // namespace dom
namespace webgpu {
class InternalError final : public Error {
public:
GPU_DECL_JS_WRAP(InternalError)
InternalError(nsIGlobalObject* const aGlobal, const nsAString& aMessage)
: Error(aGlobal, aMessage) {}
InternalError(nsIGlobalObject* const aGlobal, const nsACString& aMessage)
: Error(aGlobal, aMessage) {}
private:
~InternalError() override = default;
public:
static already_AddRefed<InternalError> Constructor(
const dom::GlobalObject& aGlobal, const nsAString& aString,
ErrorResult& aRv);
};
} // namespace webgpu
} // namespace mozilla
#endif // GPU_InternalError_H_

View file

@ -12,6 +12,7 @@
#include "CommandEncoder.h" #include "CommandEncoder.h"
#include "Instance.h" #include "Instance.h"
#include "Texture.h" #include "Texture.h"
#include "nsIGlobalObject.h"
namespace mozilla::webgpu { namespace mozilla::webgpu {

View file

@ -4,14 +4,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OutOfMemoryError.h" #include "OutOfMemoryError.h"
#include "Device.h"
#include "mozilla/dom/WebGPUBinding.h" #include "mozilla/dom/WebGPUBinding.h"
namespace mozilla::webgpu { namespace mozilla::webgpu {
GPU_IMPL_CYCLE_COLLECTION(OutOfMemoryError, mParent)
GPU_IMPL_JS_WRAP(OutOfMemoryError) GPU_IMPL_JS_WRAP(OutOfMemoryError)
OutOfMemoryError::~OutOfMemoryError() = default; already_AddRefed<OutOfMemoryError> OutOfMemoryError::Constructor(
const dom::GlobalObject& aGlobal, const nsAString& aString,
ErrorResult& aRv) {
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_RELEASE_ASSERT(global);
return MakeAndAddRef<OutOfMemoryError>(global, aString);
}
} // namespace mozilla::webgpu } // namespace mozilla::webgpu

View file

@ -6,27 +6,32 @@
#ifndef GPU_OutOfMemoryError_H_ #ifndef GPU_OutOfMemoryError_H_
#define GPU_OutOfMemoryError_H_ #define GPU_OutOfMemoryError_H_
#include "nsWrapperCache.h" #include "Error.h"
#include "ObjectModel.h"
namespace mozilla { namespace mozilla {
class ErrorResult;
namespace dom { namespace dom {
class GlobalObject; class GlobalObject;
} // namespace dom } // namespace dom
namespace webgpu { namespace webgpu {
class Device;
class OutOfMemoryError final : public nsWrapperCache, public ChildOf<Device> { class OutOfMemoryError final : public Error {
public: public:
GPU_DECL_CYCLE_COLLECTION(OutOfMemoryError)
GPU_DECL_JS_WRAP(OutOfMemoryError) GPU_DECL_JS_WRAP(OutOfMemoryError)
explicit OutOfMemoryError(const RefPtr<Device>& aParent) OutOfMemoryError(nsIGlobalObject* const aGlobal, const nsAString& aMessage)
: ChildOf<Device>(aParent) {} : Error(aGlobal, aMessage) {}
OutOfMemoryError(nsIGlobalObject* const aGlobal, const nsACString& aMessage)
: Error(aGlobal, aMessage) {}
private: private:
virtual ~OutOfMemoryError(); ~OutOfMemoryError() override = default;
void Cleanup() {}
public:
static already_AddRefed<OutOfMemoryError> Constructor(
const dom::GlobalObject& aGlobal, const nsAString& aString,
ErrorResult& aRv);
}; };
} // namespace webgpu } // namespace webgpu

View file

@ -5,36 +5,16 @@
#include "ValidationError.h" #include "ValidationError.h"
#include "mozilla/dom/WebGPUBinding.h" #include "mozilla/dom/WebGPUBinding.h"
#include "mozilla/ErrorResult.h"
#include "nsIGlobalObject.h"
#include "nsReadableUtils.h"
namespace mozilla::webgpu { namespace mozilla::webgpu {
GPU_IMPL_CYCLE_COLLECTION(ValidationError, mGlobal)
GPU_IMPL_JS_WRAP(ValidationError) GPU_IMPL_JS_WRAP(ValidationError)
ValidationError::ValidationError(nsIGlobalObject* aGlobal,
const nsACString& aMessage)
: mGlobal(aGlobal) {
CopyUTF8toUTF16(aMessage, mMessage);
}
ValidationError::ValidationError(nsIGlobalObject* aGlobal,
const nsAString& aMessage)
: mGlobal(aGlobal), mMessage(aMessage) {}
ValidationError::~ValidationError() = default;
already_AddRefed<ValidationError> ValidationError::Constructor( already_AddRefed<ValidationError> ValidationError::Constructor(
const dom::GlobalObject& aGlobal, const nsAString& aString, const dom::GlobalObject& aGlobal, const nsAString& aString,
ErrorResult& aRv) { ErrorResult& aRv) {
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
if (!global) { MOZ_RELEASE_ASSERT(global);
aRv.ThrowInvalidStateError("aGlobal is not nsIGlobalObject");
return nullptr;
}
return MakeAndAddRef<ValidationError>(global, aString); return MakeAndAddRef<ValidationError>(global, aString);
} }

View file

@ -6,39 +6,32 @@
#ifndef GPU_ValidationError_H_ #ifndef GPU_ValidationError_H_
#define GPU_ValidationError_H_ #define GPU_ValidationError_H_
#include "nsCOMPtr.h" #include "Error.h"
#include "nsString.h"
#include "nsWrapperCache.h"
#include "ObjectModel.h"
namespace mozilla { namespace mozilla {
class ErrorResult; class ErrorResult;
namespace dom { namespace dom {
class GlobalObject; class GlobalObject;
} // namespace dom } // namespace dom
namespace webgpu { namespace webgpu {
class ValidationError final : public nsWrapperCache { class ValidationError final : public Error {
nsCOMPtr<nsIGlobalObject> mGlobal;
nsString mMessage;
public: public:
GPU_DECL_CYCLE_COLLECTION(ValidationError)
GPU_DECL_JS_WRAP(ValidationError) GPU_DECL_JS_WRAP(ValidationError)
ValidationError(nsIGlobalObject* aGlobal, const nsACString& aMessage);
ValidationError(nsIGlobalObject* aGlobal, const nsAString& aMessage); ValidationError(nsIGlobalObject* const aGlobal, const nsAString& aMessage)
: Error(aGlobal, aMessage) {}
ValidationError(nsIGlobalObject* const aGlobal, const nsACString& aMessage)
: Error(aGlobal, aMessage) {}
private: private:
virtual ~ValidationError(); ~ValidationError() override = default;
void Cleanup() {}
public: public:
static already_AddRefed<ValidationError> Constructor( static already_AddRefed<ValidationError> Constructor(
const dom::GlobalObject& aGlobal, const nsAString& aString, const dom::GlobalObject& aGlobal, const nsAString& aString,
ErrorResult& aRv); ErrorResult& aRv);
void GetMessage(nsAString& aMessage) const { aMessage = mMessage; }
nsIGlobalObject* GetParentObject() const { return mGlobal; }
}; };
} // namespace webgpu } // namespace webgpu

View file

@ -1105,8 +1105,7 @@ ipc::IPCResult WebGPUChild::RecvUncapturedError(const Maybe<RawId> aDeviceId,
JsWarning(device->GetOwnerGlobal(), aMessage); JsWarning(device->GetOwnerGlobal(), aMessage);
dom::GPUUncapturedErrorEventInit init; dom::GPUUncapturedErrorEventInit init;
init.mError.SetAsGPUValidationError() = init.mError = new ValidationError(device->GetParentObject(), aMessage);
new ValidationError(device->GetParentObject(), aMessage);
RefPtr<mozilla::dom::GPUUncapturedErrorEvent> event = RefPtr<mozilla::dom::GPUUncapturedErrorEvent> event =
dom::GPUUncapturedErrorEvent::Constructor( dom::GPUUncapturedErrorEvent::Constructor(
device, u"uncapturederror"_ns, init); device, u"uncapturederror"_ns, init);

View file

@ -1149,9 +1149,9 @@ ipc::IPCResult WebGPUParent::RecvDevicePopErrorScope(
case dom::GPUErrorFilter::Out_of_memory: case dom::GPUErrorFilter::Out_of_memory:
ret.resultType = PopErrorScopeResultType::OutOfMemory; ret.resultType = PopErrorScopeResultType::OutOfMemory;
break; break;
// case dom::GPUErrorFilter::Internal: case dom::GPUErrorFilter::Internal:
// ret.resultType = PopErrorScopeResultType::InternalError; ret.resultType = PopErrorScopeResultType::InternalError;
// break; break;
case dom::GPUErrorFilter::EndGuard_: case dom::GPUErrorFilter::EndGuard_:
MOZ_CRASH("Bad GPUErrorFilter"); MOZ_CRASH("Bad GPUErrorFilter");
} }

View file

@ -28,7 +28,9 @@ h_and_cpp = [
"ComputePipeline", "ComputePipeline",
"Device", "Device",
"DeviceLostInfo", "DeviceLostInfo",
"Error",
"Instance", "Instance",
"InternalError",
"ObjectModel", "ObjectModel",
"OutOfMemoryError", "OutOfMemoryError",
"PipelineLayout", "PipelineLayout",

View file

@ -1182,23 +1182,38 @@ partial interface GPUDevice {
[Pref="dom.webgpu.enabled", [Pref="dom.webgpu.enabled",
Exposed=(Window /* ,DedicatedWorker */), SecureContext] Exposed=(Window /* ,DedicatedWorker */), SecureContext]
interface GPUOutOfMemoryError { interface GPUError {
//constructor(); readonly attribute DOMString message;
}; };
[Pref="dom.webgpu.enabled", [Pref="dom.webgpu.enabled",
Exposed=(Window /* ,DedicatedWorker */), SecureContext] Exposed=(Window /* ,DedicatedWorker */), SecureContext]
interface GPUValidationError { interface GPUValidationError
: GPUError {
[Throws] [Throws]
constructor(DOMString message); constructor(DOMString message);
readonly attribute DOMString message;
}; };
typedef (GPUOutOfMemoryError or GPUValidationError) GPUError; [Pref="dom.webgpu.enabled",
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
interface GPUOutOfMemoryError
: GPUError {
[Throws]
constructor(DOMString message);
};
[Pref="dom.webgpu.enabled",
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
interface GPUInternalError
: GPUError {
[Throws]
constructor(DOMString message);
};
enum GPUErrorFilter { enum GPUErrorFilter {
"validation",
"out-of-memory", "out-of-memory",
"validation" "internal",
}; };
typedef [EnforceRange] unsigned long GPUBufferDynamicOffset; typedef [EnforceRange] unsigned long GPUBufferDynamicOffset;