webgpu.h: Add Adapter and Device GetFeatures() methods
Bug: 368672123
Change-Id: I0b16347f6c2912e71228f5f613d665efa1f95161
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/212174
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Fr <beaufort.francois@gmail.com>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index 9f66565..6b80fec 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -301,6 +301,7 @@
m for m in json_data['members'] if is_enabled(m)
]
Type.__init__(self, name, dict(json_data, **json_data_override))
+ self.out = json_data.get('out', False)
self.chained = json_data.get('chained', None)
self.extensible = json_data.get('extensible', None)
if self.chained:
@@ -332,7 +333,10 @@
@property
def output(self):
- return self.chained == "out" or self.extensible == "out"
+ # self.out is a temporary way to express that this is an output structure
+ # without also making it extensible. See
+ # https://dawn-review.googlesource.com/c/dawn/+/212174/comment/2271690b_1fd82ea9/
+ return self.chained == "out" or self.extensible == "out" or self.out
@property
def has_free_members_function(self):
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index bfa79d0..cbdca32 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -156,12 +156,20 @@
},
{
"name": "enumerate features",
+ "tags": ["deprecated"],
"returns": "size_t",
"args": [
{"name": "features", "type": "feature name", "annotation": "*"}
]
},
{
+ "name": "get features",
+ "returns": "void",
+ "args": [
+ {"name": "features", "type": "supported features", "annotation": "*"}
+ ]
+ },
+ {
"name": "request device",
"args": [
{"name": "descriptor", "type": "device descriptor", "annotation": "const*", "optional": true, "no_default": true},
@@ -1560,12 +1568,20 @@
},
{
"name": "enumerate features",
+ "tags": ["deprecated"],
"returns": "size_t",
"args": [
{"name": "features", "type": "feature name", "annotation": "*"}
]
},
{
+ "name": "get features",
+ "returns": "void",
+ "args": [
+ {"name": "features", "type": "supported features", "annotation": "*"}
+ ]
+ },
+ {
"name": "get adapter",
"returns": "adapter",
"tags": ["dawn"]
@@ -1867,6 +1883,14 @@
{"name": "limits", "type": "limits"}
]
},
+ "supported features": {
+ "category": "structure",
+ "out": true,
+ "members": [
+ {"name": "feature count", "type": "size_t"},
+ {"name": "features", "type": "feature name", "annotation": "const*", "length": "feature count"}
+ ]
+ },
"logging callback": {
"category": "function pointer",
"tags": ["dawn"],
diff --git a/src/dawn/dawn_wire.json b/src/dawn/dawn_wire.json
index 270bb10..f5a5107 100644
--- a/src/dawn/dawn_wire.json
+++ b/src/dawn/dawn_wire.json
@@ -218,6 +218,7 @@
],
"client_side_commands": [
"AdapterCreateDevice",
+ "AdapterGetFeatures",
"AdapterGetFormatCapabilities",
"AdapterGetInfo",
"AdapterGetInstance",
@@ -243,6 +244,7 @@
"DeviceCreateRenderPipelineAsyncF",
"DeviceCreateRenderPipelineAsync2",
"DeviceGetAdapter",
+ "DeviceGetFeatures",
"DeviceGetLimits",
"DeviceHasFeature",
"DeviceEnumerateFeatures",
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 57958d6..be0cca3 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -228,6 +228,18 @@
return mSupportedFeatures.EnumerateFeatures(features);
}
+void AdapterBase::APIGetFeatures(wgpu::SupportedFeatures* features) const {
+ this->APIGetFeatures(reinterpret_cast<SupportedFeatures*>(features));
+}
+
+void AdapterBase::APIGetFeatures(SupportedFeatures* features) const {
+ mSupportedFeatures.ToSupportedFeatures(features);
+}
+
+void APISupportedFeaturesFreeMembers(WGPUSupportedFeatures supportedFeatures) {
+ delete[] supportedFeatures.features;
+}
+
// TODO(https://crbug.com/dawn/2465) Could potentially re-implement via AllowSpontaneous async mode.
DeviceBase* AdapterBase::APICreateDevice(const DeviceDescriptor* descriptor) {
if (descriptor == nullptr) {
diff --git a/src/dawn/native/Adapter.h b/src/dawn/native/Adapter.h
index b0e1b08..28b5bcf 100644
--- a/src/dawn/native/Adapter.h
+++ b/src/dawn/native/Adapter.h
@@ -64,6 +64,8 @@
wgpu::Status APIGetInfo(AdapterInfo* info) const;
bool APIHasFeature(wgpu::FeatureName feature) const;
size_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
+ void APIGetFeatures(SupportedFeatures* features) const;
+ void APIGetFeatures(wgpu::SupportedFeatures* 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 7ea30103..7fa685d 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -2009,6 +2009,14 @@
return mEnabledFeatures.EnumerateFeatures(features);
}
+void DeviceBase::APIGetFeatures(wgpu::SupportedFeatures* features) const {
+ this->APIGetFeatures(reinterpret_cast<SupportedFeatures*>(features));
+}
+
+void DeviceBase::APIGetFeatures(SupportedFeatures* features) const {
+ mEnabledFeatures.ToSupportedFeatures(features);
+}
+
void DeviceBase::APIInjectError(wgpu::ErrorType type, StringView message) {
if (ConsumedError(ValidateErrorType(type))) {
return;
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index a93516d..7b2170e 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -289,6 +289,8 @@
wgpu::Status APIGetLimits(SupportedLimits* limits) const;
bool APIHasFeature(wgpu::FeatureName feature) const;
size_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
+ void APIGetFeatures(wgpu::SupportedFeatures* features) const;
+ void APIGetFeatures(SupportedFeatures* features) const;
void APIInjectError(wgpu::ErrorType type, StringView message);
bool APITick();
void APIValidateTextureDescriptor(const TextureDescriptor* desc);
diff --git a/src/dawn/native/Features.cpp b/src/dawn/native/Features.cpp
index 703fd90..a548e10 100644
--- a/src/dawn/native/Features.cpp
+++ b/src/dawn/native/Features.cpp
@@ -444,6 +444,29 @@
return enabledFeatureNames;
}
+void FeaturesSet::ToSupportedFeatures(SupportedFeatures* supportedFeatures) const {
+ if (!supportedFeatures) {
+ return;
+ }
+
+ const size_t count = featuresBitSet.count();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = nullptr;
+
+ if (count == 0) {
+ return;
+ }
+
+ // This will be freed by wgpuSupportedFeaturesFreeMembers.
+ wgpu::FeatureName* features = new wgpu::FeatureName[count];
+ uint32_t index = 0;
+ for (Feature f : IterateBitSet(featuresBitSet)) {
+ features[index++] = ToAPI(f);
+ }
+ DAWN_ASSERT(index == count);
+ supportedFeatures->features = features;
+}
+
} // namespace dawn::native
#include "dawn/native/Features_autogen.inl"
diff --git a/src/dawn/native/Features.h b/src/dawn/native/Features.h
index f97359e..d97d0b5 100644
--- a/src/dawn/native/Features.h
+++ b/src/dawn/native/Features.h
@@ -60,6 +60,7 @@
// non-null.
size_t EnumerateFeatures(wgpu::FeatureName* features) const;
std::vector<const char*> GetEnabledFeatureNames() const;
+ void ToSupportedFeatures(SupportedFeatures* supportedFeatures) const;
};
} // namespace dawn::native
diff --git a/src/dawn/node/binding/GPUAdapter.cpp b/src/dawn/node/binding/GPUAdapter.cpp
index ce5992f..2b38434 100644
--- a/src/dawn/node/binding/GPUAdapter.cpp
+++ b/src/dawn/node/binding/GPUAdapter.cpp
@@ -88,15 +88,11 @@
std::shared_ptr<AsyncRunner> async)
: adapter_(a), flags_(flags), async_(async) {}
-// TODO(dawn:1133): Avoid the extra copy by making the generator make a virtual method with const
-// std::string&
interop::Interface<interop::GPUSupportedFeatures> GPUAdapter::getFeatures(Napi::Env env) {
- wgpu::Adapter adapter(adapter_.Get());
- size_t count = adapter.EnumerateFeatures(nullptr);
- std::vector<wgpu::FeatureName> features(count);
- adapter.EnumerateFeatures(&features[0]);
- return interop::GPUSupportedFeatures::Create<GPUSupportedFeatures>(env, env,
- std::move(features));
+ wgpu::Adapter wgpuAdapter = adapter_.Get();
+ wgpu::SupportedFeatures features{};
+ wgpuAdapter.GetFeatures(&features);
+ return interop::GPUSupportedFeatures::Create<GPUSupportedFeatures>(env, env, features);
}
interop::Interface<interop::GPUSupportedLimits> GPUAdapter::getLimits(Napi::Env env) {
diff --git a/src/dawn/node/binding/GPUDevice.cpp b/src/dawn/node/binding/GPUDevice.cpp
index 741380e..7953066 100644
--- a/src/dawn/node/binding/GPUDevice.cpp
+++ b/src/dawn/node/binding/GPUDevice.cpp
@@ -176,13 +176,9 @@
}
interop::Interface<interop::GPUSupportedFeatures> GPUDevice::getFeatures(Napi::Env env) {
- size_t count = device_.EnumerateFeatures(nullptr);
- std::vector<wgpu::FeatureName> features(count);
- if (count > 0) {
- device_.EnumerateFeatures(features.data());
- }
- return interop::GPUSupportedFeatures::Create<GPUSupportedFeatures>(env, env,
- std::move(features));
+ wgpu::SupportedFeatures features{};
+ device_.GetFeatures(&features);
+ return interop::GPUSupportedFeatures::Create<GPUSupportedFeatures>(env, env, features);
}
interop::Interface<interop::GPUSupportedLimits> GPUDevice::getLimits(Napi::Env env) {
diff --git a/src/dawn/node/binding/GPUSupportedFeatures.cpp b/src/dawn/node/binding/GPUSupportedFeatures.cpp
index 0fa29f7..1d31e40 100644
--- a/src/dawn/node/binding/GPUSupportedFeatures.cpp
+++ b/src/dawn/node/binding/GPUSupportedFeatures.cpp
@@ -36,12 +36,13 @@
////////////////////////////////////////////////////////////////////////////////
GPUSupportedFeatures::GPUSupportedFeatures(Napi::Env env,
- const std::vector<wgpu::FeatureName>& features) {
+ const wgpu::SupportedFeatures& supportedFeatures) {
Converter conv(env);
// Add all known GPUFeatureNames that are known by dawn.node and skip the other ones are they
// may be native-only extension, Dawn-specific or other special cases.
- for (wgpu::FeatureName feature : features) {
+ for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
+ wgpu::FeatureName feature = supportedFeatures.features[i];
interop::GPUFeatureName gpuFeature;
if (conv(gpuFeature, feature)) {
enabled_.emplace(gpuFeature);
diff --git a/src/dawn/node/binding/GPUSupportedFeatures.h b/src/dawn/node/binding/GPUSupportedFeatures.h
index 417c4b3..d7a93e7 100644
--- a/src/dawn/node/binding/GPUSupportedFeatures.h
+++ b/src/dawn/node/binding/GPUSupportedFeatures.h
@@ -42,7 +42,7 @@
// GPUSupportedLFeatures is an implementation of interop::GPUSupportedFeatures.
class GPUSupportedFeatures final : public interop::GPUSupportedFeatures {
public:
- GPUSupportedFeatures(Napi::Env env, const std::vector<wgpu::FeatureName>& features);
+ GPUSupportedFeatures(Napi::Env env, const wgpu::SupportedFeatures& features);
// interop::GPUSupportedFeatures interface compliance
bool has(Napi::Env, std::string name) override;
diff --git a/src/dawn/samples/DawnInfo.cpp b/src/dawn/samples/DawnInfo.cpp
index cc5eaa6..8ddfe07 100644
--- a/src/dawn/samples/DawnInfo.cpp
+++ b/src/dawn/samples/DawnInfo.cpp
@@ -235,13 +235,12 @@
}
void DumpAdapterFeatures(const wgpu::Adapter& adapter) {
- auto feature_count = adapter.EnumerateFeatures(nullptr);
- std::vector<wgpu::FeatureName> features(feature_count);
- adapter.EnumerateFeatures(features.data());
-
+ wgpu::SupportedFeatures supportedFeatures;
+ adapter.GetFeatures(&supportedFeatures);
std::cout << " Features\n";
std::cout << " ========\n";
- for (const auto& f : features) {
+ for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
+ wgpu::FeatureName f = supportedFeatures.features[i];
auto info = dawn::native::GetFeatureInfo(f);
std::cout << " * " << info->name << "\n";
std::cout << WrapString(info->description, " ") << "\n";
diff --git a/src/dawn/tests/DawnTest.cpp b/src/dawn/tests/DawnTest.cpp
index 99bd853..f9c926f9 100644
--- a/src/dawn/tests/DawnTest.cpp
+++ b/src/dawn/tests/DawnTest.cpp
@@ -1073,14 +1073,13 @@
bool DawnTestBase::SupportsFeatures(const std::vector<wgpu::FeatureName>& features) {
DAWN_ASSERT(mBackendAdapter);
- std::vector<wgpu::FeatureName> supportedFeatures;
- uint32_t count = native::GetProcs().adapterEnumerateFeatures(mBackendAdapter.Get(), nullptr);
- supportedFeatures.resize(count);
- native::GetProcs().adapterEnumerateFeatures(
- mBackendAdapter.Get(), reinterpret_cast<WGPUFeatureName*>(&supportedFeatures[0]));
+ wgpu::SupportedFeatures supportedFeatures;
+ native::GetProcs().adapterGetFeatures(
+ mBackendAdapter.Get(), reinterpret_cast<WGPUSupportedFeatures*>(&supportedFeatures));
std::unordered_set<wgpu::FeatureName> supportedSet;
- for (wgpu::FeatureName f : supportedFeatures) {
+ for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
+ wgpu::FeatureName f = supportedFeatures.features[i];
supportedSet.insert(f);
}
diff --git a/src/dawn/tests/unittests/FeatureTests.cpp b/src/dawn/tests/unittests/FeatureTests.cpp
index ff7abdc..e7d8472 100644
--- a/src/dawn/tests/unittests/FeatureTests.cpp
+++ b/src/dawn/tests/unittests/FeatureTests.cpp
@@ -165,11 +165,12 @@
// Helper to check the returned device has all required features
auto ExpectDeviceHasRequiredFeatures =
[&requiredFeaturesSet](native::DeviceBase* deviceBase) {
- ASSERT_EQ(requiredFeaturesSet.size(), deviceBase->APIEnumerateFeatures(nullptr));
- std::vector<wgpu::FeatureName> enabledFeatures(requiredFeaturesSet.size());
- deviceBase->APIEnumerateFeatures(enabledFeatures.data());
- for (auto enabledFeature : enabledFeatures) {
- EXPECT_TRUE(requiredFeaturesSet.count(enabledFeature) > 0);
+ native::SupportedFeatures enabledFeatures;
+ deviceBase->APIGetFeatures(&enabledFeatures);
+ ASSERT_EQ(requiredFeaturesSet.size(), enabledFeatures.featureCount);
+ for (uint32_t i = 0; i < enabledFeatures.featureCount; ++i) {
+ wgpu::FeatureName enabledFeature = enabledFeatures.features[i];
+ EXPECT_TRUE(requiredFeaturesSet.contains(enabledFeature));
}
};
diff --git a/src/dawn/tests/unittests/native/DeviceCreationTests.cpp b/src/dawn/tests/unittests/native/DeviceCreationTests.cpp
index 4a1efec..cc62cd0 100644
--- a/src/dawn/tests/unittests/native/DeviceCreationTests.cpp
+++ b/src/dawn/tests/unittests/native/DeviceCreationTests.cpp
@@ -168,6 +168,11 @@
wgpu::FeatureName enabledFeature;
device.EnumerateFeatures(&enabledFeature);
EXPECT_EQ(enabledFeature, featureName);
+
+ wgpu::SupportedFeatures supportedFeatures;
+ device.GetFeatures(&supportedFeatures);
+ ASSERT_EQ(1u, supportedFeatures.featureCount);
+ EXPECT_EQ(enabledFeature, supportedFeatures.features[0]);
}
// Test creating device with AllowUnsafeApis enabled in device toggle descriptor will
@@ -188,6 +193,11 @@
wgpu::FeatureName enabledFeature;
device.EnumerateFeatures(&enabledFeature);
EXPECT_EQ(enabledFeature, featureName);
+
+ wgpu::SupportedFeatures supportedFeatures;
+ device.GetFeatures(&supportedFeatures);
+ ASSERT_EQ(1u, supportedFeatures.featureCount);
+ EXPECT_EQ(enabledFeature, supportedFeatures.features[0]);
}
// Test on adapter with AllowUnsafeApis disabled.
@@ -199,6 +209,11 @@
wgpu::FeatureName enabledFeature;
device.EnumerateFeatures(&enabledFeature);
EXPECT_EQ(enabledFeature, featureName);
+
+ wgpu::SupportedFeatures supportedFeatures;
+ device.GetFeatures(&supportedFeatures);
+ ASSERT_EQ(1u, supportedFeatures.featureCount);
+ EXPECT_EQ(enabledFeature, supportedFeatures.features[0]);
}
}
diff --git a/src/dawn/tests/unittests/wire/WireAdapterTests.cpp b/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
index b4b42bc..e242e5e 100644
--- a/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
@@ -183,15 +183,17 @@
return WGPUStatus_Success;
})));
- EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
- .WillOnce(Return(fakeFeatures.size()));
-
- EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, NotNull()))
- .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
+ EXPECT_CALL(api, DeviceGetFeatures(apiDevice, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* supportedFeatures) {
+ const size_t count = fakeFeatures.size();
+ WGPUFeatureName* features = new WGPUFeatureName[count];
+ uint32_t index = 0;
for (wgpu::FeatureName feature : fakeFeatures) {
- *(features++) = static_cast<WGPUFeatureName>(feature);
+ features[index++] = static_cast<WGPUFeatureName>(feature);
}
- return fakeFeatures.size();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = features;
+ return WGPUStatus_Success;
})));
// The backend device should still not be known by the wire server since the
@@ -220,13 +222,13 @@
fakeLimits.limits.maxTextureDimension1D);
EXPECT_EQ(limits.limits.maxVertexAttributes, fakeLimits.limits.maxVertexAttributes);
- std::vector<wgpu::FeatureName> features;
- features.resize(device.EnumerateFeatures(nullptr));
- ASSERT_EQ(features.size(), fakeFeatures.size());
- EXPECT_EQ(device.EnumerateFeatures(&features[0]), features.size());
+ wgpu::SupportedFeatures supportedFeatures;
+ device.GetFeatures(&supportedFeatures);
+ ASSERT_EQ(supportedFeatures.featureCount, fakeFeatures.size());
std::unordered_set<wgpu::FeatureName> featureSet(fakeFeatures);
- for (wgpu::FeatureName feature : features) {
+ for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
+ wgpu::FeatureName feature = supportedFeatures.features[i];
EXPECT_EQ(featureSet.erase(feature), 1u);
}
})));
@@ -265,15 +267,16 @@
WGPUDevice apiDevice = api.GetNewDevice();
EXPECT_CALL(api, OnAdapterRequestDevice(apiAdapter, NotNull(), _))
.WillOnce(InvokeWithoutArgs([&] {
- EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
- .WillOnce(Return(fakeFeatures.size()));
-
- EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, NotNull()))
- .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
+ EXPECT_CALL(api, DeviceGetFeatures(apiDevice, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* supportedFeatures) {
+ const size_t count = fakeFeatures.size();
+ WGPUFeatureName* features = new WGPUFeatureName[count];
+ uint32_t index = 0;
for (wgpu::FeatureName feature : fakeFeatures) {
- *(features++) = static_cast<WGPUFeatureName>(feature);
+ features[index++] = static_cast<WGPUFeatureName>(feature);
}
- return fakeFeatures.size();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = features;
})));
// The device was actually created, but the wire didn't support its features.
@@ -349,15 +352,16 @@
return WGPUStatus_Success;
})));
- EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
- .WillOnce(Return(fakeFeatures.size()));
-
- EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, NotNull()))
- .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
+ EXPECT_CALL(api, DeviceGetFeatures(apiDevice, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* supportedFeatures) {
+ const size_t count = fakeFeatures.size();
+ WGPUFeatureName* features = new WGPUFeatureName[count];
+ uint32_t index = 0;
for (wgpu::FeatureName feature : fakeFeatures) {
- *(features++) = static_cast<WGPUFeatureName>(feature);
+ features[index++] = static_cast<WGPUFeatureName>(feature);
}
- return fakeFeatures.size();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = features;
})));
api.CallAdapterRequestDeviceCallback(apiAdapter, WGPURequestDeviceStatus_Success,
diff --git a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
index a2950f7..92a32de 100644
--- a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
@@ -161,15 +161,16 @@
return WGPUStatus_Success;
})));
- EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
- .WillOnce(Return(fakeFeatures.size()));
-
- EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
- .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
+ EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* supportedFeatures) {
+ const size_t count = fakeFeatures.size();
+ WGPUFeatureName* features = new WGPUFeatureName[count];
+ uint32_t index = 0;
for (WGPUFeatureName feature : fakeFeatures) {
- *(features++) = feature;
+ features[index++] = feature;
}
- return fakeFeatures.size();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = features;
})));
api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Success,
apiAdapter, kEmptyOutputStringView);
@@ -204,13 +205,13 @@
fakeLimits.limits.maxTextureDimension1D);
EXPECT_EQ(limits.limits.maxVertexAttributes, fakeLimits.limits.maxVertexAttributes);
- std::vector<WGPUFeatureName> features;
- features.resize(wgpuAdapterEnumerateFeatures(adapter, nullptr));
- ASSERT_EQ(features.size(), fakeFeatures.size());
- EXPECT_EQ(wgpuAdapterEnumerateFeatures(adapter, &features[0]), features.size());
+ WGPUSupportedFeatures supportedFeatures;
+ wgpuAdapterGetFeatures(adapter, &supportedFeatures);
+ ASSERT_EQ(supportedFeatures.featureCount, fakeFeatures.size());
std::unordered_set<WGPUFeatureName> featureSet(fakeFeatures);
- for (WGPUFeatureName feature : features) {
+ for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
+ WGPUFeatureName feature = supportedFeatures.features[i];
EXPECT_EQ(featureSet.erase(feature), 1u);
}
})));
@@ -299,15 +300,16 @@
return WGPUStatus_Success;
})));
- EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
- .WillOnce(Return(fakeFeatures.size()));
-
- EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
- .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
+ EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* supportedFeatures) {
+ const size_t count = fakeFeatures.size();
+ WGPUFeatureName* features = new WGPUFeatureName[count];
+ uint32_t index = 0;
for (WGPUFeatureName feature : fakeFeatures) {
- *(features++) = feature;
+ features[index++] = feature;
}
- return fakeFeatures.size();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = features;
})));
api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Success,
apiAdapter, kEmptyOutputStringView);
@@ -396,15 +398,16 @@
return WGPUStatus_Success;
})));
- EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
- .WillOnce(Return(fakeFeatures.size()));
-
- EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
- .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
+ EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* supportedFeatures) {
+ const size_t count = fakeFeatures.size();
+ WGPUFeatureName* features = new WGPUFeatureName[count];
+ uint32_t index = 0;
for (WGPUFeatureName feature : fakeFeatures) {
- *(features++) = feature;
+ features[index++] = feature;
}
- return fakeFeatures.size();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = features;
})));
api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Success,
apiAdapter, kEmptyOutputStringView);
@@ -418,10 +421,10 @@
EXPECT_CALL(mockCb,
Call(WGPURequestAdapterStatus_Success, NotNull(), EmptySizedString(), nullptr))
.WillOnce(WithArg<1>(Invoke([&](WGPUAdapter adapter) {
- WGPUFeatureName feature;
- ASSERT_EQ(wgpuAdapterEnumerateFeatures(adapter, nullptr), 1u);
- wgpuAdapterEnumerateFeatures(adapter, &feature);
- EXPECT_EQ(feature, WGPUFeatureName_Depth32FloatStencil8);
+ WGPUSupportedFeatures supportedFeatures;
+ wgpuAdapterGetFeatures(adapter, &supportedFeatures);
+ EXPECT_EQ(supportedFeatures.featureCount, 1u);
+ EXPECT_EQ(supportedFeatures.features[0], WGPUFeatureName_Depth32FloatStencil8);
})));
FlushCallbacks();
diff --git a/src/dawn/tests/unittests/wire/WireTest.cpp b/src/dawn/tests/unittests/wire/WireTest.cpp
index 7aeba35..8d653bd 100644
--- a/src/dawn/tests/unittests/wire/WireTest.cpp
+++ b/src/dawn/tests/unittests/wire/WireTest.cpp
@@ -118,9 +118,11 @@
return WGPUStatus_Success;
})));
- EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
- .WillOnce(Return(0))
- .WillOnce(Return(0));
+ EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* features) {
+ features->featureCount = 0;
+ return WGPUStatus_Success;
+ })));
api.CallInstanceRequestAdapter2Callback(apiInstance, WGPURequestAdapterStatus_Success,
apiAdapter, kEmptyOutputStringView);
@@ -167,9 +169,11 @@
return WGPUStatus_Success;
})));
- EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
- .WillOnce(Return(0))
- .WillOnce(Return(0));
+ EXPECT_CALL(api, DeviceGetFeatures(apiDevice, NotNull()))
+ .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* features) {
+ features->featureCount = 0;
+ return WGPUStatus_Success;
+ })));
api.CallAdapterRequestDevice2Callback(apiAdapter, WGPURequestDeviceStatus_Success,
apiDevice, kEmptyOutputStringView);
diff --git a/src/dawn/wire/client/Adapter.cpp b/src/dawn/wire/client/Adapter.cpp
index 8ed8052..2547eac 100644
--- a/src/dawn/wire/client/Adapter.cpp
+++ b/src/dawn/wire/client/Adapter.cpp
@@ -154,6 +154,10 @@
return mLimitsAndFeatures.EnumerateFeatures(features);
}
+void Adapter::GetFeatures(WGPUSupportedFeatures* features) const {
+ mLimitsAndFeatures.ToSupportedFeatures(features);
+}
+
void Adapter::SetLimits(const WGPUSupportedLimits* limits) {
return mLimitsAndFeatures.SetLimits(limits);
}
@@ -390,3 +394,8 @@
WGPUDrmFormatCapabilities capabilities) {
delete[] capabilities.properties;
}
+
+DAWN_WIRE_EXPORT void wgpuDawnWireClientSupportedFeaturesFreeMembers(
+ WGPUSupportedFeatures supportedFeatures) {
+ delete[] supportedFeatures.features;
+}
diff --git a/src/dawn/wire/client/Adapter.h b/src/dawn/wire/client/Adapter.h
index 743598a..c21d7f2 100644
--- a/src/dawn/wire/client/Adapter.h
+++ b/src/dawn/wire/client/Adapter.h
@@ -52,6 +52,7 @@
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
void SetInfo(const WGPUAdapterInfo* info);
WGPUStatus GetInfo(WGPUAdapterInfo* info) const;
+ void GetFeatures(WGPUSupportedFeatures* 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 8923e75..329dd6c 100644
--- a/src/dawn/wire/client/Device.cpp
+++ b/src/dawn/wire/client/Device.cpp
@@ -341,6 +341,10 @@
return mLimitsAndFeatures.EnumerateFeatures(features);
}
+void Device::GetFeatures(WGPUSupportedFeatures* features) const {
+ mLimitsAndFeatures.ToSupportedFeatures(features);
+}
+
void Device::SetLimits(const WGPUSupportedLimits* limits) {
return mLimitsAndFeatures.SetLimits(limits);
}
diff --git a/src/dawn/wire/client/Device.h b/src/dawn/wire/client/Device.h
index c7503e2..baf70de 100644
--- a/src/dawn/wire/client/Device.h
+++ b/src/dawn/wire/client/Device.h
@@ -98,6 +98,7 @@
WGPUStatus GetLimits(WGPUSupportedLimits* limits) const;
bool HasFeature(WGPUFeatureName feature) const;
size_t EnumerateFeatures(WGPUFeatureName* features) const;
+ void GetFeatures(WGPUSupportedFeatures* features) const;
WGPUAdapter GetAdapter() const;
WGPUQueue GetQueue();
diff --git a/src/dawn/wire/client/LimitsAndFeatures.cpp b/src/dawn/wire/client/LimitsAndFeatures.cpp
index 612890a..803480a 100644
--- a/src/dawn/wire/client/LimitsAndFeatures.cpp
+++ b/src/dawn/wire/client/LimitsAndFeatures.cpp
@@ -84,6 +84,29 @@
return mFeatures.size();
}
+void LimitsAndFeatures::ToSupportedFeatures(WGPUSupportedFeatures* supportedFeatures) const {
+ if (!supportedFeatures) {
+ return;
+ }
+
+ const size_t count = mFeatures.size();
+ supportedFeatures->featureCount = count;
+ supportedFeatures->features = nullptr;
+
+ if (count == 0) {
+ return;
+ }
+
+ // This will be freed by wgpuSupportedFeaturesFreeMembers.
+ WGPUFeatureName* features = new WGPUFeatureName[count];
+ uint32_t index = 0;
+ for (WGPUFeatureName f : mFeatures) {
+ features[index++] = f;
+ }
+ DAWN_ASSERT(index == count);
+ supportedFeatures->features = features;
+}
+
void LimitsAndFeatures::SetLimits(const WGPUSupportedLimits* limits) {
DAWN_ASSERT(limits != nullptr);
mLimits = *limits;
diff --git a/src/dawn/wire/client/LimitsAndFeatures.h b/src/dawn/wire/client/LimitsAndFeatures.h
index 5846a58..4c4933f 100644
--- a/src/dawn/wire/client/LimitsAndFeatures.h
+++ b/src/dawn/wire/client/LimitsAndFeatures.h
@@ -42,6 +42,7 @@
WGPUStatus GetLimits(WGPUSupportedLimits* limits) const;
bool HasFeature(WGPUFeatureName feature) const;
size_t EnumerateFeatures(WGPUFeatureName* features) const;
+ void ToSupportedFeatures(WGPUSupportedFeatures* supportedFeatures) const;
void SetLimits(const WGPUSupportedLimits* limits);
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
diff --git a/src/dawn/wire/server/ServerAdapter.cpp b/src/dawn/wire/server/ServerAdapter.cpp
index 8d4c3c8..65c2755 100644
--- a/src/dawn/wire/server/ServerAdapter.cpp
+++ b/src/dawn/wire/server/ServerAdapter.cpp
@@ -97,17 +97,15 @@
return;
}
- std::vector<WGPUFeatureName> features;
-
- size_t featuresCount = mProcs.deviceEnumerateFeatures(device, nullptr);
- features.resize(featuresCount);
- mProcs.deviceEnumerateFeatures(device, features.data());
+ WGPUSupportedFeatures supportedFeatures;
+ mProcs.deviceGetFeatures(device, &supportedFeatures);
// The client should only be able to request supported features, so all enumerated
// features that were enabled must also be supported by the wire.
// Note: We fail the callback here, instead of immediately upon receiving
// the request to preserve callback ordering.
- for (WGPUFeatureName f : features) {
+ for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
+ WGPUFeatureName f = supportedFeatures.features[i];
if (!IsFeatureSupported(f)) {
// Release the device.
mProcs.deviceRelease(device);
@@ -120,8 +118,8 @@
}
}
- cmd.featuresCount = features.size();
- cmd.features = features.data();
+ cmd.featuresCount = supportedFeatures.featureCount;
+ cmd.features = supportedFeatures.features;
// Query and report the adapter limits, including DawnExperimentalSubgroupLimits and
// DawnExperimentalImmediateDataLimits. Reporting to client.
@@ -153,6 +151,7 @@
reservation->info->self = reservation.AsHandle();
SetForwardingDeviceCallbacks(reservation);
SerializeCommand(cmd);
+ mProcs.supportedFeaturesFreeMembers(supportedFeatures);
}
} // namespace dawn::wire::server
diff --git a/src/dawn/wire/server/ServerInstance.cpp b/src/dawn/wire/server/ServerInstance.cpp
index 4e1b883..02b998c 100644
--- a/src/dawn/wire/server/ServerInstance.cpp
+++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -25,11 +25,7 @@
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <algorithm>
-#include <vector>
-
#include "dawn/common/StringViewUtils.h"
-#include "dawn/wire/SupportedFeatures.h"
#include "dawn/wire/server/ObjectStorage.h"
#include "dawn/wire/server/Server.h"
@@ -87,17 +83,10 @@
}
// Query and report the adapter supported features.
- std::vector<WGPUFeatureName> features;
-
- size_t featuresCount = mProcs.adapterEnumerateFeatures(adapter, nullptr);
- features.resize(featuresCount);
- mProcs.adapterEnumerateFeatures(adapter, features.data());
-
- // Hide features the wire cannot support.
- auto it = std::partition(features.begin(), features.end(), IsFeatureSupported);
-
- cmd.featuresCount = std::distance(features.begin(), it);
- cmd.features = features.data();
+ WGPUSupportedFeatures supportedFeatures;
+ mProcs.adapterGetFeatures(adapter, &supportedFeatures);
+ cmd.featuresCount = supportedFeatures.featureCount;
+ cmd.features = supportedFeatures.features;
// Query and report the adapter info.
WGPUAdapterInfo info = {};
@@ -149,6 +138,7 @@
SerializeCommand(cmd);
mProcs.adapterInfoFreeMembers(info);
mProcs.adapterPropertiesMemoryHeapsFreeMembers(memoryHeapProperties);
+ mProcs.supportedFeaturesFreeMembers(supportedFeatures);
}
} // namespace dawn::wire::server
diff --git a/tools/android/BUILD.gn b/tools/android/BUILD.gn
index b25225b..815442d 100644
--- a/tools/android/BUILD.gn
+++ b/tools/android/BUILD.gn
@@ -182,6 +182,7 @@
"java/android/dawn/StorageTextureAccess.kt",
"java/android/dawn/StorageTextureBindingLayout.kt",
"java/android/dawn/StoreOp.kt",
+ "java/android/dawn/SupportedFeatures.kt",
"java/android/dawn/SupportedLimits.kt",
"java/android/dawn/Surface.kt",
"java/android/dawn/SurfaceCapabilities.kt",