gdk/vulkancontext: Use more appropriate present mode
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Thu, 13 Apr 2023 15:15:53 +0000 (12:15 -0300)
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Thu, 13 Apr 2023 16:54:45 +0000 (13:54 -0300)
Check if the driver supports MAILBOX and prefer using it; in its
absense, checkif the driver supports IMMEDIATE and prefer using
it; finally, if neither of them are supported, use the guaranteed
to be supported FIFO mode.

gdk/gdkvulkancontext.c

index f1f41ce6c9657ffc65f8a40d8a6c81db28312f5f..07caa8af4b2142215992918d4018af671070e050 100644 (file)
@@ -243,6 +243,74 @@ gdk_vulkan_strerror (VkResult result)
   }
 }
 
+#ifdef G_ENABLE_DEBUG
+static const char *
+surface_present_mode_to_string (VkPresentModeKHR present_mode)
+{
+  switch (present_mode)
+    {
+    case VK_PRESENT_MODE_MAILBOX_KHR:
+      return "VK_PRESENT_MODE_MAILBOX_KHR";
+    case VK_PRESENT_MODE_IMMEDIATE_KHR:
+      return "VK_PRESENT_MODE_IMMEDIATE_KHR";
+    case VK_PRESENT_MODE_FIFO_KHR:
+      return "VK_PRESENT_MODE_FIFO_KHR";
+    case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
+      return "VK_PRESENT_MODE_FIFO_RELAXED_KHR";
+    case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR:
+    case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR:
+    case VK_PRESENT_MODE_MAX_ENUM_KHR:
+    default:
+      return "(invalid)";
+    }
+
+  return "(unknown)";
+}
+#endif
+
+static const VkPresentModeKHR preferred_present_modes[] = {
+  VK_PRESENT_MODE_MAILBOX_KHR,
+  VK_PRESENT_MODE_IMMEDIATE_KHR,
+};
+
+static VkPresentModeKHR
+find_best_surface_present_mode (GdkVulkanContext *context)
+{
+  GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
+  VkPresentModeKHR *available_present_modes;
+  uint32_t n_present_modes;
+  VkResult res;
+
+  res = GDK_VK_CHECK (vkGetPhysicalDeviceSurfacePresentModesKHR, gdk_vulkan_context_get_physical_device (context),
+                                                                 priv->surface,
+                                                                 &n_present_modes,
+                                                                 NULL);
+
+  if (res != VK_SUCCESS)
+    goto fallback_present_mode;
+
+  available_present_modes = g_alloca (sizeof (VkPresentModeKHR) * n_present_modes);
+  res = GDK_VK_CHECK (vkGetPhysicalDeviceSurfacePresentModesKHR, gdk_vulkan_context_get_physical_device (context),
+                                                                 priv->surface,
+                                                                 &n_present_modes,
+                                                                 available_present_modes);
+
+  if (res != VK_SUCCESS)
+    goto fallback_present_mode;
+
+  for (uint32_t i = 0; i < G_N_ELEMENTS (preferred_present_modes); i++)
+    {
+      for (uint32_t j = 0; j < n_present_modes; j++)
+        {
+          if (preferred_present_modes[i] == available_present_modes[j])
+            return available_present_modes[j];
+        }
+    }
+
+fallback_present_mode:
+  return VK_PRESENT_MODE_FIFO_KHR;
+}
+
 static void
 gdk_vulkan_context_dispose (GObject *gobject)
 {
@@ -302,6 +370,7 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext  *context,
   GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
   VkSurfaceCapabilitiesKHR capabilities;
   VkCompositeAlphaFlagBitsKHR composite_alpha;
+  VkPresentModeKHR present_mode;
   VkSwapchainKHR new_swapchain;
   VkResult res;
   VkDevice device;
@@ -333,6 +402,11 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext  *context,
       composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
     }
 
+  present_mode = find_best_surface_present_mode (context);
+
+  GDK_DEBUG (VULKAN, "Using surface present mode %s",
+             surface_present_mode_to_string (present_mode));
+
   /*
    * Per https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#VkSurfaceCapabilitiesKHR
    * the current extent may assume a special value, meaning that the extent should assume whatever
@@ -367,7 +441,7 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext  *context,
                                                 },
                                                 .preTransform = capabilities.currentTransform,
                                                 .compositeAlpha = composite_alpha,
-                                                .presentMode = VK_PRESENT_MODE_FIFO_KHR,
+                                                .presentMode = present_mode,
                                                 .clipped = VK_FALSE,
                                                 .oldSwapchain = priv->swapchain
                                             },