Add feature queries to dawn_native/dawn_wire
This is so we can implement the adapter/device APIs fully
on dawn_wire.
Bug: dawn:689
Change-Id: I47f68157d081f359f871e0efe0d974dfe53de7d7
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/71521
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/dawn.json b/dawn.json
index 884b5e6..97cff4a 100644
--- a/dawn.json
+++ b/dawn.json
@@ -98,6 +98,14 @@
]
},
{
+ "tags": ["dawn"],
+ "name": "enumerate features",
+ "returns": "uint32_t",
+ "args": [
+ {"name": "features", "type": "feature name", "annotation": "*"}
+ ]
+ },
+ {
"name": "request device",
"args": [
{"name": "descriptor", "type": "device descriptor", "annotation": "const*"},
@@ -1058,6 +1066,22 @@
]
},
{
+ "tags": ["dawn"],
+ "name": "has feature",
+ "returns": "bool",
+ "args": [
+ {"name": "feature", "type": "feature name"}
+ ]
+ },
+ {
+ "tags": ["dawn"],
+ "name": "enumerate features",
+ "returns": "uint32_t",
+ "args": [
+ {"name": "features", "type": "feature name", "annotation": "*"}
+ ]
+ },
+ {
"name": "get queue",
"returns": "queue"
},
@@ -1297,7 +1321,10 @@
{"value": 7, "name": "texture compression ETC2"},
{"value": 8, "name": "texture compression ASTC"},
{"value": 9, "name": "indirect first instance"},
- {"value": 1000, "name": "depth clamping", "tags": ["emscripten", "dawn"]}
+ {"value": 1000, "name": "depth clamping", "tags": ["emscripten", "dawn"]},
+ {"value": 1001, "name": "dawn shader float 16", "tags": ["dawn"]},
+ {"value": 1002, "name": "dawn internal usages", "tags": ["dawn"]},
+ {"value": 1003, "name": "dawn multi planar formats", "tags": ["dawn"]}
]
},
"filter mode": {
diff --git a/dawn_wire.json b/dawn_wire.json
index 5083751..4bd03a1 100644
--- a/dawn_wire.json
+++ b/dawn_wire.json
@@ -151,6 +151,7 @@
"AdapterGetProperties",
"AdapterGetLimits",
"AdapterHasFeature",
+ "AdapterEnumerateFeatures",
"AdapterRequestDevice",
"BufferMapAsync",
"BufferGetConstMappedRange",
@@ -159,6 +160,8 @@
"DeviceCreateComputePipelineAsync",
"DeviceCreateRenderPipelineAsync",
"DeviceGetLimits",
+ "DeviceHasFeature",
+ "DeviceEnumerateFeatures",
"DevicePopErrorScope",
"DeviceSetDeviceLostCallback",
"DeviceSetUncapturedErrorCallback",
diff --git a/generator/templates/dawn_native/ProcTable.cpp b/generator/templates/dawn_native/ProcTable.cpp
index 73a9d8d..857cbc7 100644
--- a/generator/templates/dawn_native/ProcTable.cpp
+++ b/generator/templates/dawn_native/ProcTable.cpp
@@ -43,7 +43,7 @@
{% for arg in method.arguments %}
{% set varName = as_varName(arg.name) %}
- {% if arg.type.category in ["enum", "bitmask"] %}
+ {% if arg.type.category in ["enum", "bitmask"] and arg.annotation == "value" %}
auto {{varName}}_ = static_cast<{{as_frontendType(arg.type)}}>({{varName}});
{% elif arg.annotation != "value" or arg.type.category == "object" %}
auto {{varName}}_ = reinterpret_cast<{{decorate("", as_frontendType(arg.type), arg)}}>({{varName}});
diff --git a/generator/templates/dawn_wire/client/ApiProcs.cpp b/generator/templates/dawn_wire/client/ApiProcs.cpp
index 48b3e3a..71201ec 100644
--- a/generator/templates/dawn_wire/client/ApiProcs.cpp
+++ b/generator/templates/dawn_wire/client/ApiProcs.cpp
@@ -64,6 +64,8 @@
{% endif %}
{% for arg in method.arguments %}
+ //* Commands with mutable pointers should not be autogenerated.
+ {{assert(arg.annotation != "*")}}
cmd.{{as_varName(arg.name)}} = {{as_varName(arg.name)}};
{% endfor %}
diff --git a/src/dawn_native/Adapter.cpp b/src/dawn_native/Adapter.cpp
index c3ac8de..7ef85c1 100644
--- a/src/dawn_native/Adapter.cpp
+++ b/src/dawn_native/Adapter.cpp
@@ -86,6 +86,10 @@
return mSupportedFeatures.IsEnabled(feature);
}
+ uint32_t AdapterBase::APIEnumerateFeatures(wgpu::FeatureName* features) const {
+ return mSupportedFeatures.EnumerateFeatures(features);
+ }
+
void AdapterBase::APIRequestDevice(const DeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata) {
diff --git a/src/dawn_native/Adapter.h b/src/dawn_native/Adapter.h
index 36930db..a8a5fdb 100644
--- a/src/dawn_native/Adapter.h
+++ b/src/dawn_native/Adapter.h
@@ -40,6 +40,7 @@
bool APIGetLimits(SupportedLimits* limits) const;
void APIGetProperties(AdapterProperties* properties) const;
bool APIHasFeature(wgpu::FeatureName feature) const;
+ uint32_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
void APIRequestDevice(const DeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata);
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index 35b5101..127b29f 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -1197,7 +1197,7 @@
}
}
- bool DeviceBase::APIGetLimits(SupportedLimits* limits) {
+ bool DeviceBase::APIGetLimits(SupportedLimits* limits) const {
ASSERT(limits != nullptr);
if (limits->nextInChain != nullptr) {
return false;
@@ -1206,6 +1206,14 @@
return true;
}
+ bool DeviceBase::APIHasFeature(wgpu::FeatureName feature) const {
+ return mEnabledFeatures.IsEnabled(feature);
+ }
+
+ uint32_t DeviceBase::APIEnumerateFeatures(wgpu::FeatureName* features) const {
+ return mEnabledFeatures.EnumerateFeatures(features);
+ }
+
void DeviceBase::APIInjectError(wgpu::ErrorType type, const char* message) {
if (ConsumedError(ValidateErrorType(type))) {
return;
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index ff9b7f0..298d0b4 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -257,7 +257,9 @@
QueueBase* APIGetQueue();
- bool APIGetLimits(SupportedLimits* limits);
+ bool APIGetLimits(SupportedLimits* limits) const;
+ bool APIHasFeature(wgpu::FeatureName feature) const;
+ uint32_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
void APIInjectError(wgpu::ErrorType type, const char* message);
bool APITick();
diff --git a/src/dawn_native/Features.cpp b/src/dawn_native/Features.cpp
index ad427d3..037d8f4 100644
--- a/src/dawn_native/Features.cpp
+++ b/src/dawn_native/Features.cpp
@@ -106,6 +106,12 @@
return Feature::Depth24UnormStencil8;
case wgpu::FeatureName::Depth32FloatStencil8:
return Feature::Depth32FloatStencil8;
+ case wgpu::FeatureName::DawnShaderFloat16:
+ return Feature::ShaderFloat16;
+ case wgpu::FeatureName::DawnInternalUsages:
+ return Feature::DawnInternalUsages;
+ case wgpu::FeatureName::DawnMultiPlanarFormats:
+ return Feature::MultiPlanarFormats;
case wgpu::FeatureName::IndirectFirstInstance:
return Feature::InvalidEnum;
@@ -113,6 +119,36 @@
return Feature::InvalidEnum;
}
+ wgpu::FeatureName ToAPIFeature(Feature feature) {
+ switch (feature) {
+ case Feature::TextureCompressionBC:
+ return wgpu::FeatureName::TextureCompressionBC;
+ case Feature::TextureCompressionETC2:
+ return wgpu::FeatureName::TextureCompressionETC2;
+ case Feature::TextureCompressionASTC:
+ return wgpu::FeatureName::TextureCompressionASTC;
+ case Feature::PipelineStatisticsQuery:
+ return wgpu::FeatureName::PipelineStatisticsQuery;
+ case Feature::TimestampQuery:
+ return wgpu::FeatureName::TimestampQuery;
+ case Feature::DepthClamping:
+ return wgpu::FeatureName::DepthClamping;
+ case Feature::Depth24UnormStencil8:
+ return wgpu::FeatureName::Depth24UnormStencil8;
+ case Feature::Depth32FloatStencil8:
+ return wgpu::FeatureName::Depth32FloatStencil8;
+ case Feature::ShaderFloat16:
+ return wgpu::FeatureName::DawnShaderFloat16;
+ case Feature::DawnInternalUsages:
+ return wgpu::FeatureName::DawnInternalUsages;
+ case Feature::MultiPlanarFormats:
+ return wgpu::FeatureName::DawnMultiPlanarFormats;
+
+ case Feature::EnumCount:
+ UNREACHABLE();
+ }
+ }
+
} // anonymous namespace
void FeaturesSet::EnableFeature(Feature feature) {
@@ -132,6 +168,17 @@
return f != Feature::InvalidEnum && IsEnabled(f);
}
+ uint32_t FeaturesSet::EnumerateFeatures(wgpu::FeatureName* features) const {
+ for (uint32_t i : IterateBitSet(featuresBitSet)) {
+ wgpu::FeatureName feature = ToAPIFeature(static_cast<Feature>(i));
+ if (features != nullptr) {
+ *features = feature;
+ features += 1;
+ }
+ }
+ return featuresBitSet.count();
+ }
+
std::vector<const char*> FeaturesSet::GetEnabledFeatureNames() const {
std::vector<const char*> enabledFeatureNames(featuresBitSet.count());
diff --git a/src/dawn_native/Features.h b/src/dawn_native/Features.h
index 4c4a79a..6dd2afc 100644
--- a/src/dawn_native/Features.h
+++ b/src/dawn_native/Features.h
@@ -19,6 +19,7 @@
#include <unordered_map>
#include <vector>
+#include "common/ityp_bitset.h"
#include "dawn/webgpu_cpp.h"
#include "dawn_native/DawnNative.h"
@@ -52,6 +53,9 @@
void EnableFeature(Feature feature);
bool IsEnabled(Feature feature) const;
bool IsEnabled(wgpu::FeatureName feature) const;
+ // Returns |count|, the number of features. Writes out all |count| values if |features| is
+ // non-null.
+ uint32_t EnumerateFeatures(wgpu::FeatureName* features) const;
std::vector<const char*> GetEnabledFeatureNames() const;
void InitializeDeviceProperties(WGPUDeviceProperties* properties) const;
};
diff --git a/src/dawn_wire/client/Adapter.cpp b/src/dawn_wire/client/Adapter.cpp
index ee789f9..f3e46ef 100644
--- a/src/dawn_wire/client/Adapter.cpp
+++ b/src/dawn_wire/client/Adapter.cpp
@@ -28,6 +28,10 @@
UNREACHABLE();
}
+ uint32_t Adapter::EnumerateFeatures(WGPUFeatureName* features) const {
+ UNREACHABLE();
+ }
+
void Adapter::RequestDevice(const WGPUDeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata) {
diff --git a/src/dawn_wire/client/Adapter.h b/src/dawn_wire/client/Adapter.h
index d939220..58c5d0f 100644
--- a/src/dawn_wire/client/Adapter.h
+++ b/src/dawn_wire/client/Adapter.h
@@ -29,6 +29,7 @@
bool GetLimits(WGPUSupportedLimits* limits) const;
void GetProperties(WGPUAdapterProperties* properties) const;
bool HasFeature(WGPUFeatureName feature) const;
+ uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
void RequestDevice(const WGPUDeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata);
diff --git a/src/dawn_wire/client/Device.cpp b/src/dawn_wire/client/Device.cpp
index 8379d51..57e6599 100644
--- a/src/dawn_wire/client/Device.cpp
+++ b/src/dawn_wire/client/Device.cpp
@@ -196,12 +196,20 @@
return Buffer::CreateError(this);
}
- bool Device::GetLimits(WGPUSupportedLimits* limits) {
+ bool Device::GetLimits(WGPUSupportedLimits* limits) const {
// Not implemented in the wire.
UNREACHABLE();
return false;
}
+ bool Device::HasFeature(WGPUFeatureName feature) const {
+ UNREACHABLE();
+ }
+
+ uint32_t Device::EnumerateFeatures(WGPUFeatureName* features) const {
+ UNREACHABLE();
+ }
+
WGPUQueue Device::GetQueue() {
// The queue is lazily created because if a Device is created by
// Reserve/Inject, we cannot send the GetQueue message until
diff --git a/src/dawn_wire/client/Device.h b/src/dawn_wire/client/Device.h
index 426799c..fff5cf8 100644
--- a/src/dawn_wire/client/Device.h
+++ b/src/dawn_wire/client/Device.h
@@ -64,7 +64,9 @@
WGPUCreatePipelineAsyncStatus status,
const char* message);
- bool GetLimits(WGPUSupportedLimits* limits);
+ bool GetLimits(WGPUSupportedLimits* limits) const;
+ bool HasFeature(WGPUFeatureName feature) const;
+ uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
WGPUQueue GetQueue();
void CancelCallbacksForDisconnect() override;
diff --git a/src/tests/unittests/wire/WireInjectInstanceTests.cpp b/src/tests/unittests/wire/WireInjectInstanceTests.cpp
index 7bdf170..05502f5 100644
--- a/src/tests/unittests/wire/WireInjectInstanceTests.cpp
+++ b/src/tests/unittests/wire/WireInjectInstanceTests.cpp
@@ -23,7 +23,7 @@
namespace {
class WireInjectInstanceTests : public WireTest {
- public:
+ public:
WireInjectInstanceTests() {
}
~WireInjectInstanceTests() override = default;
@@ -36,13 +36,14 @@
WGPUInstance serverInstance = api.GetNewInstance();
EXPECT_CALL(api, InstanceReference(serverInstance));
- ASSERT_TRUE(
- GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+ ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
+ reservation.generation));
WGPUSurfaceDescriptor surfaceDesc = {};
wgpuInstanceCreateSurface(reservation.instance, &surfaceDesc);
WGPUSurface serverSurface = api.GetNewSurface();
- EXPECT_CALL(api, InstanceCreateSurface(serverInstance, NotNull())).WillOnce(Return(serverSurface));
+ EXPECT_CALL(api, InstanceCreateSurface(serverInstance, NotNull()))
+ .WillOnce(Return(serverSurface));
FlushClient();
}
@@ -55,19 +56,18 @@
ASSERT_NE(reservation1.instance, reservation2.instance);
}
-
// Test that injecting the same id fails.
TEST_F(WireInjectInstanceTests, InjectExistingID) {
ReservedInstance reservation = GetWireClient()->ReserveInstance();
WGPUInstance serverInstance = api.GetNewInstance();
EXPECT_CALL(api, InstanceReference(serverInstance));
- ASSERT_TRUE(
- GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+ ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
+ reservation.generation));
// ID already in use, call fails.
- ASSERT_FALSE(
- GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+ ASSERT_FALSE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
+ reservation.generation));
}
// Test that the server only borrows the instance and does a single reference-release
@@ -77,8 +77,8 @@
// Injecting the instance adds a reference
WGPUInstance serverInstance = api.GetNewInstance();
EXPECT_CALL(api, InstanceReference(serverInstance));
- ASSERT_TRUE(
- GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+ ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reservation.id,
+ reservation.generation));
// Releasing the instance removes a single reference.
wgpuInstanceRelease(reservation.instance);