dawn_node: Begin implementing GPUSupportedFeatures

Requires setlike interface interop.

Bug: dawn:1123
Bug: dawn:1143
Change-Id: I1451f72b32b99858be871db99888f86872b53fd0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65245
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Ben Clayton 2021-09-30 07:17:33 +00:00 committed by Dawn LUCI CQ
parent 3e122818a2
commit 7ed0624337
5 changed files with 128 additions and 6 deletions

View File

@ -19,6 +19,51 @@
namespace wgpu { namespace binding { namespace wgpu { namespace binding {
namespace {
////////////////////////////////////////////////////////////////////////////////
// wgpu::binding::<anon>::Features
// Implements interop::GPUSupportedFeatures
////////////////////////////////////////////////////////////////////////////////
class Features : public interop::GPUSupportedFeatures {
public:
Features(WGPUDeviceProperties properties) : properties_(std::move(properties)) {
}
bool has(interop::GPUFeatureName feature) {
switch (feature) {
case interop::GPUFeatureName::kDepthClamping:
return properties_.depthClamping;
case interop::GPUFeatureName::kDepth24UnormStencil8:
return false; // TODO(crbug.com/dawn/1130)
case interop::GPUFeatureName::kDepth32FloatStencil8:
return false; // TODO(crbug.com/dawn/1130)
case interop::GPUFeatureName::kPipelineStatisticsQuery:
return properties_.pipelineStatisticsQuery;
case interop::GPUFeatureName::kTextureCompressionBc:
return properties_.textureCompressionBC;
case interop::GPUFeatureName::kTimestampQuery:
return properties_.timestampQuery;
}
UNIMPLEMENTED("feature: ", feature);
return false;
}
// 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;
}
private:
WGPUDeviceProperties properties_;
};
} // namespace
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// wgpu::bindings::GPUAdapter // wgpu::bindings::GPUAdapter
// TODO(crbug.com/dawn/1133): This is a stub implementation. Properly implement. // TODO(crbug.com/dawn/1133): This is a stub implementation. Properly implement.
@ -31,8 +76,8 @@ namespace wgpu { namespace binding {
} }
interop::Interface<interop::GPUSupportedFeatures> GPUAdapter::getFeatures(Napi::Env env) { interop::Interface<interop::GPUSupportedFeatures> GPUAdapter::getFeatures(Napi::Env env) {
class Features : public interop::GPUSupportedFeatures {}; return interop::GPUSupportedFeatures::Create<Features>(env,
return interop::GPUSupportedFeatures::Create<Features>(env); adapter_.GetAdapterProperties());
} }
interop::Interface<interop::GPUSupportedLimits> GPUAdapter::getLimits(Napi::Env env) { interop::Interface<interop::GPUSupportedLimits> GPUAdapter::getLimits(Napi::Env env) {
@ -49,6 +94,30 @@ namespace wgpu { namespace binding {
dawn_native::DeviceDescriptor desc{}; // TODO(crbug.com/dawn/1133): Fill in. dawn_native::DeviceDescriptor desc{}; // TODO(crbug.com/dawn/1133): Fill in.
interop::Promise<interop::Interface<interop::GPUDevice>> promise(env); interop::Promise<interop::Interface<interop::GPUDevice>> promise(env);
if (descriptor.has_value()) {
// See src/dawn_native/Extensions.cpp for feature <-> extension mappings.
for (auto required : descriptor->requiredFeatures) {
switch (required) {
case interop::GPUFeatureName::kDepthClamping:
desc.requiredExtensions.emplace_back("depth_clamping");
continue;
case interop::GPUFeatureName::kPipelineStatisticsQuery:
desc.requiredExtensions.emplace_back("pipeline_statistics_query");
continue;
case interop::GPUFeatureName::kTextureCompressionBc:
desc.requiredExtensions.emplace_back("texture_compression_bc");
continue;
case interop::GPUFeatureName::kTimestampQuery:
desc.requiredExtensions.emplace_back("timestamp_query");
continue;
case interop::GPUFeatureName::kDepth24UnormStencil8:
case interop::GPUFeatureName::kDepth32FloatStencil8:
continue; // TODO(crbug.com/dawn/1130)
}
UNIMPLEMENTED("required: ", required);
}
}
auto wgpu_device = adapter_.CreateDevice(&desc); auto wgpu_device = adapter_.CreateDevice(&desc);
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));
@ -57,5 +126,4 @@ namespace wgpu { namespace binding {
} }
return promise; return promise;
} }
}} // namespace wgpu::binding }} // namespace wgpu::binding

View File

@ -109,7 +109,12 @@ namespace wgpu { namespace binding {
} }
interop::Interface<interop::GPUSupportedFeatures> GPUDevice::getFeatures(Napi::Env env) { interop::Interface<interop::GPUSupportedFeatures> GPUDevice::getFeatures(Napi::Env env) {
class Features : public interop::GPUSupportedFeatures {}; class Features : public interop::GPUSupportedFeatures {
public:
bool has(Napi::Env, std::string feature) override {
UNIMPLEMENTED();
}
};
return interop::GPUSupportedFeatures::Create<Features>(env); return interop::GPUSupportedFeatures::Create<Features>(env);
} }

View File

@ -141,6 +141,9 @@ Wrappers* Wrappers::instance = nullptr;
{{- end}} {{- end}}
static Napi::Function Class(Napi::Env env) { static Napi::Function Class(Napi::Env env) {
return DefineClass(env, "{{$.Name}}", { return DefineClass(env, "{{$.Name}}", {
{{ if $s := SetlikeOf $}}
InstanceMethod("has", &W{{$.Name}}::has),
{{- end}}
{{- range $m := MethodsOf $}} {{- range $m := MethodsOf $}}
InstanceMethod("{{$m.Name}}", &W{{$.Name}}::{{$m.Name}}), InstanceMethod("{{$m.Name}}", &W{{$.Name}}::{{$m.Name}}),
{{- end}} {{- end}}
@ -156,6 +159,17 @@ Wrappers* Wrappers::instance = nullptr;
} }
W{{$.Name}}(const Napi::CallbackInfo& info) : ObjectWrap(info) {} W{{$.Name}}(const Napi::CallbackInfo& info) : ObjectWrap(info) {}
{{ if $s := SetlikeOf $}}
Napi::Value has(const Napi::CallbackInfo& info) {
std::tuple<{{template "Type" $s.Elem}}> args;
if (FromJS(info, args)) {
return ToJS(info.Env(), impl->has(info.Env(), std::get<0>(args)));
}
Napi::Error::New(info.Env(), "invalid arguments to has()").ThrowAsJavaScriptException();
return {};
}
{{- end}}
{{- range $m := MethodsOf $}} {{- range $m := MethodsOf $}}
Napi::Value {{$m.Name}}(const Napi::CallbackInfo& info) { Napi::Value {{$m.Name}}(const Napi::CallbackInfo& info) {
{{- range $overload_idx, $o := $m.Overloads}} {{- range $overload_idx, $o := $m.Overloads}}
@ -307,8 +321,7 @@ Interface<{{$.Name}}> {{$.Name}}::Bind(Napi::Env env, std::unique_ptr<{{$.Name}}
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
*/ -}} */ -}}
{{- define "Enum"}} {{- define "Enum"}}
bool Converter<{{$.Name}}>::FromJS(Napi::Env env, Napi::Value value, {{$.Name}}& out) { bool Converter<{{$.Name}}>::FromString(std::string str, {{$.Name}}& out) {
std::string str = value.ToString();
{{- range $e := $.Values}} {{- range $e := $.Values}}
if (str == {{$e.Value}}) { if (str == {{$e.Value}}) {
out = {{$.Name}}::{{EnumEntryName $e.Value}}; out = {{$.Name}}::{{EnumEntryName $e.Value}};
@ -317,6 +330,9 @@ bool Converter<{{$.Name}}>::FromJS(Napi::Env env, Napi::Value value, {{$.Name}}&
{{- end}} {{- end}}
return false; return false;
} }
bool Converter<{{$.Name}}>::FromJS(Napi::Env env, Napi::Value value, {{$.Name}}& out) {
return FromString(value.ToString(), out);
}
Napi::Value Converter<{{$.Name}}>::ToJS(Napi::Env env, {{$.Name}} value) { Napi::Value Converter<{{$.Name}}>::ToJS(Napi::Env env, {{$.Name}} value) {
switch (value) { switch (value) {
{{- range $e := $.Values}} {{- range $e := $.Values}}

View File

@ -123,6 +123,9 @@ public:
virtual ~{{$.Name}}(); virtual ~{{$.Name}}();
{{$.Name}}(); {{$.Name}}();
{{- if $s := SetlikeOf $}}
{{- template "InterfaceSetlike" $s}}
{{- end}}
{{- range $m := MethodsOf $}} {{- range $m := MethodsOf $}}
{{- template "InterfaceMethod" $m}} {{- template "InterfaceMethod" $m}}
{{- end}} {{- end}}
@ -165,6 +168,7 @@ class Converter<{{$.Name}}> {
public: public:
static bool FromJS(Napi::Env, Napi::Value, {{$.Name}}&); static bool FromJS(Napi::Env, Napi::Value, {{$.Name}}&);
static Napi::Value ToJS(Napi::Env, {{$.Name}}); static Napi::Value ToJS(Napi::Env, {{$.Name}});
static bool FromString(std::string, {{$.Name}}&);
}; };
std::ostream& operator<<(std::ostream& o, {{$.Name}}); std::ostream& operator<<(std::ostream& o, {{$.Name}});
@ -184,6 +188,20 @@ std::ostream& operator<<(std::ostream& o, {{$.Name}});
{{- end }} {{- end }}
{{- /*
--------------------------------------------------------------------------------
-- InterfaceSetlike emits the C++ methods for a setlike interface
--------------------------------------------------------------------------------
*/ -}}
{{- define "InterfaceSetlike"}}
virtual bool has(Napi::Env, {{template "Type" $.Elem}}) = 0;
{{- /* TODO(crbug.com/dawn/1143):
entries, forEach, keys, size, values
read-write: add, clear, or delete
*/}}
{{- end }}
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- InterfaceMethod emits the C++ declaration for a single interface ast.Member -- InterfaceMethod emits the C++ declaration for a single interface ast.Member

View File

@ -128,6 +128,7 @@ func run() error {
"IsUnionType": is(ast.UnionType{}), "IsUnionType": is(ast.UnionType{}),
"Lookup": g.lookup, "Lookup": g.lookup,
"MethodsOf": methodsOf, "MethodsOf": methodsOf,
"SetlikeOf": setlikeOf,
"Title": strings.Title, "Title": strings.Title,
} }
t, err := g.t. t, err := g.t.
@ -569,6 +570,20 @@ func constantsOf(obj interface{}) []*ast.Member {
return out return out
} }
// setlikeOf returns the setlike ast.Pattern, if obj is a setlike interface.
func setlikeOf(obj interface{}) *ast.Pattern {
iface, ok := obj.(*ast.Interface)
if !ok {
return nil
}
for _, pattern := range iface.Patterns {
if pattern.Type == ast.Setlike {
return pattern
}
}
return nil
}
// pascalCase returns the snake-case string s transformed into 'PascalCase', // pascalCase returns the snake-case string s transformed into 'PascalCase',
// Rules: // Rules:
// * The first letter of the string is capitalized // * The first letter of the string is capitalized