Add AdapterPropertiesVk

Add Vulkan specific adapter properties in order to pass
VkPhysicalDeviceProperties::driverVersion back into Chrome. This is used
on Android decide if Vulkan or GL should be used.

Bug: chromium:327457605
Change-Id: Ic6626683b0fdd1572c1d1889d3b06a7531f1ed64
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/178262
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Kyle Charbonneau <kylechar@google.com>
diff --git a/docs/dawn/features/adapter_properties.md b/docs/dawn/features/adapter_properties.md
index 147b239..90b1240 100644
--- a/docs/dawn/features/adapter_properties.md
+++ b/docs/dawn/features/adapter_properties.md
@@ -41,3 +41,16 @@
     uint32_t shaderModel;  // The D3D shader model
 };
 ```
+
+## Vulkan
+
+`wgpu::FeatureName::AdapterPropertiesVk` allows querying Vulkan information from the adapter.
+
+`wgpu::AdapterPropertiesVk` may be chained on `wgpu::AdapterProperties` in a call to `wgpu::Adapter::GetProperties` in order to query Vulkan information on that adapter.
+
+Adds `wgpu::AdapterPropertiesVk` which is a struct describing the D3D adapter.
+```
+struct AdapterPropertiesVk {
+    uint32_t driverVersion;  // The Vulkan driver version
+};
+```
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 8f41de2..9f7e882 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -2187,7 +2187,8 @@
             {"value": 1026, "name": "buffer map extended usages", "tags": ["dawn"]},
             {"value": 1027, "name": "adapter properties memory heaps", "tags": ["dawn"]},
             {"value": 1028, "name": "adapter properties D3D", "tags": ["dawn"]},
-            {"value": 1029, "name": "r8 unorm storage", "tags": ["dawn"]},
+            {"value": 1029, "name": "adapter properties vk", "tags": ["dawn"]},
+            {"value": 1030, "name": "r8 unorm storage", "tags": ["dawn"]},
 
             {"value": 1100, "name": "shared texture memory vk dedicated allocation", "tags": ["dawn", "native"]},
             {"value": 1101, "name": "shared texture memory a hardware buffer", "tags": ["dawn", "native"]},
@@ -3612,9 +3613,10 @@
             {"value": 1018, "name": "dawn experimental subgroup limits", "tags": ["dawn"]},
             {"value": 1019, "name": "adapter properties memory heaps", "tags": ["dawn"]},
             {"value": 1020, "name": "adapter properties D3D", "tags": ["dawn"]},
-            {"value": 1021, "name": "dawn compute pipeline full subgroups", "tags": ["dawn"]},
-            {"value": 1022, "name": "dawn wire WGSL control", "tags": ["dawn"]},
-            {"value": 1023, "name": "dawn WGSL blocklist", "tags": ["dawn", "native"]},
+            {"value": 1021, "name": "adapter properties vk", "tags": ["dawn"]},
+            {"value": 1022, "name": "dawn compute pipeline full subgroups", "tags": ["dawn"]},
+            {"value": 1023, "name": "dawn wire WGSL control", "tags": ["dawn"]},
+            {"value": 1024, "name": "dawn WGSL blocklist", "tags": ["dawn", "native"]},
 
             {"value": 1100, "name": "shared texture memory vk image descriptor", "tags": ["dawn", "native"]},
             {"value": 1101, "name": "shared texture memory vk dedicated allocation descriptor", "tags": ["dawn", "native"]},
@@ -4147,6 +4149,15 @@
             {"name": "shader model", "type": "uint32_t"}
         ]
     },
+    "adapter properties vk": {
+      "category": "structure",
+      "chained": "out",
+      "chain roots": ["adapter properties"],
+      "tags": ["dawn"],
+      "members": [
+          {"name": "driver version", "type": "uint32_t"}
+      ]
+    },
     "dawn buffer descriptor error info from wire client": {
         "category": "structure",
         "chained": "in",
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index f737392..4145b7c 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -130,6 +130,12 @@
         instance->ConsumedError(
             DAWN_VALIDATION_ERROR("Feature AdapterPropertiesD3D is not available."));
     }
+    if (unpacked.Get<AdapterPropertiesVk>() != nullptr &&
+        !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesVk)) {
+        instance->ConsumedError(
+            DAWN_VALIDATION_ERROR("Feature AdapterPropertiesVk is not available."));
+    }
+
     if (auto* powerPreferenceDesc = unpacked.Get<DawnAdapterPropertiesPowerPreference>()) {
         powerPreferenceDesc->powerPreference = mPowerPreference;
     }
diff --git a/src/dawn/native/Features.cpp b/src/dawn/native/Features.cpp
index 74a7216..e3697fa 100644
--- a/src/dawn/native/Features.cpp
+++ b/src/dawn/native/Features.cpp
@@ -295,6 +295,11 @@
       "https://dawn.googlesource.com/dawn/+/refs/heads/main/docs/dawn/features/"
       "adapter_properties.md",
       FeatureInfo::FeatureState::Stable}},
+    {Feature::AdapterPropertiesVk,
+     {"Support querying Vulkan info from the adapter.",
+      "https://dawn.googlesource.com/dawn/+/refs/heads/main/docs/dawn/features/"
+      "adapter_properties.md",
+      FeatureInfo::FeatureState::Stable}},
     {Feature::SharedBufferMemoryD3D12Resource,
      {"Support importing ID3D12Resource as shared buffer memory.",
       "https://dawn.googlesource.com/dawn/+/refs/heads/main/docs/dawn/features/shared_buffer.md",
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
index 4f9939a..e16aa83 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
@@ -341,6 +341,7 @@
 
     EnableFeature(Feature::SurfaceCapabilities);
     EnableFeature(Feature::TransientAttachments);
+    EnableFeature(Feature::AdapterPropertiesVk);
 
     // Enable ChromiumExperimentalSubgroups feature if:
     // 1. Vulkan API version is 1.1 or later, and
@@ -934,6 +935,9 @@
             }
         }
     }
+    if (auto* vkProperties = properties.Get<AdapterPropertiesVk>()) {
+        vkProperties->driverVersion = mDeviceInfo.properties.driverVersion;
+    }
 }
 
 }  // namespace dawn::native::vulkan
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index 17095c6..b2b0f93 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -573,6 +573,7 @@
     "end2end/AdapterCreationTests.cpp",
     "end2end/AdapterEnumerationTests.cpp",
     "end2end/AdapterPropertiesD3DTests.cpp",
+    "end2end/AdapterPropertiesVkTests.cpp",
     "end2end/BasicTests.cpp",
     "end2end/BindGroupTests.cpp",
     "end2end/BufferHostMappedPointerTests.cpp",
diff --git a/src/dawn/tests/end2end/AdapterPropertiesVkTests.cpp b/src/dawn/tests/end2end/AdapterPropertiesVkTests.cpp
new file mode 100644
index 0000000..79f1b11
--- /dev/null
+++ b/src/dawn/tests/end2end/AdapterPropertiesVkTests.cpp
@@ -0,0 +1,55 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// 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 "dawn/tests/DawnTest.h"
+
+namespace dawn {
+namespace {
+
+class AdapterPropertiesVkTest : public DawnTest {};
+
+// TODO(dawn:2257) test that is is invalid to request AdapterPropertiesVk if the
+// feature is not available.
+
+// Test that it is possible to query the Vulkan properties, and it is populated with a valid data.
+TEST_P(AdapterPropertiesVkTest, GetVkProperties) {
+    DAWN_TEST_UNSUPPORTED_IF(!adapter.HasFeature(wgpu::FeatureName::AdapterPropertiesVk));
+
+    wgpu::AdapterProperties properties;
+    wgpu::AdapterPropertiesVk vkProperties;
+    properties.nextInChain = &vkProperties;
+
+    adapter.GetProperties(&properties);
+
+    // The driver version should be set to something but it depends on the hardware.
+    EXPECT_NE(vkProperties.driverVersion, 0u);
+}
+
+DAWN_INSTANTIATE_TEST(AdapterPropertiesVkTest, VulkanBackend());
+
+}  // anonymous namespace
+}  // namespace dawn
diff --git a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
index bdf6e34..52155fd 100644
--- a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
@@ -226,9 +226,14 @@
     fakeD3DProperties.chain.sType = WGPUSType_AdapterPropertiesD3D;
     fakeD3DProperties.shaderModel = 61;
 
+    WGPUAdapterPropertiesVk fakeVkProperties = {};
+    fakeVkProperties.chain.sType = WGPUSType_AdapterPropertiesVk;
+    fakeVkProperties.driverVersion = 0x801F6000;
+
     std::initializer_list<WGPUFeatureName> fakeFeatures = {
         WGPUFeatureName_AdapterPropertiesMemoryHeaps,
         WGPUFeatureName_AdapterPropertiesD3D,
+        WGPUFeatureName_AdapterPropertiesVk,
     };
 
     // Expect the server to receive the message. Then, mock a fake reply.
@@ -258,6 +263,10 @@
                                 *reinterpret_cast<WGPUAdapterPropertiesD3D*>(chain) =
                                     fakeD3DProperties;
                                 break;
+                            case WGPUSType_AdapterPropertiesVk:
+                                *reinterpret_cast<WGPUAdapterPropertiesVk*>(chain) =
+                                    fakeVkProperties;
+                                break;
                             default:
                                 FAIL() << "Unexpected chain";
                         }
@@ -324,6 +333,14 @@
                 wgpuAdapterGetProperties(adapter, &properties);
                 // Expect them to match.
                 EXPECT_EQ(d3dProperties.shaderModel, fakeD3DProperties.shaderModel);
+
+                // Get the Vulkan properties.
+                WGPUAdapterPropertiesVk vkProperties = {};
+                vkProperties.chain.sType = WGPUSType_AdapterPropertiesVk;
+                properties.nextInChain = &vkProperties.chain;
+                wgpuAdapterGetProperties(adapter, &properties);
+                // Expect them to match.
+                EXPECT_EQ(vkProperties.driverVersion, fakeVkProperties.driverVersion);
             })));
 
         FlushCallbacks();
diff --git a/src/dawn/wire/SupportedFeatures.cpp b/src/dawn/wire/SupportedFeatures.cpp
index 5447227..e5431ee 100644
--- a/src/dawn/wire/SupportedFeatures.cpp
+++ b/src/dawn/wire/SupportedFeatures.cpp
@@ -95,6 +95,7 @@
         case WGPUFeatureName_FramebufferFetch:
         case WGPUFeatureName_AdapterPropertiesMemoryHeaps:
         case WGPUFeatureName_AdapterPropertiesD3D:
+        case WGPUFeatureName_AdapterPropertiesVk:
         case WGPUFeatureName_R8UnormStorage:
             return true;
     }
diff --git a/src/dawn/wire/client/Adapter.cpp b/src/dawn/wire/client/Adapter.cpp
index 3d3e367..f5605b3 100644
--- a/src/dawn/wire/client/Adapter.cpp
+++ b/src/dawn/wire/client/Adapter.cpp
@@ -149,6 +149,11 @@
                 mD3DProperties.shaderModel = d3dProperties->shaderModel;
                 break;
             }
+            case WGPUSType_AdapterPropertiesVk: {
+                auto* vkProperties = reinterpret_cast<WGPUAdapterPropertiesVk*>(chain);
+                mVkProperties.driverVersion = vkProperties->driverVersion;
+                break;
+            }
             default:
                 DAWN_UNREACHABLE();
                 break;
@@ -179,6 +184,11 @@
                 d3dProperties->shaderModel = mD3DProperties.shaderModel;
                 break;
             }
+            case WGPUSType_AdapterPropertiesVk: {
+                auto* vkProperties = reinterpret_cast<WGPUAdapterPropertiesVk*>(chain);
+                vkProperties->driverVersion = mVkProperties.driverVersion;
+                break;
+            }
             default:
                 break;
         }
diff --git a/src/dawn/wire/client/Adapter.h b/src/dawn/wire/client/Adapter.h
index 2ff6795..b89f7dd 100644
--- a/src/dawn/wire/client/Adapter.h
+++ b/src/dawn/wire/client/Adapter.h
@@ -67,6 +67,7 @@
     WGPUAdapterProperties mProperties;
     std::vector<WGPUMemoryHeapInfo> mMemoryHeapInfo;
     WGPUAdapterPropertiesD3D mD3DProperties;
+    WGPUAdapterPropertiesVk mVkProperties;
 };
 
 void ClientAdapterPropertiesFreeMembers(WGPUAdapterProperties);
diff --git a/src/dawn/wire/server/ServerInstance.cpp b/src/dawn/wire/server/ServerInstance.cpp
index bb09833..c25688e 100644
--- a/src/dawn/wire/server/ServerInstance.cpp
+++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -106,6 +106,14 @@
         propertiesChain = &(*propertiesChain)->next;
     }
 
+    // Query AdapterPropertiesVk if the feature is supported.
+    WGPUAdapterPropertiesVk vkProperties = {};
+    vkProperties.chain.sType = WGPUSType_AdapterPropertiesVk;
+    if (mProcs.adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesVk)) {
+        *propertiesChain = &vkProperties.chain;
+        propertiesChain = &(*propertiesChain)->next;
+    }
+
     mProcs.adapterGetProperties(adapter, &properties);
     cmd.properties = &properties;