From 89ddadcd1e30f5d83eedd0e40df816e16b234196 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Wed, 15 Dec 2021 00:12:30 +0000 Subject: [PATCH] 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 Reviewed-by: Corentin Wallez Commit-Queue: Austin Eng --- dawn.json | 29 +++++++++++- dawn_wire.json | 3 ++ generator/templates/dawn_native/ProcTable.cpp | 2 +- .../templates/dawn_wire/client/ApiProcs.cpp | 2 + src/dawn_native/Adapter.cpp | 4 ++ src/dawn_native/Adapter.h | 1 + src/dawn_native/Device.cpp | 10 +++- src/dawn_native/Device.h | 4 +- src/dawn_native/Features.cpp | 47 +++++++++++++++++++ src/dawn_native/Features.h | 4 ++ src/dawn_wire/client/Adapter.cpp | 4 ++ src/dawn_wire/client/Adapter.h | 1 + src/dawn_wire/client/Device.cpp | 10 +++- src/dawn_wire/client/Device.h | 4 +- .../wire/WireInjectInstanceTests.cpp | 22 ++++----- 15 files changed, 130 insertions(+), 17 deletions(-) diff --git a/dawn.json b/dawn.json index 884b5e6451..97cff4a410 100644 --- a/dawn.json +++ b/dawn.json @@ -97,6 +97,14 @@ {"name": "feature", "type": "feature name"} ] }, + { + "tags": ["dawn"], + "name": "enumerate features", + "returns": "uint32_t", + "args": [ + {"name": "features", "type": "feature name", "annotation": "*"} + ] + }, { "name": "request device", "args": [ @@ -1057,6 +1065,22 @@ {"name": "limits", "type": "supported limits", "annotation": "*"} ] }, + { + "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 50837517c1..4bd03a100c 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 73a9d8db55..857cbc7c69 100644 --- a/generator/templates/dawn_native/ProcTable.cpp +++ b/generator/templates/dawn_native/ProcTable.cpp @@ -43,7 +43,7 @@ namespace dawn_native { {% 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 48b3e3a59c..71201ecb47 100644 --- a/generator/templates/dawn_wire/client/ApiProcs.cpp +++ b/generator/templates/dawn_wire/client/ApiProcs.cpp @@ -64,6 +64,8 @@ namespace dawn_wire { namespace client { {% 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 c3ac8de5e1..7ef85c1375 100644 --- a/src/dawn_native/Adapter.cpp +++ b/src/dawn_native/Adapter.cpp @@ -86,6 +86,10 @@ namespace dawn_native { 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 36930db1eb..a8a5fdb5f9 100644 --- a/src/dawn_native/Adapter.h +++ b/src/dawn_native/Adapter.h @@ -40,6 +40,7 @@ namespace dawn_native { 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 35b51012da..127b29f168 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -1197,7 +1197,7 @@ namespace dawn_native { } } - bool DeviceBase::APIGetLimits(SupportedLimits* limits) { + bool DeviceBase::APIGetLimits(SupportedLimits* limits) const { ASSERT(limits != nullptr); if (limits->nextInChain != nullptr) { return false; @@ -1206,6 +1206,14 @@ namespace dawn_native { 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 ff9b7f099a..298d0b47ac 100644 --- a/src/dawn_native/Device.h +++ b/src/dawn_native/Device.h @@ -257,7 +257,9 @@ namespace dawn_native { 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 ad427d3455..037d8f4248 100644 --- a/src/dawn_native/Features.cpp +++ b/src/dawn_native/Features.cpp @@ -106,6 +106,12 @@ namespace dawn_native { 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 @@ namespace dawn_native { 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 @@ namespace dawn_native { 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(i)); + if (features != nullptr) { + *features = feature; + features += 1; + } + } + return featuresBitSet.count(); + } + std::vector FeaturesSet::GetEnabledFeatureNames() const { std::vector enabledFeatureNames(featuresBitSet.count()); diff --git a/src/dawn_native/Features.h b/src/dawn_native/Features.h index 4c4a79aad7..6dd2afc30f 100644 --- a/src/dawn_native/Features.h +++ b/src/dawn_native/Features.h @@ -19,6 +19,7 @@ #include #include +#include "common/ityp_bitset.h" #include "dawn/webgpu_cpp.h" #include "dawn_native/DawnNative.h" @@ -52,6 +53,9 @@ namespace dawn_native { 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 GetEnabledFeatureNames() const; void InitializeDeviceProperties(WGPUDeviceProperties* properties) const; }; diff --git a/src/dawn_wire/client/Adapter.cpp b/src/dawn_wire/client/Adapter.cpp index ee789f9cdd..f3e46ef5d8 100644 --- a/src/dawn_wire/client/Adapter.cpp +++ b/src/dawn_wire/client/Adapter.cpp @@ -28,6 +28,10 @@ namespace dawn_wire { namespace client { 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 d9392204bd..58c5d0ff4f 100644 --- a/src/dawn_wire/client/Adapter.h +++ b/src/dawn_wire/client/Adapter.h @@ -29,6 +29,7 @@ namespace dawn_wire { namespace client { 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 8379d51b1c..57e659919e 100644 --- a/src/dawn_wire/client/Device.cpp +++ b/src/dawn_wire/client/Device.cpp @@ -196,12 +196,20 @@ namespace dawn_wire { namespace client { 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 426799c1eb..fff5cf8543 100644 --- a/src/dawn_wire/client/Device.h +++ b/src/dawn_wire/client/Device.h @@ -64,7 +64,9 @@ namespace dawn_wire { namespace client { 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 7bdf170e6b..05502f56f9 100644 --- a/src/tests/unittests/wire/WireInjectInstanceTests.cpp +++ b/src/tests/unittests/wire/WireInjectInstanceTests.cpp @@ -23,7 +23,7 @@ using namespace dawn_wire; namespace { class WireInjectInstanceTests : public WireTest { - public: + public: WireInjectInstanceTests() { } ~WireInjectInstanceTests() override = default; @@ -36,13 +36,14 @@ namespace { 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 @@ namespace { 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 @@ namespace { // 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);