dawn_node: Implement requesting limits

And reject the device creation promise with an error that looks like an
OperationError to make the CTS happy.

Bug: dawn:1242
Change-Id: I43ec3ebc030cb4178520c9174e164a42b94f6bf8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/85060
Reviewed-by: Brandon Jones <bajones@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2022-03-29 07:45:03 +00:00 committed by Dawn LUCI CQ
parent 21163f1ade
commit fc1a2ae904
3 changed files with 135 additions and 116 deletions

View File

@ -49,7 +49,7 @@ namespace wgpu::binding {
static Napi::Error New(Napi::Env env, static Napi::Error New(Napi::Env env,
std::string name, std::string name,
std::string message = {}, std::string message,
unsigned short code = 0) { unsigned short code = 0) {
auto err = Napi::Error::New(env); auto err = Napi::Error::New(env);
err.Set("name", name); err.Set("name", name);
@ -60,120 +60,120 @@ namespace wgpu::binding {
} // namespace } // namespace
Napi::Error Errors::HierarchyRequestError(Napi::Env env) { Napi::Error Errors::HierarchyRequestError(Napi::Env env, std::string message) {
return New(env, kHierarchyRequestError); return New(env, kHierarchyRequestError, message);
} }
Napi::Error Errors::WrongDocumentError(Napi::Env env) { Napi::Error Errors::WrongDocumentError(Napi::Env env, std::string message) {
return New(env, kWrongDocumentError); return New(env, kWrongDocumentError, message);
} }
Napi::Error Errors::InvalidCharacterError(Napi::Env env) { Napi::Error Errors::InvalidCharacterError(Napi::Env env, std::string message) {
return New(env, kInvalidCharacterError); return New(env, kInvalidCharacterError, message);
} }
Napi::Error Errors::NoModificationAllowedError(Napi::Env env) { Napi::Error Errors::NoModificationAllowedError(Napi::Env env, std::string message) {
return New(env, kNoModificationAllowedError); return New(env, kNoModificationAllowedError, message);
} }
Napi::Error Errors::NotFoundError(Napi::Env env) { Napi::Error Errors::NotFoundError(Napi::Env env, std::string message) {
return New(env, kNotFoundError); return New(env, kNotFoundError, message);
} }
Napi::Error Errors::NotSupportedError(Napi::Env env) { Napi::Error Errors::NotSupportedError(Napi::Env env, std::string message) {
return New(env, kNotSupportedError); return New(env, kNotSupportedError, message);
} }
Napi::Error Errors::InUseAttributeError(Napi::Env env) { Napi::Error Errors::InUseAttributeError(Napi::Env env, std::string message) {
return New(env, kInUseAttributeError); return New(env, kInUseAttributeError, message);
} }
Napi::Error Errors::InvalidStateError(Napi::Env env) { Napi::Error Errors::InvalidStateError(Napi::Env env, std::string message) {
return New(env, kInvalidStateError); return New(env, kInvalidStateError, message);
} }
Napi::Error Errors::SyntaxError(Napi::Env env) { Napi::Error Errors::SyntaxError(Napi::Env env, std::string message) {
return New(env, kSyntaxError); return New(env, kSyntaxError, message);
} }
Napi::Error Errors::InvalidModificationError(Napi::Env env) { Napi::Error Errors::InvalidModificationError(Napi::Env env, std::string message) {
return New(env, kInvalidModificationError); return New(env, kInvalidModificationError, message);
} }
Napi::Error Errors::NamespaceError(Napi::Env env) { Napi::Error Errors::NamespaceError(Napi::Env env, std::string message) {
return New(env, kNamespaceError); return New(env, kNamespaceError, message);
} }
Napi::Error Errors::SecurityError(Napi::Env env) { Napi::Error Errors::SecurityError(Napi::Env env, std::string message) {
return New(env, kSecurityError); return New(env, kSecurityError, message);
} }
Napi::Error Errors::NetworkError(Napi::Env env) { Napi::Error Errors::NetworkError(Napi::Env env, std::string message) {
return New(env, kNetworkError); return New(env, kNetworkError, message);
} }
Napi::Error Errors::AbortError(Napi::Env env) { Napi::Error Errors::AbortError(Napi::Env env, std::string message) {
return New(env, kAbortError); return New(env, kAbortError, message);
} }
Napi::Error Errors::URLMismatchError(Napi::Env env) { Napi::Error Errors::URLMismatchError(Napi::Env env, std::string message) {
return New(env, kURLMismatchError); return New(env, kURLMismatchError, message);
} }
Napi::Error Errors::QuotaExceededError(Napi::Env env) { Napi::Error Errors::QuotaExceededError(Napi::Env env, std::string message) {
return New(env, kQuotaExceededError); return New(env, kQuotaExceededError, message);
} }
Napi::Error Errors::TimeoutError(Napi::Env env) { Napi::Error Errors::TimeoutError(Napi::Env env, std::string message) {
return New(env, kTimeoutError); return New(env, kTimeoutError, message);
} }
Napi::Error Errors::InvalidNodeTypeError(Napi::Env env) { Napi::Error Errors::InvalidNodeTypeError(Napi::Env env, std::string message) {
return New(env, kInvalidNodeTypeError); return New(env, kInvalidNodeTypeError, message);
} }
Napi::Error Errors::DataCloneError(Napi::Env env) { Napi::Error Errors::DataCloneError(Napi::Env env, std::string message) {
return New(env, kDataCloneError); return New(env, kDataCloneError, message);
} }
Napi::Error Errors::EncodingError(Napi::Env env) { Napi::Error Errors::EncodingError(Napi::Env env, std::string message) {
return New(env, kEncodingError); return New(env, kEncodingError, message);
} }
Napi::Error Errors::NotReadableError(Napi::Env env) { Napi::Error Errors::NotReadableError(Napi::Env env, std::string message) {
return New(env, kNotReadableError); return New(env, kNotReadableError, message);
} }
Napi::Error Errors::UnknownError(Napi::Env env) { Napi::Error Errors::UnknownError(Napi::Env env, std::string message) {
return New(env, kUnknownError); return New(env, kUnknownError, message);
} }
Napi::Error Errors::ConstraintError(Napi::Env env) { Napi::Error Errors::ConstraintError(Napi::Env env, std::string message) {
return New(env, kConstraintError); return New(env, kConstraintError, message);
} }
Napi::Error Errors::DataError(Napi::Env env) { Napi::Error Errors::DataError(Napi::Env env, std::string message) {
return New(env, kDataError); return New(env, kDataError, message);
} }
Napi::Error Errors::TransactionInactiveError(Napi::Env env) { Napi::Error Errors::TransactionInactiveError(Napi::Env env, std::string message) {
return New(env, kTransactionInactiveError); return New(env, kTransactionInactiveError, message);
} }
Napi::Error Errors::ReadOnlyError(Napi::Env env) { Napi::Error Errors::ReadOnlyError(Napi::Env env, std::string message) {
return New(env, kReadOnlyError); return New(env, kReadOnlyError, message);
} }
Napi::Error Errors::VersionError(Napi::Env env) { Napi::Error Errors::VersionError(Napi::Env env, std::string message) {
return New(env, kVersionError); return New(env, kVersionError, message);
} }
Napi::Error Errors::OperationError(Napi::Env env) { Napi::Error Errors::OperationError(Napi::Env env, std::string message) {
return New(env, kOperationError); return New(env, kOperationError, message);
} }
Napi::Error Errors::NotAllowedError(Napi::Env env) { Napi::Error Errors::NotAllowedError(Napi::Env env, std::string message) {
return New(env, kNotAllowedError); return New(env, kNotAllowedError, message);
} }
} // namespace wgpu::binding } // namespace wgpu::binding

View File

@ -24,35 +24,35 @@ namespace wgpu::binding {
// https://heycam.github.io/webidl/#idl-DOMException-error-names // https://heycam.github.io/webidl/#idl-DOMException-error-names
class Errors { class Errors {
public: public:
static Napi::Error HierarchyRequestError(Napi::Env); static Napi::Error HierarchyRequestError(Napi::Env, std::string message = {});
static Napi::Error WrongDocumentError(Napi::Env); static Napi::Error WrongDocumentError(Napi::Env, std::string message = {});
static Napi::Error InvalidCharacterError(Napi::Env); static Napi::Error InvalidCharacterError(Napi::Env, std::string message = {});
static Napi::Error NoModificationAllowedError(Napi::Env); static Napi::Error NoModificationAllowedError(Napi::Env, std::string message = {});
static Napi::Error NotFoundError(Napi::Env); static Napi::Error NotFoundError(Napi::Env, std::string message = {});
static Napi::Error NotSupportedError(Napi::Env); static Napi::Error NotSupportedError(Napi::Env, std::string message = {});
static Napi::Error InUseAttributeError(Napi::Env); static Napi::Error InUseAttributeError(Napi::Env, std::string message = {});
static Napi::Error InvalidStateError(Napi::Env); static Napi::Error InvalidStateError(Napi::Env, std::string message = {});
static Napi::Error SyntaxError(Napi::Env); static Napi::Error SyntaxError(Napi::Env, std::string message = {});
static Napi::Error InvalidModificationError(Napi::Env); static Napi::Error InvalidModificationError(Napi::Env, std::string message = {});
static Napi::Error NamespaceError(Napi::Env); static Napi::Error NamespaceError(Napi::Env, std::string message = {});
static Napi::Error SecurityError(Napi::Env); static Napi::Error SecurityError(Napi::Env, std::string message = {});
static Napi::Error NetworkError(Napi::Env); static Napi::Error NetworkError(Napi::Env, std::string message = {});
static Napi::Error AbortError(Napi::Env); static Napi::Error AbortError(Napi::Env, std::string message = {});
static Napi::Error URLMismatchError(Napi::Env); static Napi::Error URLMismatchError(Napi::Env, std::string message = {});
static Napi::Error QuotaExceededError(Napi::Env); static Napi::Error QuotaExceededError(Napi::Env, std::string message = {});
static Napi::Error TimeoutError(Napi::Env); static Napi::Error TimeoutError(Napi::Env, std::string message = {});
static Napi::Error InvalidNodeTypeError(Napi::Env); static Napi::Error InvalidNodeTypeError(Napi::Env, std::string message = {});
static Napi::Error DataCloneError(Napi::Env); static Napi::Error DataCloneError(Napi::Env, std::string message = {});
static Napi::Error EncodingError(Napi::Env); static Napi::Error EncodingError(Napi::Env, std::string message = {});
static Napi::Error NotReadableError(Napi::Env); static Napi::Error NotReadableError(Napi::Env, std::string message = {});
static Napi::Error UnknownError(Napi::Env); static Napi::Error UnknownError(Napi::Env, std::string message = {});
static Napi::Error ConstraintError(Napi::Env); static Napi::Error ConstraintError(Napi::Env, std::string message = {});
static Napi::Error DataError(Napi::Env); static Napi::Error DataError(Napi::Env, std::string message = {});
static Napi::Error TransactionInactiveError(Napi::Env); static Napi::Error TransactionInactiveError(Napi::Env, std::string message = {});
static Napi::Error ReadOnlyError(Napi::Env); static Napi::Error ReadOnlyError(Napi::Env, std::string message = {});
static Napi::Error VersionError(Napi::Env); static Napi::Error VersionError(Napi::Env, std::string message = {});
static Napi::Error OperationError(Napi::Env); static Napi::Error OperationError(Napi::Env, std::string message = {});
static Napi::Error NotAllowedError(Napi::Env); static Napi::Error NotAllowedError(Napi::Env, std::string message = {});
}; };
} // namespace wgpu::binding } // namespace wgpu::binding

View File

@ -16,6 +16,7 @@
#include <unordered_set> #include <unordered_set>
#include "src/dawn/node/binding/Errors.h"
#include "src/dawn/node/binding/Flags.h" #include "src/dawn/node/binding/Flags.h"
#include "src/dawn/node/binding/GPUDevice.h" #include "src/dawn/node/binding/GPUDevice.h"
#include "src/dawn/node/binding/GPUSupportedLimits.h" #include "src/dawn/node/binding/GPUSupportedLimits.h"
@ -48,6 +49,34 @@ namespace {
} }
} // namespace } // namespace
#define FOR_EACH_LIMIT(X) \
X(maxTextureDimension1D) \
X(maxTextureDimension2D) \
X(maxTextureDimension3D) \
X(maxTextureArrayLayers) \
X(maxBindGroups) \
X(maxDynamicUniformBuffersPerPipelineLayout) \
X(maxDynamicStorageBuffersPerPipelineLayout) \
X(maxSampledTexturesPerShaderStage) \
X(maxSamplersPerShaderStage) \
X(maxStorageBuffersPerShaderStage) \
X(maxStorageTexturesPerShaderStage) \
X(maxUniformBuffersPerShaderStage) \
X(maxUniformBufferBindingSize) \
X(maxStorageBufferBindingSize) \
X(minUniformBufferOffsetAlignment) \
X(minStorageBufferOffsetAlignment) \
X(maxVertexBuffers) \
X(maxVertexAttributes) \
X(maxVertexBufferArrayStride) \
X(maxInterStageShaderComponents) \
X(maxComputeWorkgroupStorageSize) \
X(maxComputeInvocationsPerWorkgroup) \
X(maxComputeWorkgroupSizeX) \
X(maxComputeWorkgroupSizeY) \
X(maxComputeWorkgroupSizeZ) \
X(maxComputeWorkgroupsPerDimension)
namespace wgpu::binding { namespace wgpu::binding {
namespace { namespace {
@ -138,33 +167,8 @@ namespace wgpu::binding {
wgpu::SupportedLimits wgpuLimits{}; wgpu::SupportedLimits wgpuLimits{};
#define COPY_LIMIT(LIMIT) wgpuLimits.limits.LIMIT = limits.limits.LIMIT #define COPY_LIMIT(LIMIT) wgpuLimits.limits.LIMIT = limits.limits.LIMIT;
COPY_LIMIT(maxTextureDimension1D); FOR_EACH_LIMIT(COPY_LIMIT)
COPY_LIMIT(maxTextureDimension2D);
COPY_LIMIT(maxTextureDimension3D);
COPY_LIMIT(maxTextureArrayLayers);
COPY_LIMIT(maxBindGroups);
COPY_LIMIT(maxDynamicUniformBuffersPerPipelineLayout);
COPY_LIMIT(maxDynamicStorageBuffersPerPipelineLayout);
COPY_LIMIT(maxSampledTexturesPerShaderStage);
COPY_LIMIT(maxSamplersPerShaderStage);
COPY_LIMIT(maxStorageBuffersPerShaderStage);
COPY_LIMIT(maxStorageTexturesPerShaderStage);
COPY_LIMIT(maxUniformBuffersPerShaderStage);
COPY_LIMIT(maxUniformBufferBindingSize);
COPY_LIMIT(maxStorageBufferBindingSize);
COPY_LIMIT(minUniformBufferOffsetAlignment);
COPY_LIMIT(minStorageBufferOffsetAlignment);
COPY_LIMIT(maxVertexBuffers);
COPY_LIMIT(maxVertexAttributes);
COPY_LIMIT(maxVertexBufferArrayStride);
COPY_LIMIT(maxInterStageShaderComponents);
COPY_LIMIT(maxComputeWorkgroupStorageSize);
COPY_LIMIT(maxComputeInvocationsPerWorkgroup);
COPY_LIMIT(maxComputeWorkgroupSizeX);
COPY_LIMIT(maxComputeWorkgroupSizeY);
COPY_LIMIT(maxComputeWorkgroupSizeZ);
COPY_LIMIT(maxComputeWorkgroupsPerDimension);
#undef COPY_LIMIT #undef COPY_LIMIT
return interop::GPUSupportedLimits::Create<GPUSupportedLimits>(env, wgpuLimits); return interop::GPUSupportedLimits::Create<GPUSupportedLimits>(env, wgpuLimits);
@ -210,6 +214,20 @@ namespace wgpu::binding {
UNIMPLEMENTED("required: ", required); UNIMPLEMENTED("required: ", required);
} }
wgpu::RequiredLimits limits;
#define COPY_LIMIT(LIMIT) \
if (descriptor.requiredLimits.count(#LIMIT)) { \
limits.limits.LIMIT = descriptor.requiredLimits[#LIMIT]; \
descriptor.requiredLimits.erase(#LIMIT); \
}
FOR_EACH_LIMIT(COPY_LIMIT)
#undef COPY_LIMIT
for (auto [key, _] : descriptor.requiredLimits) {
promise.Reject(binding::Errors::OperationError(env, "Unknown limit \"" + key + "\""));
return promise;
}
// Propogate enabled/disabled dawn features // Propogate enabled/disabled dawn features
// Note: DawnDeviceTogglesDescriptor::forceEnabledToggles and forceDisabledToggles are // Note: DawnDeviceTogglesDescriptor::forceEnabledToggles and forceDisabledToggles are
// vectors of 'const char*', so we make sure the parsed strings survive the CreateDevice() // vectors of 'const char*', so we make sure the parsed strings survive the CreateDevice()
@ -233,6 +251,7 @@ namespace wgpu::binding {
desc.requiredFeaturesCount = requiredFeatures.size(); desc.requiredFeaturesCount = requiredFeatures.size();
desc.requiredFeatures = requiredFeatures.data(); desc.requiredFeatures = requiredFeatures.data();
desc.requiredLimits = &limits;
DawnTogglesDeviceDescriptor togglesDesc = {}; DawnTogglesDeviceDescriptor togglesDesc = {};
desc.nextInChain = &togglesDesc; desc.nextInChain = &togglesDesc;
@ -245,7 +264,7 @@ namespace wgpu::binding {
if (wgpu_device) { if (wgpu_device) {
promise.Resolve(interop::GPUDevice::Create<GPUDevice>(env, env, wgpu_device)); promise.Resolve(interop::GPUDevice::Create<GPUDevice>(env, env, wgpu_device));
} else { } else {
Napi::Error::New(env, "failed to create device").ThrowAsJavaScriptException(); promise.Reject(binding::Errors::OperationError(env, "failed to create device"));
} }
return promise; return promise;
} }