node: Implement GPUDevice.features
Bug: None
Change-Id: I29f2832d22567d357a474e2b9522d3b7f195b3fb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112600
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Kokoro: Ben Clayton <bclayton@google.com>
diff --git a/src/dawn/node/binding/CMakeLists.txt b/src/dawn/node/binding/CMakeLists.txt
index 7907ae7..a4e427b 100644
--- a/src/dawn/node/binding/CMakeLists.txt
+++ b/src/dawn/node/binding/CMakeLists.txt
@@ -59,6 +59,8 @@
"GPUSampler.h"
"GPUShaderModule.cpp"
"GPUShaderModule.h"
+ "GPUSupportedFeatures.cpp"
+ "GPUSupportedFeatures.h"
"GPUSupportedLimits.cpp"
"GPUSupportedLimits.h"
"GPUTexture.cpp"
diff --git a/src/dawn/node/binding/Converter.cpp b/src/dawn/node/binding/Converter.cpp
index f2718bd..524fdca 100644
--- a/src/dawn/node/binding/Converter.cpp
+++ b/src/dawn/node/binding/Converter.cpp
@@ -1622,6 +1622,85 @@
return false;
}
+bool Converter::Convert(wgpu::FeatureName& out, interop::GPUFeatureName in) {
+ switch (in) {
+ case interop::GPUFeatureName::kTextureCompressionBc:
+ out = wgpu::FeatureName::TextureCompressionBC;
+ return true;
+ case interop::GPUFeatureName::kTextureCompressionEtc2:
+ out = wgpu::FeatureName::TextureCompressionETC2;
+ return true;
+ case interop::GPUFeatureName::kTextureCompressionAstc:
+ out = wgpu::FeatureName::TextureCompressionASTC;
+ return true;
+ case interop::GPUFeatureName::kTimestampQuery:
+ out = wgpu::FeatureName::TimestampQuery;
+ return true;
+ case interop::GPUFeatureName::kDepth32FloatStencil8:
+ out = wgpu::FeatureName::Depth32FloatStencil8;
+ return true;
+ case interop::GPUFeatureName::kDepthClipControl:
+ out = wgpu::FeatureName::DepthClipControl;
+ return true;
+ case interop::GPUFeatureName::kIndirectFirstInstance:
+ out = wgpu::FeatureName::IndirectFirstInstance;
+ return true;
+ case interop::GPUFeatureName::kShaderF16:
+ out = wgpu::FeatureName::ShaderF16;
+ return true;
+ case interop::GPUFeatureName::kRg11B10UfloatRenderable:
+ out = wgpu::FeatureName::RG11B10UfloatRenderable;
+ return true;
+ case interop::GPUFeatureName::kBgra8UnormStorage:
+ // TODO(dawn:1123) Add support for these extensions when possible.
+ return false;
+ }
+ return false;
+}
+
+bool Converter::Convert(interop::GPUFeatureName& out, wgpu::FeatureName in) {
+ switch (in) {
+ case wgpu::FeatureName::Depth32FloatStencil8:
+ out = interop::GPUFeatureName::kDepth32FloatStencil8;
+ return true;
+ case wgpu::FeatureName::TimestampQuery:
+ out = interop::GPUFeatureName::kTimestampQuery;
+ return true;
+ case wgpu::FeatureName::TextureCompressionBC:
+ out = interop::GPUFeatureName::kTextureCompressionBc;
+ return true;
+ case wgpu::FeatureName::TextureCompressionETC2:
+ out = interop::GPUFeatureName::kTextureCompressionEtc2;
+ return true;
+ case wgpu::FeatureName::TextureCompressionASTC:
+ out = interop::GPUFeatureName::kTextureCompressionAstc;
+ return true;
+ case wgpu::FeatureName::IndirectFirstInstance:
+ out = interop::GPUFeatureName::kIndirectFirstInstance;
+ return true;
+ case wgpu::FeatureName::DepthClipControl:
+ out = interop::GPUFeatureName::kDepthClipControl;
+ return true;
+ case wgpu::FeatureName::ShaderF16:
+ out = interop::GPUFeatureName::kShaderF16;
+ return true;
+ case wgpu::FeatureName::RG11B10UfloatRenderable:
+ out = interop::GPUFeatureName::kRg11B10UfloatRenderable;
+ return true;
+
+ case wgpu::FeatureName::PipelineStatisticsQuery:
+ case wgpu::FeatureName::DawnShaderFloat16:
+ case wgpu::FeatureName::DawnInternalUsages:
+ case wgpu::FeatureName::DawnMultiPlanarFormats:
+ case wgpu::FeatureName::DawnNative:
+ case wgpu::FeatureName::ChromiumExperimentalDp4a:
+ case wgpu::FeatureName::TimestampQueryInsidePasses:
+ case wgpu::FeatureName::Undefined:
+ return false;
+ }
+ return false;
+}
+
bool Converter::Convert(interop::GPUQueryType& out, wgpu::QueryType in) {
switch (in) {
case wgpu::QueryType::Occlusion:
diff --git a/src/dawn/node/binding/Converter.h b/src/dawn/node/binding/Converter.h
index 564b8a6..16ad9b9 100644
--- a/src/dawn/node/binding/Converter.h
+++ b/src/dawn/node/binding/Converter.h
@@ -270,6 +270,12 @@
[[nodiscard]] bool Convert(interop::GPUQueryType& out, wgpu::QueryType in);
+ // The two conversion methods don't generate an error when false is returned. That
+ // responsibility is left to the caller if it is needed (it isn't always needed, see
+ // https://gpuweb.github.io/gpuweb/#gpu-supportedfeatures)
+ [[nodiscard]] bool Convert(wgpu::FeatureName& out, interop::GPUFeatureName in);
+ [[nodiscard]] bool Convert(interop::GPUFeatureName& out, wgpu::FeatureName in);
+
// std::string to C string
inline bool Convert(const char*& out, const std::string& in) {
out = in.c_str();
diff --git a/src/dawn/node/binding/GPUAdapter.cpp b/src/dawn/node/binding/GPUAdapter.cpp
index c396a6a..73c8c11 100644
--- a/src/dawn/node/binding/GPUAdapter.cpp
+++ b/src/dawn/node/binding/GPUAdapter.cpp
@@ -18,9 +18,11 @@
#include <utility>
#include <vector>
+#include "src/dawn/node/binding/Converter.h"
#include "src/dawn/node/binding/Errors.h"
#include "src/dawn/node/binding/Flags.h"
#include "src/dawn/node/binding/GPUDevice.h"
+#include "src/dawn/node/binding/GPUSupportedFeatures.h"
#include "src/dawn/node/binding/GPUSupportedLimits.h"
namespace {
@@ -88,72 +90,6 @@
namespace wgpu::binding {
-namespace {
-
-////////////////////////////////////////////////////////////////////////////////
-// wgpu::binding::<anon>::Features
-// Implements interop::GPUSupportedFeatures
-////////////////////////////////////////////////////////////////////////////////
-class Features : public interop::GPUSupportedFeatures {
- public:
- explicit Features(std::vector<wgpu::FeatureName> features) {
- for (wgpu::FeatureName feature : features) {
- switch (feature) {
- case wgpu::FeatureName::Depth32FloatStencil8:
- enabled_.emplace(interop::GPUFeatureName::kDepth32FloatStencil8);
- break;
- case wgpu::FeatureName::TimestampQuery:
- enabled_.emplace(interop::GPUFeatureName::kTimestampQuery);
- break;
- case wgpu::FeatureName::TextureCompressionBC:
- enabled_.emplace(interop::GPUFeatureName::kTextureCompressionBc);
- break;
- case wgpu::FeatureName::TextureCompressionETC2:
- enabled_.emplace(interop::GPUFeatureName::kTextureCompressionEtc2);
- break;
- case wgpu::FeatureName::TextureCompressionASTC:
- enabled_.emplace(interop::GPUFeatureName::kTextureCompressionAstc);
- break;
- case wgpu::FeatureName::IndirectFirstInstance:
- enabled_.emplace(interop::GPUFeatureName::kIndirectFirstInstance);
- break;
- case wgpu::FeatureName::DepthClipControl:
- enabled_.emplace(interop::GPUFeatureName::kDepthClipControl);
- break;
- default:
- break;
- }
- }
- // TODO(dawn:1123) add support for these extensions when possible.
- // wgpu::interop::GPUFeatureName::kShaderF16
- // wgpu::interop::GPUFeatureName::kBgra8UnormStorage
- }
-
- bool has(interop::GPUFeatureName feature) { return enabled_.count(feature) != 0; }
-
- // interop::GPUSupportedFeatures compliance
- bool has(Napi::Env, std::string name) override {
- interop::GPUFeatureName feature;
- if (interop::Converter<interop::GPUFeatureName>::FromString(name, feature)) {
- return has(feature);
- }
- return false;
- }
- std::vector<std::string> keys(Napi::Env) override {
- std::vector<std::string> out;
- out.reserve(enabled_.size());
- for (auto feature : enabled_) {
- out.push_back(interop::Converter<interop::GPUFeatureName>::ToString(feature));
- }
- return out;
- }
-
- private:
- std::unordered_set<interop::GPUFeatureName> enabled_;
-};
-
-} // namespace
-
////////////////////////////////////////////////////////////////////////////////
// wgpu::bindings::GPUAdapter
// TODO(crbug.com/dawn/1133): This is a stub implementation. Properly implement.
@@ -167,7 +103,8 @@
size_t count = adapter.EnumerateFeatures(nullptr);
std::vector<wgpu::FeatureName> features(count);
adapter.EnumerateFeatures(&features[0]);
- return interop::GPUSupportedFeatures::Create<Features>(env, std::move(features));
+ return interop::GPUSupportedFeatures::Create<GPUSupportedFeatures>(env, env,
+ std::move(features));
}
interop::Interface<interop::GPUSupportedLimits> GPUAdapter::getLimits(Napi::Env env) {
@@ -195,34 +132,19 @@
wgpu::DeviceDescriptor desc{}; // TODO(crbug.com/dawn/1133): Fill in.
interop::Promise<interop::Interface<interop::GPUDevice>> promise(env, PROMISE_INFO);
+ Converter conv(env);
std::vector<wgpu::FeatureName> requiredFeatures;
- // See src/dawn/native/Features.cpp for enum <-> string mappings.
for (auto required : descriptor.requiredFeatures) {
- switch (required) {
- case interop::GPUFeatureName::kTextureCompressionBc:
- requiredFeatures.emplace_back(wgpu::FeatureName::TextureCompressionBC);
- continue;
- case interop::GPUFeatureName::kTextureCompressionEtc2:
- requiredFeatures.emplace_back(wgpu::FeatureName::TextureCompressionETC2);
- continue;
- case interop::GPUFeatureName::kTextureCompressionAstc:
- requiredFeatures.emplace_back(wgpu::FeatureName::TextureCompressionASTC);
- continue;
- case interop::GPUFeatureName::kTimestampQuery:
- requiredFeatures.emplace_back(wgpu::FeatureName::TimestampQuery);
- continue;
- case interop::GPUFeatureName::kDepth32FloatStencil8:
- requiredFeatures.emplace_back(wgpu::FeatureName::Depth32FloatStencil8);
- continue;
- case interop::GPUFeatureName::kDepthClipControl:
- case interop::GPUFeatureName::kShaderF16:
- case interop::GPUFeatureName::kIndirectFirstInstance:
- case interop::GPUFeatureName::kBgra8UnormStorage:
- case interop::GPUFeatureName::kRg11B10UfloatRenderable:
- // TODO(dawn:1123) Add support for these extensions when possible.
- continue;
+ wgpu::FeatureName feature = wgpu::FeatureName::Undefined;
+
+ // requiredFeatures is a "sequence<GPUFeatureName>" so a Javascript exception should be
+ // thrown if one of the strings isn't one of the known features.
+ if (!conv(feature, required)) {
+ Napi::Error::New(env, "invalid value for GPUFeatureName").ThrowAsJavaScriptException();
+ return promise;
}
- UNIMPLEMENTED("required: ", required);
+
+ requiredFeatures.emplace_back(feature);
}
wgpu::RequiredLimits limits;
diff --git a/src/dawn/node/binding/GPUDevice.cpp b/src/dawn/node/binding/GPUDevice.cpp
index 5aab3eb..3623621 100644
--- a/src/dawn/node/binding/GPUDevice.cpp
+++ b/src/dawn/node/binding/GPUDevice.cpp
@@ -33,6 +33,7 @@
#include "src/dawn/node/binding/GPURenderPipeline.h"
#include "src/dawn/node/binding/GPUSampler.h"
#include "src/dawn/node/binding/GPUShaderModule.h"
+#include "src/dawn/node/binding/GPUSupportedFeatures.h"
#include "src/dawn/node/binding/GPUSupportedLimits.h"
#include "src/dawn/node/binding/GPUTexture.h"
#include "src/dawn/node/utils/Debug.h"
@@ -178,12 +179,11 @@
}
interop::Interface<interop::GPUSupportedFeatures> GPUDevice::getFeatures(Napi::Env env) {
- class Features : public interop::GPUSupportedFeatures {
- public:
- bool has(Napi::Env, std::string feature) override { UNIMPLEMENTED(); }
- std::vector<std::string> keys(Napi::Env) override { UNIMPLEMENTED(); }
- };
- return interop::GPUSupportedFeatures::Create<Features>(env);
+ size_t count = device_.EnumerateFeatures(nullptr);
+ std::vector<wgpu::FeatureName> features(count);
+ device_.EnumerateFeatures(&features[0]);
+ return interop::GPUSupportedFeatures::Create<GPUSupportedFeatures>(env, env,
+ std::move(features));
}
interop::Interface<interop::GPUSupportedLimits> GPUDevice::getLimits(Napi::Env env) {
diff --git a/src/dawn/node/binding/GPUSupportedFeatures.cpp b/src/dawn/node/binding/GPUSupportedFeatures.cpp
new file mode 100644
index 0000000..cebce06
--- /dev/null
+++ b/src/dawn/node/binding/GPUSupportedFeatures.cpp
@@ -0,0 +1,56 @@
+// Copyright 2022 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/dawn/node/binding/GPUSupportedFeatures.h"
+
+#include "src/dawn/node/binding/Converter.h"
+
+namespace wgpu::binding {
+
+////////////////////////////////////////////////////////////////////////////////
+// wgpu::bindings::GPUSupportedFeatures
+////////////////////////////////////////////////////////////////////////////////
+
+GPUSupportedFeatures::GPUSupportedFeatures(Napi::Env env, std::vector<wgpu::FeatureName> features) {
+ Converter conv(env);
+
+ // Add all known GPUFeatureNames that are known by dawn.node and skip the other ones are they
+ // may be native-only extension, Dawn-specific or other special cases.
+ for (wgpu::FeatureName feature : features) {
+ interop::GPUFeatureName gpuFeature;
+ if (conv(gpuFeature, feature)) {
+ enabled_.emplace(gpuFeature);
+ }
+ }
+}
+
+bool GPUSupportedFeatures::has(Napi::Env, std::string name) {
+ interop::GPUFeatureName feature;
+ if (!interop::Converter<interop::GPUFeatureName>::FromString(name, feature)) {
+ return false;
+ }
+
+ return enabled_.count(feature);
+}
+
+std::vector<std::string> GPUSupportedFeatures::keys(Napi::Env) {
+ std::vector<std::string> out;
+ out.reserve(enabled_.size());
+ for (auto feature : enabled_) {
+ out.push_back(interop::Converter<interop::GPUFeatureName>::ToString(feature));
+ }
+ return out;
+}
+
+} // namespace wgpu::binding
diff --git a/src/dawn/node/binding/GPUSupportedFeatures.h b/src/dawn/node/binding/GPUSupportedFeatures.h
new file mode 100644
index 0000000..922cefa
--- /dev/null
+++ b/src/dawn/node/binding/GPUSupportedFeatures.h
@@ -0,0 +1,44 @@
+// Copyright 2022 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_DAWN_NODE_BINDING_GPUSUPPORTEDFEATURES_H_
+#define SRC_DAWN_NODE_BINDING_GPUSUPPORTEDFEATURES_H_
+
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include "dawn/webgpu_cpp.h"
+
+#include "src/dawn/node/interop/Napi.h"
+#include "src/dawn/node/interop/WebGPU.h"
+
+namespace wgpu::binding {
+
+// GPUSupportedLFeatures is an implementation of interop::GPUSupportedFeatures.
+class GPUSupportedFeatures final : public interop::GPUSupportedFeatures {
+ public:
+ GPUSupportedFeatures(Napi::Env env, std::vector<wgpu::FeatureName> features);
+
+ // interop::GPUSupportedFeatures interface compliance
+ bool has(Napi::Env, std::string name) override;
+ std::vector<std::string> keys(Napi::Env) override;
+
+ private:
+ std::unordered_set<interop::GPUFeatureName> enabled_;
+};
+
+} // namespace wgpu::binding
+
+#endif // SRC_DAWN_NODE_BINDING_GPUSUPPORTEDFEATURES_H_