From: Georges Basile Stavracas Neto Date: Fri, 4 Oct 2019 21:53:10 +0000 (-0300) Subject: vulkan/context: Implement VK_KHR_incremental_present X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~20^2~812^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=a795d6635b63c6d1dad9acbb3a78fc3eef8d7670;p=gtk4.git vulkan/context: Implement VK_KHR_incremental_present This is the Vulkan version of eglSwapBuffersWithDamage(), and it's always a good idea to limit the number of pixels we're pushing to the GPU and/or swapping into the display. --- diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index a47808cc3b..7234421e1b 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -64,6 +64,9 @@ struct _GdkVulkanContextPrivate { guint n_images; VkImage *images; cairo_region_t **regions; + + gboolean has_present_region; + #endif guint32 draw_index; @@ -385,6 +388,26 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context, return res == VK_SUCCESS; } +static gboolean +device_supports_incremental_present (VkPhysicalDevice device) +{ + VkExtensionProperties *extensions; + uint32_t n_device_extensions; + + vkEnumerateDeviceExtensionProperties (device, NULL, &n_device_extensions, NULL); + + extensions = g_newa (VkExtensionProperties, n_device_extensions); + vkEnumerateDeviceExtensionProperties (device, NULL, &n_device_extensions, extensions); + + for (uint32_t i = 0; i < n_device_extensions; i++) + { + if (g_str_equal (extensions[i].extensionName, VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME)) + return TRUE; + } + + return FALSE; +} + static void gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context, cairo_region_t *region) @@ -414,6 +437,29 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context, { GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context); GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context); + VkPresentRegionsKHR *regionsptr = VK_NULL_HANDLE; + VkPresentRegionsKHR regions; + cairo_rectangle_int_t extents; + + cairo_region_get_extents (painted, &extents); + + regions = (VkPresentRegionsKHR) { + .sType = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR, + .swapchainCount = 1, + .pRegions = &(VkPresentRegionKHR) { + .rectangleCount = 1, + .pRectangles = &(VkRectLayerKHR) { + .layer = 0, + .offset.x = extents.x, + .offset.y = extents.y, + .extent.width = extents.width, + .extent.height = extents.height, + } + }, + }; + + if (priv->has_present_region) + regionsptr = ®ions; GDK_VK_CHECK (vkQueuePresentKHR, gdk_vulkan_context_get_queue (context), &(VkPresentInfoKHR) { @@ -429,6 +475,7 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context, .pImageIndices = (uint32_t[]) { priv->draw_index }, + .pNext = regionsptr, }); cairo_region_destroy (priv->regions[priv->draw_index]); @@ -491,11 +538,12 @@ gdk_vulkan_context_real_init (GInitable *initable, { GdkVulkanContext *context = GDK_VULKAN_CONTEXT (initable); GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context); + GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)); VkResult res; VkBool32 supported; uint32_t i; - priv->vulkan_ref = gdk_display_ref_vulkan (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), error); + priv->vulkan_ref = gdk_display_ref_vulkan (display, error); if (!priv->vulkan_ref) return FALSE; @@ -543,6 +591,7 @@ gdk_vulkan_context_real_init (GInitable *initable, goto out_surface; } priv->image_format = formats[i]; + priv->has_present_region = device_supports_incremental_present (display->vk_physical_device); if (!gdk_vulkan_context_check_swapchain (context, error)) goto out_surface; @@ -866,11 +915,20 @@ gdk_display_create_vulkan_device (GdkDisplay *display, vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, NULL); VkQueueFamilyProperties *queue_props = g_newa (VkQueueFamilyProperties, n_queue_props); vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, queue_props); - for (j = 0; j < n_queue_props; j++) { if (queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) { + GPtrArray *device_extensions; + gboolean has_incremental_present; + + has_incremental_present = device_supports_incremental_present (devices[i]); + + device_extensions = g_ptr_array_new (); + g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME); + if (has_incremental_present) + g_ptr_array_add (device_extensions, (gpointer) VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); + GDK_DISPLAY_NOTE (display, VULKAN, g_print ("Using Vulkan device %u, queue %u\n", i, j)); if (GDK_VK_CHECK (vkCreateDevice, devices[i], &(VkDeviceCreateInfo) { @@ -886,14 +944,17 @@ gdk_display_create_vulkan_device (GdkDisplay *display, }, 0, NULL, - 1, - (const char * const []) { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, - }, + device_extensions->len, + (const gchar * const *) device_extensions->pdata }, NULL, &display->vk_device) != VK_SUCCESS) - continue; + { + g_ptr_array_unref (device_extensions); + continue; + } + + g_ptr_array_unref (device_extensions); display->vk_physical_device = devices[i]; vkGetDeviceQueue(display->vk_device, j, 0, &display->vk_queue);