vulkan: Create framebuffers from GskVulkanRender object

Also create them on-demand, as they need to be created per-image and
per-framebuffer, so we don't want to create loads of them.
This commit is contained in:
Benjamin Otte 2016-12-08 22:35:16 +01:00
parent 8756deec58
commit e989375c04
3 changed files with 98 additions and 80 deletions

View File

@ -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);

View File

@ -15,8 +15,6 @@
#include <graphene.h>
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);

View File

@ -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);