dawn_node: add support for input flags

This change replaces the ".gpu" export with ".create()" function that
accepts an array of flags. These will be used by cmdline.ts to set flags
such as what dawn backend to use. We currenly environment variables, but
this will be more flexible.

Bug: dawn:1163
Change-Id: If2fb35811cac45e16121fbd828f997ef3d795f36
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/66960
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
Antonio Maiorano 2021-10-21 19:34:34 +00:00 committed by Dawn LUCI CQ
parent 7dc906a4c9
commit e772615b53
7 changed files with 106 additions and 9 deletions

View File

@ -13,10 +13,41 @@
// limitations under the License. // limitations under the License.
#include "dawn/dawn_proc.h" #include "dawn/dawn_proc.h"
#include "src/dawn_node/binding/Flags.h"
#include "src/dawn_node/binding/GPU.h" #include "src/dawn_node/binding/GPU.h"
namespace {
Napi::Value CreateGPU(const Napi::CallbackInfo& info) {
const auto& env = info.Env();
std::tuple<std::vector<std::string>> args;
auto res = wgpu::interop::FromJS(info, args);
if (res != wgpu::interop::Success) {
Napi::Error::New(env, res.error).ThrowAsJavaScriptException();
return env.Undefined();
}
wgpu::binding::Flags flags;
// Parse out the key=value flags out of the input args array
for (const auto& arg : std::get<0>(args)) {
const size_t sep_index = arg.find("=");
if (sep_index == std::string::npos) {
Napi::Error::New(env, "Flags expected argument format is <key>=<value>")
.ThrowAsJavaScriptException();
return env.Undefined();
}
flags.Set(arg.substr(0, sep_index), arg.substr(sep_index + 1));
}
// Construct a wgpu::interop::GPU interface, implemented by wgpu::bindings::GPU.
return wgpu::interop::GPU::Create<wgpu::binding::GPU>(env, std::move(flags));
}
} // namespace
// Initialize() initializes the Dawn node module, registering all the WebGPU // Initialize() initializes the Dawn node module, registering all the WebGPU
// types into the global object, and adding the 'gpu' property on the exported // types into the global object, and adding the 'create' function on the exported
// object. // object.
Napi::Object Initialize(Napi::Env env, Napi::Object exports) { Napi::Object Initialize(Napi::Env env, Napi::Object exports) {
// Begin by setting the Dawn procedure function pointers. // Begin by setting the Dawn procedure function pointers.
@ -25,10 +56,9 @@ Napi::Object Initialize(Napi::Env env, Napi::Object exports) {
// Register all the interop types // Register all the interop types
wgpu::interop::Initialize(env); wgpu::interop::Initialize(env);
// Construct a wgpu::interop::GPU interface, implemented by // Export function that creates and returns the wgpu::interop::GPU interface
// wgpu::bindings::GPU. This will be the 'gpu' field of exported object. exports.Set(Napi::String::New(env, "create"), Napi::Function::New<CreateGPU>(env));
auto gpu = wgpu::interop::GPU::Create<wgpu::binding::GPU>(env);
exports.Set(Napi::String::New(env, "gpu"), gpu);
return exports; return exports;
} }

View File

@ -19,6 +19,8 @@ add_library(dawn_node_binding STATIC
"Converter.h" "Converter.h"
"Errors.cpp" "Errors.cpp"
"Errors.h" "Errors.h"
"Flags.cpp"
"Flags.h"
"GPU.cpp" "GPU.cpp"
"GPU.h" "GPU.h"
"GPUAdapter.cpp" "GPUAdapter.cpp"

View File

@ -0,0 +1,29 @@
// Copyright 2021 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/Flags.h"
namespace wgpu { namespace binding {
void Flags::Set(const std::string& key, const std::string& value) {
flags_[key] = value;
}
std::optional<std::string> Flags::Get(const std::string& key) const {
auto iter = flags_.find(key);
if (iter != flags_.end()) {
return iter->second;
}
return {};
}
}} // namespace wgpu::binding

View File

@ -0,0 +1,35 @@
// Copyright 2021 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 DAWN_NODE_BINDING_FLAGS_H_
#define DAWN_NODE_BINDING_FLAGS_H_
#include <optional>
#include <string>
#include <unordered_map>
namespace wgpu { namespace binding {
// Flags maintains a key-value mapping of input flags passed into the module's create()
// function, used to configure dawn_node.
class Flags {
public:
void Set(const std::string& key, const std::string& value);
std::optional<std::string> Get(const std::string& key) const;
private:
std::unordered_map<std::string, std::string> flags_;
};
}} // namespace wgpu::binding
#endif // DAWN_NODE_BINDING_FLAGS_H_

View File

@ -44,7 +44,7 @@ namespace wgpu { namespace binding {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// wgpu::bindings::GPU // wgpu::bindings::GPU
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
GPU::GPU() { GPU::GPU(Flags flags) : flags_(std::move(flags)) {
// TODO: Disable in 'release' // TODO: Disable in 'release'
instance_.EnableBackendValidation(true); instance_.EnableBackendValidation(true);
instance_.SetBackendValidationLevel(dawn_native::BackendValidationLevel::Full); instance_.SetBackendValidationLevel(dawn_native::BackendValidationLevel::Full);

View File

@ -18,14 +18,14 @@
#include "dawn/webgpu_cpp.h" #include "dawn/webgpu_cpp.h"
#include "dawn_native/DawnNative.h" #include "dawn_native/DawnNative.h"
#include "napi.h" #include "napi.h"
#include "src/dawn_node/binding/Flags.h"
#include "src/dawn_node/interop/WebGPU.h" #include "src/dawn_node/interop/WebGPU.h"
namespace wgpu { namespace binding { namespace wgpu { namespace binding {
// GPU is an implementation of interop::GPU that wraps a dawn_native::Instance. // GPU is an implementation of interop::GPU that wraps a dawn_native::Instance.
class GPU final : public interop::GPU { class GPU final : public interop::GPU {
public: public:
GPU(); GPU(Flags flags);
// interop::GPU interface compliance // interop::GPU interface compliance
interop::Promise<std::optional<interop::Interface<interop::GPUAdapter>>> requestAdapter( interop::Promise<std::optional<interop::Interface<interop::GPUAdapter>>> requestAdapter(
@ -33,6 +33,7 @@ namespace wgpu { namespace binding {
interop::GPURequestAdapterOptions options) override; interop::GPURequestAdapterOptions options) override;
private: private:
const Flags flags_;
dawn_native::Instance instance_; dawn_native::Instance instance_;
}; };

View File

@ -492,7 +492,7 @@ namespace wgpu { namespace interop {
auto arr = value.As<Napi::Array>(); auto arr = value.As<Napi::Array>();
std::vector<T> vec(arr.Length()); std::vector<T> vec(arr.Length());
for (size_t i = 0; i < vec.size(); i++) { for (size_t i = 0; i < vec.size(); i++) {
auto res = Converter<T>::FromJS(env, arr[i], vec[i]); auto res = Converter<T>::FromJS(env, arr[static_cast<uint32_t>(i)], vec[i]);
if (!res) { if (!res) {
return res.Append("for array element ", i); return res.Append("for array element ", i);
} }