[dawn][emscripten] Implement GetFeatures in Emscripten.

- Also removes EnumerateFeatures.

Bug: 368672123
Change-Id: I79fc0a5c96af810e016cab1f94adb922263deeca
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/214274
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Auto-Submit: Loko Kung <lokokung@google.com>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
diff --git a/third_party/emdawnwebgpu/library_webgpu.js b/third_party/emdawnwebgpu/library_webgpu.js
index 7e4909b..1fabfeb 100644
--- a/third_party/emdawnwebgpu/library_webgpu.js
+++ b/third_party/emdawnwebgpu/library_webgpu.js
@@ -650,22 +650,24 @@
   // Methods of Adapter
   // --------------------------------------------------------------------------
 
-  wgpuAdapterEnumerateFeatures: (adapterPtr, featuresOutPtr) => {
+  wgpuAdapterGetFeatures__deps: ['malloc'],
+  wgpuAdapterGetFeatures: (adapterPtr, supportedFeatures) => {
     var adapter = WebGPU.getJsObject(adapterPtr);
 
+    // Always allocate enough space for all the features, though some may be unused.
+    var featuresPtr = _malloc(adapter.features.size * 4);
     var offset = 0;
     var numFeatures = 0;
     adapter.features.forEach(feature => {
       var featureEnumValue = WebGPU.FeatureNameString2Enum[feature];
       if (featureEnumValue !== undefined) {
-        if (featuresOutPtr !== 0) {
-          {{{ makeSetValue('featuresOutPtr', 'offset', 'featureEnumValue', 'i32') }}};
-          offset += 4;
-        }
+        {{{ makeSetValue('featuresPtr', 'offset', 'featureEnumValue', 'i32') }}};
+        offset += 4;
         numFeatures++;
       }
     });
-    return numFeatures;
+    {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.features, 'featuresPtr', '*') }}};
+    {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.featureCount, 'numFeatures', '*') }}};
   },
 
   wgpuAdapterGetInfo__deps: ['$stringToNewUTF8', '$lengthBytesUTF8'],
@@ -1740,22 +1742,24 @@
     WebGPU.getJsObject(devicePtr).destroy()
   },
 
-  wgpuDeviceEnumerateFeatures: (devicePtr, featuresOutPtr) => {
+  wgpuDeviceGetFeatures__deps: ['malloc'],
+  wgpuDeviceGetFeatures: (devicePtr, supportedFeatures) => {
     var device = WebGPU.getJsObject(devicePtr);
 
+    // Always allocate enough space for all the features, though some may be unused.
+    var featuresPtr = _malloc(device.features.size * 4);
     var offset = 0;
     var numFeatures = 0;
     device.features.forEach(feature => {
       var featureEnumValue = WebGPU.FeatureNameString2Enum[feature];
       if (featureEnumValue !== undefined) {
-        if (featuresOutPtr !== 0) {
-          {{{ makeSetValue('featuresOutPtr', 'offset', 'featureEnumValue', 'i32') }}};
-          offset += 4;
-        }
+        {{{ makeSetValue('featuresPtr', 'offset', 'featureEnumValue', 'i32') }}};
+        offset += 4;
         numFeatures++;
       }
     });
-    return numFeatures;
+    {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.features, 'featuresPtr', '*') }}};
+    {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.featureCount, 'numFeatures', '*') }}};
   },
 
   wgpuDeviceGetLimits: (devicePtr, limitsOutPtr) => {
diff --git a/third_party/emdawnwebgpu/webgpu.cpp b/third_party/emdawnwebgpu/webgpu.cpp
index 5bd625e1..5ed457c 100644
--- a/third_party/emdawnwebgpu/webgpu.cpp
+++ b/third_party/emdawnwebgpu/webgpu.cpp
@@ -1506,7 +1506,7 @@
 WGPU_OBJECTS(DEFINE_WGPU_DEFAULT_SETLABEL)
 
 // ----------------------------------------------------------------------------
-// Standalone (non-method) functions
+// FreeMember functions
 // ----------------------------------------------------------------------------
 
 void wgpuAdapterInfoFreeMembers(WGPUAdapterInfo value) {
@@ -1515,9 +1515,8 @@
   free(const_cast<char*>(value.vendor.data));
 }
 
-WGPUInstance wgpuCreateInstance([[maybe_unused]] const WGPUInstanceDescriptor* descriptor) {
-  assert(descriptor == nullptr);  // descriptor not implemented yet
-  return new WGPUInstanceImpl();
+void wgpuSupportedFeaturesFreeMembers(WGPUSupportedFeatures value) {
+  free(const_cast<WGPUFeatureName*>(value.features));
 }
 
 void wgpuSurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities) {
@@ -1525,6 +1524,16 @@
 }
 
 // ----------------------------------------------------------------------------
+// Standalone (non-method) functions
+// ----------------------------------------------------------------------------
+
+WGPUInstance wgpuCreateInstance(
+    [[maybe_unused]] const WGPUInstanceDescriptor* descriptor) {
+  assert(descriptor == nullptr);  // descriptor not implemented yet
+  return new WGPUInstanceImpl();
+}
+
+// ----------------------------------------------------------------------------
 // Methods of Adapter
 // ----------------------------------------------------------------------------