vulkan: Add support for high bit depth
authorBenjamin Otte <otte@redhat.com>
Sun, 18 Jun 2023 12:00:39 +0000 (14:00 +0200)
committerBenjamin Otte <otte@redhat.com>
Mon, 19 Jun 2023 13:08:00 +0000 (15:08 +0200)
gdk/gdkvulkancontext.c
gsk/vulkan/gskvulkanrenderer.c

index a1a670a26261ea21530c350fdebbcc064419435a..99ab8da959c47806571005ea2e8361c4c50d2d7a 100644 (file)
@@ -47,7 +47,11 @@ typedef struct _GdkVulkanContextPrivate GdkVulkanContextPrivate;
 struct _GdkVulkanContextPrivate {
 #ifdef GDK_RENDERING_VULKAN
   VkSurfaceKHR surface;
-  VkSurfaceFormatKHR image_format;
+  struct {
+    VkSurfaceFormatKHR vk_format;
+    GdkMemoryFormat gdk_format;
+  } formats[4];
+  GdkMemoryDepth current_format;
 
   VkSwapchainKHR swapchain;
   VkSemaphore draw_semaphore;
@@ -429,8 +433,8 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext  *context,
                                                 .minImageCount = CLAMP (4,
                                                                         capabilities.minImageCount,
                                                                         capabilities.maxImageCount ? capabilities.maxImageCount : G_MAXUINT32),
-                                                .imageFormat = priv->image_format.format,
-                                                .imageColorSpace = priv->image_format.colorSpace,
+                                                .imageFormat = priv->formats[priv->current_format].vk_format.format,
+                                                .imageColorSpace = priv->formats[priv->current_format].vk_format.colorSpace,
                                                 .imageExtent = capabilities.currentExtent,
                                                 .imageArrayLayers = 1,
                                                 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
@@ -527,6 +531,20 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
   GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
   guint i;
 
+  if (depth != priv->current_format)
+    {
+      if (priv->formats[depth].gdk_format != priv->formats[priv->current_format].gdk_format)
+        {
+          GError *error = NULL;
+          if (!gdk_vulkan_context_check_swapchain (context, &error))
+            {
+              g_warning ("%s", error->message);
+              g_error_free (error);
+              return;
+            }
+        }
+      priv->current_format = depth;
+    }
   for (i = 0; i < priv->n_images; i++)
     {
       cairo_region_union (priv->regions[i], region);
@@ -676,8 +694,12 @@ gdk_vulkan_context_real_init (GInitable     *initable,
 
   if (surface == NULL)
     {
-      priv->image_format.format = VK_FORMAT_B8G8R8A8_UNORM;
-      priv->image_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+      for (i = 0; i < G_N_ELEMENTS (priv->formats); i++)
+        {
+          priv->formats[i].vk_format.format = VK_FORMAT_B8G8R8A8_UNORM;
+          priv->formats[i].vk_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+          priv->formats[i].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
+        }
       return TRUE;
     }
 
@@ -715,16 +737,71 @@ gdk_vulkan_context_real_init (GInitable     *initable,
                                                           &n_formats, formats);
       for (i = 0; i < n_formats; i++)
         {
-          if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM)
-            break;
+          if (formats[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
+            continue;
+
+          switch ((int) formats[i].format)
+            {
+              case VK_FORMAT_B8G8R8A8_UNORM:
+                if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
+                  {
+                    priv->formats[GDK_MEMORY_U8].vk_format = formats[i];
+                    priv->formats[GDK_MEMORY_U8].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
+                  };
+                break;
+
+              case VK_FORMAT_R8G8B8A8_UNORM:
+                if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
+                  {
+                    priv->formats[GDK_MEMORY_U8].vk_format = formats[i];
+                    priv->formats[GDK_MEMORY_U8].gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
+                  }
+                break;
+
+              case VK_FORMAT_R16G16B16A16_UNORM:
+                priv->formats[GDK_MEMORY_U16].vk_format = formats[i];
+                priv->formats[GDK_MEMORY_U16].gdk_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
+                break;
+
+              case VK_FORMAT_R16G16B16A16_SFLOAT:
+                priv->formats[GDK_MEMORY_FLOAT16].vk_format = formats[i];
+                priv->formats[GDK_MEMORY_FLOAT16].gdk_format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
+                break;
+
+              case VK_FORMAT_R32G32B32A32_SFLOAT:
+                priv->formats[GDK_MEMORY_FLOAT32].vk_format = formats[i];
+                priv->formats[GDK_MEMORY_FLOAT32].gdk_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
+                break;
+
+              default:
+                break;
+            }
         }
-      if (i == n_formats)
+      if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
         {
           g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
                                "No supported image format found.");
           goto out_surface;
         }
-      priv->image_format = formats[i];
+      /* Ensure all the formats exist:
+       * - If a format was found, keep that one.
+       * - FLOAT32 chooses the best format we have.
+       * - FLOAT16 and U16 pick the format FLOAT32 uses
+       */
+      if (priv->formats[GDK_MEMORY_FLOAT32].vk_format.format == VK_FORMAT_UNDEFINED)
+        {
+          if (priv->formats[GDK_MEMORY_FLOAT16].vk_format.format != VK_FORMAT_UNDEFINED)
+            priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_FLOAT16];
+          else if (priv->formats[GDK_MEMORY_U16].vk_format.format != VK_FORMAT_UNDEFINED)
+            priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_U16];
+          else
+            priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_U8];
+        }
+      if (priv->formats[GDK_MEMORY_FLOAT16].vk_format.format == VK_FORMAT_UNDEFINED)
+        priv->formats[GDK_MEMORY_FLOAT16] = priv->formats[GDK_MEMORY_FLOAT32];
+      if (priv->formats[GDK_MEMORY_U16].vk_format.format == VK_FORMAT_UNDEFINED)
+        priv->formats[GDK_MEMORY_U16] = priv->formats[GDK_MEMORY_FLOAT32];
+
       priv->has_present_region = device_supports_incremental_present (display->vk_physical_device);
 
       if (!gdk_vulkan_context_check_swapchain (context, error))
@@ -851,7 +928,7 @@ gdk_vulkan_context_get_image_format (GdkVulkanContext *context)
 
   g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), VK_FORMAT_UNDEFINED);
 
-  return priv->image_format.format;
+  return priv->formats[priv->current_format].vk_format.format;
 }
 
 /**
index 35a4269da6eb1502b297da05b8d93da55ed95ea8..694786e13fb71f16c8630d758ff7d986739eb8b3 100644 (file)
@@ -13,6 +13,7 @@
 #include "gskvulkanglyphcacheprivate.h"
 
 #include "gdk/gdkdisplayprivate.h"
+#include "gdk/gdkdrawcontextprivate.h"
 #include "gdk/gdktextureprivate.h"
 #include "gdk/gdkprofilerprivate.h"
 
@@ -341,7 +342,9 @@ gsk_vulkan_renderer_render (GskRenderer          *renderer,
   gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
 #endif
 
-  gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->vulkan), region);
+  gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->vulkan),
+                                     gsk_render_node_get_preferred_depth (root),
+                                     region);
   render = gsk_vulkan_renderer_get_render (self);
 
   render_region = get_render_region (self);