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::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
// 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) {
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) {
@ -49,6 +94,30 @@ namespace wgpu { namespace binding {
dawn_native::DeviceDescriptor desc{}; // TODO(crbug.com/dawn/1133): Fill in.
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);
if (wgpu_device) {
promise.Resolve(interop::GPUDevice::Create<GPUDevice>(env, env, wgpu_device));
@ -57,5 +126,4 @@ namespace wgpu { namespace binding {
}
return promise;
}
}} // namespace wgpu::binding

View File

@ -109,7 +109,12 @@ namespace wgpu { namespace binding {
}
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);
}

View File

@ -141,6 +141,9 @@ Wrappers* Wrappers::instance = nullptr;
{{- end}}
static Napi::Function Class(Napi::Env env) {
return DefineClass(env, "{{$.Name}}", {
{{ if $s := SetlikeOf $}}
InstanceMethod("has", &W{{$.Name}}::has),
{{- end}}
{{- range $m := MethodsOf $}}
InstanceMethod("{{$m.Name}}", &W{{$.Name}}::{{$m.Name}}),
{{- end}}
@ -156,6 +159,17 @@ Wrappers* Wrappers::instance = nullptr;
}
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 $}}
Napi::Value {{$m.Name}}(const Napi::CallbackInfo& info) {
{{- range $overload_idx, $o := $m.Overloads}}
@ -307,8 +321,7 @@ Interface<{{$.Name}}> {{$.Name}}::Bind(Napi::Env env, std::unique_ptr<{{$.Name}}
--------------------------------------------------------------------------------
*/ -}}
{{- define "Enum"}}
bool Converter<{{$.Name}}>::FromJS(Napi::Env env, Napi::Value value, {{$.Name}}& out) {
std::string str = value.ToString();
bool Converter<{{$.Name}}>::FromString(std::string str, {{$.Name}}& out) {
{{- range $e := $.Values}}
if (str == {{$e.Value}}) {
out = {{$.Name}}::{{EnumEntryName $e.Value}};
@ -317,6 +330,9 @@ bool Converter<{{$.Name}}>::FromJS(Napi::Env env, Napi::Value value, {{$.Name}}&
{{- end}}
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) {
switch (value) {
{{- range $e := $.Values}}

View File

@ -123,6 +123,9 @@ public:
virtual ~{{$.Name}}();
{{$.Name}}();
{{- if $s := SetlikeOf $}}
{{- template "InterfaceSetlike" $s}}
{{- end}}
{{- range $m := MethodsOf $}}
{{- template "InterfaceMethod" $m}}
{{- end}}
@ -165,6 +168,7 @@ class Converter<{{$.Name}}> {
public:
static bool FromJS(Napi::Env, Napi::Value, {{$.Name}}&);
static Napi::Value ToJS(Napi::Env, {{$.Name}});
static bool FromString(std::string, {{$.Name}}&);
};
std::ostream& operator<<(std::ostream& o, {{$.Name}});
@ -184,6 +188,20 @@ std::ostream& operator<<(std::ostream& o, {{$.Name}});
{{- 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

View File

@ -128,6 +128,7 @@ func run() error {
"IsUnionType": is(ast.UnionType{}),
"Lookup": g.lookup,
"MethodsOf": methodsOf,
"SetlikeOf": setlikeOf,
"Title": strings.Title,
}
t, err := g.t.
@ -569,6 +570,20 @@ func constantsOf(obj interface{}) []*ast.Member {
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',
// Rules:
// * The first letter of the string is capitalized