From ac9d48151bdf316f4dcb67eac75d73c6c05606a5 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 8 Dec 2016 18:40:35 +0100 Subject: [PATCH] vulkan: Keep render objects around That way we can reuse them. We only create a new one if the last render operation hasn't finished executing. --- gsk/gskvulkanrender.c | 81 ++++++++++++++++++++++++++---------- gsk/gskvulkanrenderer.c | 28 +++++++++++-- gsk/gskvulkanrenderprivate.h | 3 ++ 3 files changed, 86 insertions(+), 26 deletions(-) diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index a876a2a38d..b645dc3397 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -68,8 +68,6 @@ gsk_vulkan_render_new (GskRenderer *renderer, self->vulkan = context; self->renderer = renderer; - gsk_vulkan_render_compute_mvp (self); - device = gdk_vulkan_context_get_device (self->vulkan); GSK_VK_CHECK (vkCreateCommandPool, device, @@ -84,26 +82,11 @@ gsk_vulkan_render_new (GskRenderer *renderer, GSK_VK_CHECK (vkCreateFence, device, &(VkFenceCreateInfo) { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - .flags = 0 + .flags = VK_FENCE_CREATE_SIGNALED_BIT }, NULL, &self->fence); - GSK_VK_CHECK (vkAllocateCommandBuffers, device, - &(VkCommandBufferAllocateInfo) { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .commandPool = self->command_pool, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = 1, - }, - &self->command_buffer); - - GSK_VK_CHECK (vkBeginCommandBuffer, self->command_buffer, - &(VkCommandBufferBeginInfo) { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = 0 - }); - return self; } @@ -294,22 +277,41 @@ gsk_vulkan_render_submit (GskVulkanRender *self) &self->fence, VK_TRUE, INT64_MAX); - GSK_VK_CHECK (vkResetFences, gdk_vulkan_context_get_device (self->vulkan), - 1, - &self->fence); } -void -gsk_vulkan_render_free (GskVulkanRender *self) +static void +gsk_vulkan_render_cleanup (GskVulkanRender *self) { VkDevice device = gdk_vulkan_context_get_device (self->vulkan); + /* XXX: Wait for fence here or just in reset()? */ + GSK_VK_CHECK (vkWaitForFences, device, + 1, + &self->fence, + VK_TRUE, + INT64_MAX); + + GSK_VK_CHECK (vkResetFences, device, + 1, + &self->fence); GSK_VK_CHECK (vkResetCommandPool, device, self->command_pool, 0); g_slist_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free); + self->render_passes = NULL; g_slist_free_full (self->cleanup_images, (GDestroyNotify) gsk_vulkan_image_free); + self->cleanup_images = NULL; +} + +void +gsk_vulkan_render_free (GskVulkanRender *self) +{ + VkDevice device; + + gsk_vulkan_render_cleanup (self); + + device = gdk_vulkan_context_get_device (self->vulkan); vkDestroyFence (device, self->fence, @@ -321,6 +323,39 @@ gsk_vulkan_render_free (GskVulkanRender *self) g_slice_free (GskVulkanRender, self); } +gboolean +gsk_vulkan_render_is_busy (GskVulkanRender *self) +{ + return vkGetFenceStatus (gdk_vulkan_context_get_device (self->vulkan), self->fence) != VK_SUCCESS; +} + +void +gsk_vulkan_render_reset (GskVulkanRender *self) +{ + VkDevice device; + + gsk_vulkan_render_cleanup (self); + + gsk_vulkan_render_compute_mvp (self); + + device = gdk_vulkan_context_get_device (self->vulkan); + + GSK_VK_CHECK (vkAllocateCommandBuffers, device, + &(VkCommandBufferAllocateInfo) { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = self->command_pool, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }, + &self->command_buffer); + + GSK_VK_CHECK (vkBeginCommandBuffer, self->command_buffer, + &(VkCommandBufferBeginInfo) { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = 0 + }); +} + GskRenderer * gsk_vulkan_render_get_renderer (GskVulkanRender *self) { diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index 2332ccfd1e..929ea9118d 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -42,6 +42,8 @@ struct _GskVulkanRenderer VkSampler sampler; + GSList *renders; + #ifdef G_ENABLE_DEBUG ProfileTimers profile_timers; #endif @@ -267,6 +269,9 @@ gsk_vulkan_renderer_realize (GskRenderer *renderer, self); gsk_vulkan_renderer_update_images_cb (self->vulkan, self); + /* We will need at least one render object, so create it early where we can still fail fine */ + self->renders = g_slist_prepend (self->renders, gsk_vulkan_render_new (renderer, self->vulkan)); + return TRUE; } @@ -276,6 +281,9 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer) GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); VkDevice device; + g_slist_free_full (self->renders, (GDestroyNotify) gsk_vulkan_render_free); + self->renders = NULL; + device = gdk_vulkan_context_get_device (self->vulkan); gsk_vulkan_renderer_free_targets (self); @@ -310,6 +318,7 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); GskVulkanRender *render; + GSList *l; #ifdef G_ENABLE_DEBUG GskProfiler *profiler; gint64 cpu_time; @@ -320,7 +329,22 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time); #endif - render = gsk_vulkan_render_new (renderer, self->vulkan); + for (l = self->renders; l; l = l->next) + { + if (!gsk_vulkan_render_is_busy (l->data)) + break; + } + if (l) + { + render = l->data; + } + else + { + render = gsk_vulkan_render_new (renderer, self->vulkan); + self->renders = g_slist_prepend (self->renders, render); + } + + gsk_vulkan_render_reset (render); gsk_vulkan_render_add_node (render, root); @@ -333,8 +357,6 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, gsk_vulkan_render_submit (render); - gsk_vulkan_render_free (render); - #ifdef G_ENABLE_DEBUG cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time); gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time); diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index b4f5edd5a8..a86e5c8a65 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -24,6 +24,9 @@ GskVulkanRender * gsk_vulkan_render_new (GskRend GdkVulkanContext *context); void gsk_vulkan_render_free (GskVulkanRender *self); +gboolean gsk_vulkan_render_is_busy (GskVulkanRender *self); +void gsk_vulkan_render_reset (GskVulkanRender *self); + GskRenderer * gsk_vulkan_render_get_renderer (GskVulkanRender *self); void gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self,