mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 03:10:09 +00:00
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:
parent
8756deec58
commit
e989375c04
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user