Vulkan: Better reflect Surface capabilities.

Fixed: 338601189
Bug: 42241264
Change-Id: I5da79bd30aa3c6932a6aef586939dcc12390b9d5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/187220
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index b2208f65..919b26b 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -2667,10 +2667,10 @@
         "category": "enum",
         "emscripten_no_enum_table": true,
         "values": [
-            {"value": 1, "name": "fifo"},
-            {"value": 2, "name": "fifo relaxed", "tags": ["upstream"]},
-            {"value": 3, "name": "immediate"},
-            {"value": 4, "name": "mailbox"}
+            {"value": 0, "name": "fifo"},
+            {"value": 1, "name": "fifo relaxed"},
+            {"value": 2, "name": "immediate"},
+            {"value": 3, "name": "mailbox"}
         ]
     },
     "programmable stage descriptor": {
diff --git a/src/dawn/native/d3d/SwapChainD3D.cpp b/src/dawn/native/d3d/SwapChainD3D.cpp
index 57b8502..83ccc28 100644
--- a/src/dawn/native/d3d/SwapChainD3D.cpp
+++ b/src/dawn/native/d3d/SwapChainD3D.cpp
@@ -49,7 +49,10 @@
             return 2;
         case wgpu::PresentMode::Mailbox:
             return 3;
+        default:
+            break;
     }
+    DAWN_UNREACHABLE();
 }
 
 uint32_t PresentModeToSwapInterval(wgpu::PresentMode mode) {
@@ -59,7 +62,10 @@
             return 0;
         case wgpu::PresentMode::Fifo:
             return 1;
+        default:
+            break;
     }
+    DAWN_UNREACHABLE();
 }
 
 UINT PresentModeToSwapChainFlags(wgpu::PresentMode mode) {
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
index 46a12a8..a08c50a 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
@@ -869,57 +869,71 @@
 ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
     InstanceBase* instance,
     const Surface* surface) const {
+    // Gather the Vulkan surface capabilities.
+    VulkanSurfaceInfo vkCaps;
+    {
+        const VulkanFunctions& fn = GetVulkanInstance()->GetFunctions();
+        VkInstance vkInstance = GetVulkanInstance()->GetVkInstance();
+
+        VkSurfaceKHR vkSurface;
+        DAWN_TRY_ASSIGN(vkSurface, CreateVulkanSurface(instance, this, surface));
+        DAWN_TRY_ASSIGN_WITH_CLEANUP(vkCaps, GatherSurfaceInfo(*this, vkSurface),
+                                     { fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr); });
+
+        fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr);
+    }
+
     PhysicalDeviceSurfaceCapabilities capabilities;
 
-    // Formats
-
-    // This is the only supported format in native mode (see crbug.com/dawn/160).
-#if DAWN_PLATFORM_IS(ANDROID)
-    capabilities.formats.push_back(wgpu::TextureFormat::RGBA8Unorm);
-#else
-    capabilities.formats.push_back(wgpu::TextureFormat::BGRA8Unorm);
-#endif  // !DAWN_PLATFORM_IS(ANDROID)
-
-    // Present Modes
-
-    // TODO(dawn:2320): Other present modes than Mailbox do not pass tests on Intel Graphics. Once
-    // 'surface' will actually contain a vkSurface we'll be able to test
-    // vkGetPhysicalDeviceSurfaceSupportKHR to avoid this #if.
-#if DAWN_PLATFORM_IS(LINUX)
-    capabilities.presentModes = {
-        wgpu::PresentMode::Mailbox,
+    // Convert known swapchain formats
+    auto ToWGPUSwapChainFormat = [](VkFormat format) -> wgpu::TextureFormat {
+        switch (format) {
+            case VK_FORMAT_R8G8B8A8_UNORM:
+                return wgpu::TextureFormat::RGBA8Unorm;
+            case VK_FORMAT_R8G8B8A8_SRGB:
+                return wgpu::TextureFormat::RGBA8UnormSrgb;
+            case VK_FORMAT_B8G8R8A8_UNORM:
+                return wgpu::TextureFormat::BGRA8Unorm;
+            case VK_FORMAT_B8G8R8A8_SRGB:
+                return wgpu::TextureFormat::BGRA8UnormSrgb;
+            case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+                return wgpu::TextureFormat::RGB10A2Unorm;
+            case VK_FORMAT_R16G16B16A16_SFLOAT:
+                return wgpu::TextureFormat::RGBA16Float;
+            default:
+                return wgpu::TextureFormat::Undefined;
+        }
     };
-#else
-    capabilities.presentModes = {
-        wgpu::PresentMode::Fifo,
-        wgpu::PresentMode::Immediate,
-        wgpu::PresentMode::Mailbox,
+    for (VkSurfaceFormatKHR surfaceFormat : vkCaps.formats) {
+        wgpu::TextureFormat format = ToWGPUSwapChainFormat(surfaceFormat.format);
+        if (format != wgpu::TextureFormat::Undefined) {
+            capabilities.formats.push_back(format);
+        }
+    }
+
+    // Convert known present modes
+    auto ToWGPUPresentMode = [](VkPresentModeKHR mode) -> std::optional<wgpu::PresentMode> {
+        switch (mode) {
+            case VK_PRESENT_MODE_FIFO_KHR:
+                return wgpu::PresentMode::Fifo;
+            case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
+                return wgpu::PresentMode::FifoRelaxed;
+            case VK_PRESENT_MODE_MAILBOX_KHR:
+                return wgpu::PresentMode::Mailbox;
+            case VK_PRESENT_MODE_IMMEDIATE_KHR:
+                return wgpu::PresentMode::Immediate;
+            default:
+                return {};
+        }
     };
-#endif  // !DAWN_PLATFORM_IS(LINUX)
+    for (VkPresentModeKHR vkMode : vkCaps.presentModes) {
+        std::optional<wgpu::PresentMode> wgpuMode = ToWGPUPresentMode(vkMode);
+        if (wgpuMode) {
+            capabilities.presentModes.push_back(*wgpuMode);
+        }
+    }
 
-    // Alpha Modes
-
-#if !DAWN_PLATFORM_IS(ANDROID)
-    capabilities.alphaModes.push_back(wgpu::CompositeAlphaMode::Opaque);
-#else
-    VkSurfaceKHR vkSurface;
-    DAWN_TRY_ASSIGN(vkSurface, CreateVulkanSurface(instance, this, surface));
-
-    VkPhysicalDevice vkPhysicalDevice = GetVkPhysicalDevice();
-    const VulkanFunctions& fn = GetVulkanInstance()->GetFunctions();
-    VkInstance vkInstance = GetVulkanInstance()->GetVkInstance();
-    const VulkanFunctions& vkFunctions = GetVulkanInstance()->GetFunctions();
-
-    // Get the surface capabilities
-    VkSurfaceCapabilitiesKHR vkCapabilities;
-    DAWN_TRY_WITH_CLEANUP(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR(
-                                             vkPhysicalDevice, vkSurface, &vkCapabilities),
-                                         "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"),
-                          { fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr); });
-
-    fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr);
-
-    // TODO(dawn:286): investigate composite alpha for WebGPU native
+    // Compute supported alpha modes
     struct AlphaModePairs {
         VkCompositeAlphaFlagBitsKHR vkBit;
         wgpu::CompositeAlphaMode webgpuEnum;
@@ -931,13 +945,12 @@
         {VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, wgpu::CompositeAlphaMode::Inherit},
     };
 
+    capabilities.alphaModes.push_back(wgpu::CompositeAlphaMode::Auto);
     for (auto mode : alphaModePairs) {
-        if (vkCapabilities.supportedCompositeAlpha & mode.vkBit) {
+        if (vkCaps.capabilities.supportedCompositeAlpha & mode.vkBit) {
             capabilities.alphaModes.push_back(mode.webgpuEnum);
         }
     }
-#endif  // #if !DAWN_PLATFORM_IS(ANDROID)
-    capabilities.alphaModes.push_back(wgpu::CompositeAlphaMode::Auto);
 
     return capabilities;
 }
diff --git a/src/dawn/native/vulkan/SwapChainVk.cpp b/src/dawn/native/vulkan/SwapChainVk.cpp
index 360fff2..3d1a186 100644
--- a/src/dawn/native/vulkan/SwapChainVk.cpp
+++ b/src/dawn/native/vulkan/SwapChainVk.cpp
@@ -55,6 +55,8 @@
     switch (mode) {
         case wgpu::PresentMode::Fifo:
             return VK_PRESENT_MODE_FIFO_KHR;
+        case wgpu::PresentMode::FifoRelaxed:
+            return VK_PRESENT_MODE_FIFO_RELAXED_KHR;
         case wgpu::PresentMode::Immediate:
             return VK_PRESENT_MODE_IMMEDIATE_KHR;
         case wgpu::PresentMode::Mailbox: