From: Benjamin Otte Date: Wed, 24 May 2023 14:55:18 +0000 (+0200) Subject: vulkan: Create multiple render objects X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~185^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=5409f0b35061e43c808b7ab4ae973a08562c5577;p=gtk4.git vulkan: Create multiple render objects Sometimes the GPU is still busy when the next frame starts (like when no-vsync benchmarking), so we need to keep all those resources alone and create new ones. That's what the render object is for, so we just create another one. However, when we create too many, we'll starve the CPU. So we'll limit it. Currently, that limit is at 4, but I've never reached it (I've also not starved the GPU yet), so that number may want to be set lower/higher in the future. Note that this is different from the number of outstanding buffers, as those are not busy on the GPU but on the compositor, and as such a buffer may have not finished rendering but have been returend from the compositor (very busy GPU) or have finished rendering but not been returned from the compositor (very idle GPU). --- diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index 1957e75e48..0e3d7dfaa4 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -350,6 +350,12 @@ gsk_vulkan_render_get_framebuffer (GskVulkanRender *self, return fb->framebuffer; } +VkFence +gsk_vulkan_render_get_fence (GskVulkanRender *self) +{ + return self->fence; +} + void gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self, GskVulkanImage *image) diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index a14e6bd373..8c1b88c315 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -17,6 +17,8 @@ #include +#define GSK_VULKAN_MAX_RENDERS 4 + typedef struct _GskVulkanTextureData GskVulkanTextureData; struct _GskVulkanTextureData { @@ -51,7 +53,7 @@ struct _GskVulkanRenderer guint n_targets; GskVulkanImage **targets; - GskVulkanRender *render; + GskVulkanRender *renders[GSK_VULKAN_MAX_RENDERS]; GSList *textures; @@ -161,6 +163,38 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, } } +static GskVulkanRender * +gsk_vulkan_renderer_get_render (GskVulkanRenderer *self) +{ + VkFence fences[G_N_ELEMENTS (self->renders)]; + VkDevice device; + guint i; + + device = gdk_vulkan_context_get_device (self->vulkan); + + while (TRUE) + { + for (i = 0; i < G_N_ELEMENTS (self->renders); i++) + { + if (self->renders[i] == NULL) + { + self->renders[i] = gsk_vulkan_render_new (GSK_RENDERER (self), self->vulkan); + return self->renders[i]; + } + + fences[i] = gsk_vulkan_render_get_fence (self->renders[i]); + if (vkGetFenceStatus (device, fences[i]) == VK_SUCCESS) + return self->renders[i]; + } + + GSK_VK_CHECK (vkWaitForFences, device, + G_N_ELEMENTS (fences), + fences, + VK_FALSE, + INT64_MAX); + } +} + static gboolean gsk_vulkan_renderer_realize (GskRenderer *renderer, GdkSurface *surface, @@ -185,8 +219,6 @@ gsk_vulkan_renderer_realize (GskRenderer *renderer, self); gsk_vulkan_renderer_update_images_cb (self->vulkan, self); - self->render = gsk_vulkan_render_new (renderer, self->vulkan); - self->glyph_cache = gsk_vulkan_glyph_cache_new (renderer, self->vulkan); return TRUE; @@ -197,6 +229,7 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer) { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); GSList *l; + guint i; g_clear_object (&self->glyph_cache); @@ -209,7 +242,8 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer) } g_clear_pointer (&self->textures, g_slist_free); - g_clear_pointer (&self->render, gsk_vulkan_render_free); + for (i = 0; i < G_N_ELEMENTS (self->renders); i++) + g_clear_pointer (&self->renders[i], gsk_vulkan_render_free); gsk_vulkan_renderer_free_targets (self); g_signal_handlers_disconnect_by_func(self->vulkan, @@ -306,7 +340,7 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, #endif gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->vulkan), region); - render = self->render; + render = gsk_vulkan_renderer_get_render (self); render_region = get_render_region (self); draw_index = gdk_vulkan_context_get_draw_index (self->vulkan); diff --git a/gsk/vulkan/gskvulkanrenderprivate.h b/gsk/vulkan/gskvulkanrenderprivate.h index 70771a078a..dc7031b405 100644 --- a/gsk/vulkan/gskvulkanrenderprivate.h +++ b/gsk/vulkan/gskvulkanrenderprivate.h @@ -95,6 +95,7 @@ void gsk_vulkan_render_submit (GskVulk GdkTexture * gsk_vulkan_render_download_target (GskVulkanRender *self); VkFramebuffer gsk_vulkan_render_get_framebuffer (GskVulkanRender *self, GskVulkanImage *image); +VkFence gsk_vulkan_render_get_fence (GskVulkanRender *self); G_END_DECLS