diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index fa51779e11..8498ee1677 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -20,11 +20,15 @@ struct _GskVulkanRender VkExtent2D size; VkRect2D scissor; + GHashTable *framebuffers; VkCommandPool command_pool; + VkRenderPass render_pass; VkFence fence; VkCommandBuffer command_buffer; + GskVulkanImage *target; + GSList *render_passes; GSList *cleanup_images; }; @@ -58,7 +62,8 @@ gsk_vulkan_render_compute_mvp (GskVulkanRender *self) GskVulkanRender * gsk_vulkan_render_new (GskRenderer *renderer, - GdkVulkanContext *context) + GdkVulkanContext *context, + VkRenderPass pretend_you_didnt_see_me) { GskVulkanRender *self; VkDevice device; @@ -67,6 +72,8 @@ gsk_vulkan_render_new (GskRenderer *renderer, self->vulkan = context; self->renderer = renderer; + self->render_pass = pretend_you_didnt_see_me; + self->framebuffers = g_hash_table_new (g_direct_hash, g_direct_equal); device = gdk_vulkan_context_get_device (self->vulkan); @@ -90,6 +97,58 @@ gsk_vulkan_render_new (GskRenderer *renderer, return self; } +typedef struct { + VkFramebuffer framebuffer; +} HashFramebufferEntry; + +static void +gsk_vulkan_render_remove_framebuffer_from_image (gpointer data, + GObject *image) +{ + GskVulkanRender *self = data; + HashFramebufferEntry *fb; + + fb = g_hash_table_lookup (self->framebuffers, image); + g_hash_table_remove (self->framebuffers, image); + + vkDestroyFramebuffer (gdk_vulkan_context_get_device (self->vulkan), + fb->framebuffer, + NULL); + + g_slice_free (HashFramebufferEntry, fb); +} + +static VkFramebuffer +gsk_vulkan_render_get_framebuffer (GskVulkanRender *self, + GskVulkanImage *image) +{ + HashFramebufferEntry *fb; + + fb = g_hash_table_lookup (self->framebuffers, image); + if (fb) + return fb->framebuffer; + + fb = g_slice_new0 (HashFramebufferEntry); + GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan), + &(VkFramebufferCreateInfo) { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = self->render_pass, + .attachmentCount = 1, + .pAttachments = (VkImageView[1]) { + gsk_vulkan_image_get_image_view (image) + }, + .width = gsk_vulkan_image_get_width (image), + .height = gsk_vulkan_image_get_height (image), + .layers = 1 + }, + NULL, + &fb->framebuffer); + g_hash_table_insert (self->framebuffers, image, fb); + g_object_weak_ref (G_OBJECT (image), gsk_vulkan_render_remove_framebuffer_from_image, self); + + return fb->framebuffer; +} + void gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self, GskVulkanImage *image) @@ -161,8 +220,6 @@ gsk_vulkan_render_collect_vertices (GskVulkanRender *self) void gsk_vulkan_render_draw (GskVulkanRender *self, GskVulkanPipeline *pipeline, - VkRenderPass render_pass, - VkFramebuffer framebuffer, VkDescriptorSet descriptor_set, VkSampler sampler) { @@ -196,8 +253,8 @@ gsk_vulkan_render_draw (GskVulkanRender *self, vkCmdBeginRenderPass (self->command_buffer, &(VkRenderPassBeginInfo) { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = render_pass, - .framebuffer = framebuffer, + .renderPass = self->render_pass, + .framebuffer = gsk_vulkan_render_get_framebuffer (self, self->target), .renderArea = { { 0, 0 }, { self->size.width, self->size.height } @@ -305,17 +362,35 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self) self->render_passes = NULL; g_slist_free_full (self->cleanup_images, g_object_unref); self->cleanup_images = NULL; + + g_clear_object (&self->target); } void gsk_vulkan_render_free (GskVulkanRender *self) { + GHashTableIter iter; + gpointer key, value; VkDevice device; gsk_vulkan_render_cleanup (self); device = gdk_vulkan_context_get_device (self->vulkan); + g_hash_table_iter_init (&iter, self->framebuffers); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + HashFramebufferEntry *fb = value; + + vkDestroyFramebuffer (gdk_vulkan_context_get_device (self->vulkan), + fb->framebuffer, + NULL); + g_slice_free (HashFramebufferEntry, fb); + g_object_weak_unref (G_OBJECT (key), gsk_vulkan_render_remove_framebuffer_from_image, self); + g_hash_table_iter_remove (&iter); + } + g_hash_table_unref (self->framebuffers); + vkDestroyFence (device, self->fence, NULL); @@ -333,12 +408,15 @@ gsk_vulkan_render_is_busy (GskVulkanRender *self) } void -gsk_vulkan_render_reset (GskVulkanRender *self) +gsk_vulkan_render_reset (GskVulkanRender *self, + GskVulkanImage *target) { VkDevice device; gsk_vulkan_render_cleanup (self); + self->target = g_object_ref (target); + gsk_vulkan_render_compute_mvp (self); device = gdk_vulkan_context_get_device (self->vulkan); diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index fe7623b5a8..e04537defd 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -15,8 +15,6 @@ #include -typedef struct _GskVulkanTarget GskVulkanTarget; - #ifdef G_ENABLE_DEBUG typedef struct { GQuark cpu_time; @@ -31,7 +29,7 @@ struct _GskVulkanRenderer GdkVulkanContext *vulkan; guint n_targets; - GskVulkanTarget **targets; + GskVulkanImage **targets; VkRenderPass render_pass; @@ -56,63 +54,6 @@ struct _GskVulkanRendererClass G_DEFINE_TYPE (GskVulkanRenderer, gsk_vulkan_renderer, GSK_TYPE_RENDERER) -struct _GskVulkanTarget { - GskVulkanImage *image; - VkFramebuffer framebuffer; -}; - -static GskVulkanTarget * -gsk_vulkan_target_new_for_image (GskVulkanRenderer *self, - VkImage image, - gsize width, - gsize height) -{ - GskVulkanTarget *target; - VkDevice device; - - device = gdk_vulkan_context_get_device (self->vulkan); - - target = g_slice_new0 (GskVulkanTarget); - - target->image = gsk_vulkan_image_new_for_swapchain (self->vulkan, - image, - gdk_vulkan_context_get_image_format (self->vulkan), - width, height); - GSK_VK_CHECK (vkCreateFramebuffer, device, - &(VkFramebufferCreateInfo) { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = self->render_pass, - .attachmentCount = 1, - .pAttachments = (VkImageView[1]) { - gsk_vulkan_image_get_image_view (target->image) - }, - .width = width, - .height = height, - .layers = 1 - }, - NULL, - &target->framebuffer); - - return target; -} - -static void -gsk_vulkan_target_free (GskVulkanRenderer *self, - GskVulkanTarget *target) -{ - VkDevice device; - - device = gdk_vulkan_context_get_device (self->vulkan); - - vkDestroyFramebuffer (device, - target->framebuffer, - NULL); - - g_object_unref (target->image); - - g_slice_free (GskVulkanTarget, target); -} - static void gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self) { @@ -120,7 +61,7 @@ gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self) for (i = 0; i < self->n_targets; i++) { - gsk_vulkan_target_free (self, self->targets[i]); + g_object_unref (self->targets[i]); } g_clear_pointer (&self->targets, g_free); @@ -139,7 +80,7 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, gsk_vulkan_renderer_free_targets (self); self->n_targets = gdk_vulkan_context_get_n_images (context); - self->targets = g_new (GskVulkanTarget *, self->n_targets); + self->targets = g_new (GskVulkanImage *, self->n_targets); window = gsk_renderer_get_window (GSK_RENDERER (self)); scale_factor = gdk_window_get_scale_factor (window); @@ -148,9 +89,10 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, for (i = 0; i < self->n_targets; i++) { - self->targets[i] = gsk_vulkan_target_new_for_image (self, - gdk_vulkan_context_get_image (context, i), - width, height); + self->targets[i] = gsk_vulkan_image_new_for_swapchain (self->vulkan, + gdk_vulkan_context_get_image (context, i), + gdk_vulkan_context_get_image_format (self->vulkan), + width, height); } } @@ -259,7 +201,7 @@ gsk_vulkan_renderer_realize (GskRenderer *renderer, 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)); + self->renders = g_slist_prepend (self->renders, gsk_vulkan_render_new (renderer, self->vulkan, self->render_pass)); return TRUE; } @@ -329,19 +271,17 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, } else { - render = gsk_vulkan_render_new (renderer, self->vulkan); + render = gsk_vulkan_render_new (renderer, self->vulkan, self->render_pass); self->renders = g_slist_prepend (self->renders, render); } - gsk_vulkan_render_reset (render); + gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)]); gsk_vulkan_render_add_node (render, root); gsk_vulkan_render_upload (render); gsk_vulkan_render_draw (render, self->pipeline, - self->render_pass, - self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)]->framebuffer, self->descriptor_set, self->sampler); gsk_vulkan_render_submit (render); diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index a86e5c8a65..a17de86c9b 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -21,11 +21,13 @@ struct _GskVulkanVertex }; GskVulkanRender * gsk_vulkan_render_new (GskRenderer *renderer, - GdkVulkanContext *context); + GdkVulkanContext *context, + VkRenderPass pretend_you_didnt_see_me); void gsk_vulkan_render_free (GskVulkanRender *self); gboolean gsk_vulkan_render_is_busy (GskVulkanRender *self); -void gsk_vulkan_render_reset (GskVulkanRender *self); +void gsk_vulkan_render_reset (GskVulkanRender *self, + GskVulkanImage *target); GskRenderer * gsk_vulkan_render_get_renderer (GskVulkanRender *self); @@ -39,8 +41,6 @@ void gsk_vulkan_render_upload (GskVulk void gsk_vulkan_render_draw (GskVulkanRender *self, GskVulkanPipeline *pipeline, - VkRenderPass render_pass, - VkFramebuffer framebuffer, VkDescriptorSet descriptor_set, VkSampler sampler);