Reland "Partial revert of webgpu.h: Add Adapter and Device GetFeatures() methods"

This reverts commit df6873d0646714d9ff284848d84958e7412cd809.

Reason for revert: flaky crashes on Chrome startup http://crbug.com/368672123#comment10

Original change's description:
> Revert "Partial revert of webgpu.h: Add Adapter and Device GetFeatures() methods"
>
> This reverts commit afd7389710ac47caed7cde667499877c6ccae327.
>
> Reason for revert: https://chromium-review.googlesource.com/c/chromium/src/+/5958567 has landed
>
> Original change's description:
> > Partial revert of webgpu.h: Add Adapter and Device GetFeatures() methods
> >
> > Commit 78a100c8c999883350ea6e5a724119289d3ad45b changes
> > dawn::wire::server to use GetFeatures to gather features instead of
> > EnumerateFeatures. This breaks the filtering of features in Chromium's
> > webgpu_cmd_decoder_impl.cc which proxies EnumerateFeatures but doesn't
> > proxy GetFeatures yet. Before this code is relanded, Chromium must
> > implement proxying of GetFeatures.
> >
> > Bug: 368672123
> > Change-Id: I738d1d3f7b5342e73dfa59b63d42bb589c12ff41
> > Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/213674
> > Commit-Queue: Corentin Wallez <cwallez@chromium.org>
> > Reviewed-by: Kai Ninomiya <kainino@chromium.org>
> > Commit-Queue: Kai Ninomiya <kainino@chromium.org>
>
> TBR=cwallez@chromium.org,kainino@chromium.org,dawn-scoped@luci-project-accounts.iam.gserviceaccount.com
>
> Change-Id: Ic659bcd271f3c95b578736d69cf5bdff10c40a18
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 368672123
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/213854
> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
> Commit-Queue: Fr <beaufort.francois@gmail.com>
> Reviewed-by: Fr <beaufort.francois@gmail.com>

# Not skipping CQ checks because this is a reland.

Bug: 368672123
Change-Id: If40cc5c979ded3c47d400b9991cc91c2bb5adf02
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/214114
Auto-Submit: Yuly Novikov <ynovikov@chromium.org>
Reviewed-by: Peter McNeeley <petermcneeley@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/dawn/tests/unittests/wire/WireAdapterTests.cpp b/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
index e242e5e..b4b42bc 100644
--- a/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
@@ -183,17 +183,15 @@
                     return WGPUStatus_Success;
                 })));
 
-            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;
+            EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
+                .WillOnce(Return(fakeFeatures.size()));
+
+            EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, NotNull()))
+                .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                     for (wgpu::FeatureName feature : fakeFeatures) {
-                        features[index++] = static_cast<WGPUFeatureName>(feature);
+                        *(features++) = static_cast<WGPUFeatureName>(feature);
                     }
-                    supportedFeatures->featureCount = count;
-                    supportedFeatures->features = features;
-                    return WGPUStatus_Success;
+                    return fakeFeatures.size();
                 })));
 
             // The backend device should still not be known by the wire server since the
@@ -222,13 +220,13 @@
                           fakeLimits.limits.maxTextureDimension1D);
                 EXPECT_EQ(limits.limits.maxVertexAttributes, fakeLimits.limits.maxVertexAttributes);
 
-                wgpu::SupportedFeatures supportedFeatures;
-                device.GetFeatures(&supportedFeatures);
-                ASSERT_EQ(supportedFeatures.featureCount, fakeFeatures.size());
+                std::vector<wgpu::FeatureName> features;
+                features.resize(device.EnumerateFeatures(nullptr));
+                ASSERT_EQ(features.size(), fakeFeatures.size());
+                EXPECT_EQ(device.EnumerateFeatures(&features[0]), features.size());
 
                 std::unordered_set<wgpu::FeatureName> featureSet(fakeFeatures);
-                for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
-                    wgpu::FeatureName feature = supportedFeatures.features[i];
+                for (wgpu::FeatureName feature : features) {
                     EXPECT_EQ(featureSet.erase(feature), 1u);
                 }
             })));
@@ -267,16 +265,15 @@
     WGPUDevice apiDevice = api.GetNewDevice();
     EXPECT_CALL(api, OnAdapterRequestDevice(apiAdapter, NotNull(), _))
         .WillOnce(InvokeWithoutArgs([&] {
-            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;
+            EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
+                .WillOnce(Return(fakeFeatures.size()));
+
+            EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, NotNull()))
+                .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                     for (wgpu::FeatureName feature : fakeFeatures) {
-                        features[index++] = static_cast<WGPUFeatureName>(feature);
+                        *(features++) = static_cast<WGPUFeatureName>(feature);
                     }
-                    supportedFeatures->featureCount = count;
-                    supportedFeatures->features = features;
+                    return fakeFeatures.size();
                 })));
 
             // The device was actually created, but the wire didn't support its features.
@@ -352,16 +349,15 @@
                     return WGPUStatus_Success;
                 })));
 
-            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;
+            EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
+                .WillOnce(Return(fakeFeatures.size()));
+
+            EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, NotNull()))
+                .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                     for (wgpu::FeatureName feature : fakeFeatures) {
-                        features[index++] = static_cast<WGPUFeatureName>(feature);
+                        *(features++) = static_cast<WGPUFeatureName>(feature);
                     }
-                    supportedFeatures->featureCount = count;
-                    supportedFeatures->features = features;
+                    return fakeFeatures.size();
                 })));
 
             api.CallAdapterRequestDeviceCallback(apiAdapter, WGPURequestDeviceStatus_Success,
diff --git a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
index 92a32de..a2950f7 100644
--- a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
@@ -161,16 +161,15 @@
                     return WGPUStatus_Success;
                 })));
 
-            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;
+            EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
+                .WillOnce(Return(fakeFeatures.size()));
+
+            EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
+                .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                     for (WGPUFeatureName feature : fakeFeatures) {
-                        features[index++] = feature;
+                        *(features++) = feature;
                     }
-                    supportedFeatures->featureCount = count;
-                    supportedFeatures->features = features;
+                    return fakeFeatures.size();
                 })));
             api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Success,
                                                    apiAdapter, kEmptyOutputStringView);
@@ -205,13 +204,13 @@
                           fakeLimits.limits.maxTextureDimension1D);
                 EXPECT_EQ(limits.limits.maxVertexAttributes, fakeLimits.limits.maxVertexAttributes);
 
-                WGPUSupportedFeatures supportedFeatures;
-                wgpuAdapterGetFeatures(adapter, &supportedFeatures);
-                ASSERT_EQ(supportedFeatures.featureCount, fakeFeatures.size());
+                std::vector<WGPUFeatureName> features;
+                features.resize(wgpuAdapterEnumerateFeatures(adapter, nullptr));
+                ASSERT_EQ(features.size(), fakeFeatures.size());
+                EXPECT_EQ(wgpuAdapterEnumerateFeatures(adapter, &features[0]), features.size());
 
                 std::unordered_set<WGPUFeatureName> featureSet(fakeFeatures);
-                for (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
-                    WGPUFeatureName feature = supportedFeatures.features[i];
+                for (WGPUFeatureName feature : features) {
                     EXPECT_EQ(featureSet.erase(feature), 1u);
                 }
             })));
@@ -300,16 +299,15 @@
                     return WGPUStatus_Success;
                 })));
 
-            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;
+            EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
+                .WillOnce(Return(fakeFeatures.size()));
+
+            EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
+                .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                     for (WGPUFeatureName feature : fakeFeatures) {
-                        features[index++] = feature;
+                        *(features++) = feature;
                     }
-                    supportedFeatures->featureCount = count;
-                    supportedFeatures->features = features;
+                    return fakeFeatures.size();
                 })));
             api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Success,
                                                    apiAdapter, kEmptyOutputStringView);
@@ -398,16 +396,15 @@
                     return WGPUStatus_Success;
                 })));
 
-            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;
+            EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
+                .WillOnce(Return(fakeFeatures.size()));
+
+            EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
+                .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                     for (WGPUFeatureName feature : fakeFeatures) {
-                        features[index++] = feature;
+                        *(features++) = feature;
                     }
-                    supportedFeatures->featureCount = count;
-                    supportedFeatures->features = features;
+                    return fakeFeatures.size();
                 })));
             api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Success,
                                                    apiAdapter, kEmptyOutputStringView);
@@ -421,10 +418,10 @@
         EXPECT_CALL(mockCb,
                     Call(WGPURequestAdapterStatus_Success, NotNull(), EmptySizedString(), nullptr))
             .WillOnce(WithArg<1>(Invoke([&](WGPUAdapter adapter) {
-                WGPUSupportedFeatures supportedFeatures;
-                wgpuAdapterGetFeatures(adapter, &supportedFeatures);
-                EXPECT_EQ(supportedFeatures.featureCount, 1u);
-                EXPECT_EQ(supportedFeatures.features[0], WGPUFeatureName_Depth32FloatStencil8);
+                WGPUFeatureName feature;
+                ASSERT_EQ(wgpuAdapterEnumerateFeatures(adapter, nullptr), 1u);
+                wgpuAdapterEnumerateFeatures(adapter, &feature);
+                EXPECT_EQ(feature, WGPUFeatureName_Depth32FloatStencil8);
             })));
 
         FlushCallbacks();
diff --git a/src/dawn/tests/unittests/wire/WireTest.cpp b/src/dawn/tests/unittests/wire/WireTest.cpp
index 8d653bd..7aeba35 100644
--- a/src/dawn/tests/unittests/wire/WireTest.cpp
+++ b/src/dawn/tests/unittests/wire/WireTest.cpp
@@ -118,11 +118,9 @@
                 return WGPUStatus_Success;
             })));
 
-        EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull()))
-            .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* features) {
-                features->featureCount = 0;
-                return WGPUStatus_Success;
-            })));
+        EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
+            .WillOnce(Return(0))
+            .WillOnce(Return(0));
 
         api.CallInstanceRequestAdapter2Callback(apiInstance, WGPURequestAdapterStatus_Success,
                                                 apiAdapter, kEmptyOutputStringView);
@@ -169,11 +167,9 @@
                     return WGPUStatus_Success;
                 })));
 
-            EXPECT_CALL(api, DeviceGetFeatures(apiDevice, NotNull()))
-                .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedFeatures* features) {
-                    features->featureCount = 0;
-                    return WGPUStatus_Success;
-                })));
+            EXPECT_CALL(api, DeviceEnumerateFeatures(apiDevice, nullptr))
+                .WillOnce(Return(0))
+                .WillOnce(Return(0));
 
             api.CallAdapterRequestDevice2Callback(apiAdapter, WGPURequestDeviceStatus_Success,
                                                   apiDevice, kEmptyOutputStringView);
diff --git a/src/dawn/wire/server/ServerAdapter.cpp b/src/dawn/wire/server/ServerAdapter.cpp
index f8ffea5..8d4c3c8 100644
--- a/src/dawn/wire/server/ServerAdapter.cpp
+++ b/src/dawn/wire/server/ServerAdapter.cpp
@@ -97,15 +97,17 @@
         return;
     }
 
-    WGPUSupportedFeatures supportedFeatures;
-    mProcs.deviceGetFeatures(device, &supportedFeatures);
+    std::vector<WGPUFeatureName> features;
+
+    size_t featuresCount = mProcs.deviceEnumerateFeatures(device, nullptr);
+    features.resize(featuresCount);
+    mProcs.deviceEnumerateFeatures(device, features.data());
 
     // 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 (uint32_t i = 0; i < supportedFeatures.featureCount; ++i) {
-        WGPUFeatureName f = supportedFeatures.features[i];
+    for (WGPUFeatureName f : features) {
         if (!IsFeatureSupported(f)) {
             // Release the device.
             mProcs.deviceRelease(device);
@@ -114,13 +116,12 @@
             cmd.status = WGPURequestDeviceStatus_Error;
             cmd.message = ToOutputStringView("Requested feature not supported.");
             SerializeCommand(cmd);
-            mProcs.supportedFeaturesFreeMembers(supportedFeatures);
             return;
         }
     }
 
-    cmd.featuresCount = supportedFeatures.featureCount;
-    cmd.features = supportedFeatures.features;
+    cmd.featuresCount = features.size();
+    cmd.features = features.data();
 
     // Query and report the adapter limits, including DawnExperimentalSubgroupLimits and
     // DawnExperimentalImmediateDataLimits. Reporting to client.
@@ -145,7 +146,6 @@
         cmd.status = WGPURequestDeviceStatus_Unknown;
         cmd.message = ToOutputStringView("Destroyed before request was fulfilled.");
         SerializeCommand(cmd);
-        mProcs.supportedFeaturesFreeMembers(supportedFeatures);
         return;
     }
     DAWN_ASSERT(reservation.data != nullptr);
@@ -153,7 +153,6 @@
     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 02b998c..4e1b883 100644
--- a/src/dawn/wire/server/ServerInstance.cpp
+++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -25,7 +25,11 @@
 // 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"
 
@@ -83,10 +87,17 @@
     }
 
     // Query and report the adapter supported features.
-    WGPUSupportedFeatures supportedFeatures;
-    mProcs.adapterGetFeatures(adapter, &supportedFeatures);
-    cmd.featuresCount = supportedFeatures.featureCount;
-    cmd.features = supportedFeatures.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();
 
     // Query and report the adapter info.
     WGPUAdapterInfo info = {};
@@ -138,7 +149,6 @@
     SerializeCommand(cmd);
     mProcs.adapterInfoFreeMembers(info);
     mProcs.adapterPropertiesMemoryHeapsFreeMembers(memoryHeapProperties);
-    mProcs.supportedFeaturesFreeMembers(supportedFeatures);
 }
 
 }  // namespace dawn::wire::server