vulkan: Cache VkRenderPasses in render object
Instead of recreating the same renderpass object in every frame and for every offscreen, just reuse it. Technically, we can save this per-renderer or even per-display (it should really be cached by VkDevice), but we have no infrastructure for that.
This commit is contained in:
@@ -58,6 +58,7 @@ struct _GskVulkanRender
|
||||
VkDescriptorPool descriptor_pool;
|
||||
VkDescriptorSet descriptor_sets[N_DESCRIPTOR_SETS];
|
||||
GHashTable *pipeline_cache;
|
||||
GHashTable *render_pass_cache;
|
||||
|
||||
GskVulkanImage *target;
|
||||
|
||||
@@ -72,6 +73,7 @@ struct _GskVulkanRender
|
||||
};
|
||||
|
||||
typedef struct _PipelineCacheKey PipelineCacheKey;
|
||||
typedef struct _RenderPassCacheKey RenderPassCacheKey;
|
||||
|
||||
struct _PipelineCacheKey
|
||||
{
|
||||
@@ -80,6 +82,13 @@ struct _PipelineCacheKey
|
||||
VkFormat format;
|
||||
};
|
||||
|
||||
struct _RenderPassCacheKey
|
||||
{
|
||||
VkFormat format;
|
||||
VkImageLayout from_layout;
|
||||
VkImageLayout to_layout;
|
||||
};
|
||||
|
||||
static guint
|
||||
pipeline_cache_key_hash (gconstpointer data)
|
||||
{
|
||||
@@ -102,6 +111,28 @@ pipeline_cache_key_equal (gconstpointer a,
|
||||
keya->format == keyb->format;
|
||||
}
|
||||
|
||||
static guint
|
||||
render_pass_cache_key_hash (gconstpointer data)
|
||||
{
|
||||
const RenderPassCacheKey *key = data;
|
||||
|
||||
return (key->from_layout << 20) ^
|
||||
(key->to_layout << 16) ^
|
||||
(key->format);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
render_pass_cache_key_equal (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const RenderPassCacheKey *keya = a;
|
||||
const RenderPassCacheKey *keyb = b;
|
||||
|
||||
return keya->from_layout == keyb->from_layout &&
|
||||
keya->to_layout == keyb->to_layout &&
|
||||
keya->format == keyb->format;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_render_verbose_print (GskVulkanRender *self,
|
||||
const char *heading)
|
||||
@@ -310,6 +341,7 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
|
||||
self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool);
|
||||
self->pipeline_cache = g_hash_table_new (pipeline_cache_key_hash, pipeline_cache_key_equal);
|
||||
self->render_pass_cache = g_hash_table_new (render_pass_cache_key_hash, render_pass_cache_key_equal);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
self->render_pass_counter = g_quark_from_static_string ("render-passes");
|
||||
@@ -474,6 +506,69 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
VkRenderPass
|
||||
gsk_vulkan_render_get_render_pass (GskVulkanRender *self,
|
||||
VkFormat format,
|
||||
VkImageLayout from_layout,
|
||||
VkImageLayout to_layout)
|
||||
{
|
||||
RenderPassCacheKey cache_key;
|
||||
VkRenderPass render_pass;
|
||||
|
||||
cache_key = (RenderPassCacheKey) {
|
||||
.format = format,
|
||||
.from_layout = from_layout,
|
||||
.to_layout = to_layout,
|
||||
};
|
||||
render_pass = g_hash_table_lookup (self->render_pass_cache, &cache_key);
|
||||
if (render_pass)
|
||||
return render_pass;
|
||||
|
||||
GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan),
|
||||
&(VkRenderPassCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = (VkAttachmentDescription[]) {
|
||||
{
|
||||
.format = format,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.initialLayout = from_layout,
|
||||
.finalLayout = to_layout
|
||||
}
|
||||
},
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = (VkSubpassDescription []) {
|
||||
{
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.inputAttachmentCount = 0,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = (VkAttachmentReference []) {
|
||||
{
|
||||
.attachment = 0,
|
||||
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
}
|
||||
},
|
||||
.pResolveAttachments = (VkAttachmentReference []) {
|
||||
{
|
||||
.attachment = VK_ATTACHMENT_UNUSED,
|
||||
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
}
|
||||
},
|
||||
.pDepthStencilAttachment = NULL,
|
||||
}
|
||||
},
|
||||
.dependencyCount = 0
|
||||
},
|
||||
NULL,
|
||||
&render_pass);
|
||||
|
||||
g_hash_table_insert (self->render_pass_cache, g_memdup (&cache_key, sizeof (RenderPassCacheKey)), render_pass);
|
||||
|
||||
return render_pass;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_render_bind_descriptor_sets (GskVulkanRender *self,
|
||||
VkCommandBuffer command_buffer)
|
||||
@@ -793,6 +888,14 @@ gsk_vulkan_render_free (GskVulkanRender *self)
|
||||
}
|
||||
g_hash_table_unref (self->pipeline_cache);
|
||||
|
||||
g_hash_table_iter_init (&iter, self->render_pass_cache);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
g_free (key);
|
||||
vkDestroyRenderPass (device, value, NULL);
|
||||
}
|
||||
g_hash_table_unref (self->render_pass_cache);
|
||||
|
||||
g_clear_pointer (&self->uploader, gsk_vulkan_uploader_free);
|
||||
|
||||
|
||||
|
||||
@@ -109,7 +109,6 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context,
|
||||
gboolean is_root)
|
||||
{
|
||||
GskVulkanRenderPass *self;
|
||||
VkImageLayout final_layout;
|
||||
|
||||
self = g_new0 (GskVulkanRenderPass, 1);
|
||||
self->vulkan = g_object_ref (context);
|
||||
@@ -120,49 +119,22 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context,
|
||||
self->viewport = *viewport;
|
||||
graphene_vec2_init_from_vec2 (&self->scale, scale);
|
||||
|
||||
if (!is_root) // this is a dependent pass
|
||||
final_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
if (is_root)
|
||||
{
|
||||
/* this is a swapchain target */
|
||||
self->render_pass = gsk_vulkan_render_get_render_pass (render,
|
||||
gsk_vulkan_image_get_vk_format (target),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
}
|
||||
else
|
||||
final_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan),
|
||||
&(VkRenderPassCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = (VkAttachmentDescription[]) {
|
||||
{
|
||||
.format = gsk_vulkan_image_get_vk_format (target),
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.finalLayout = final_layout
|
||||
}
|
||||
},
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = (VkSubpassDescription []) {
|
||||
{
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.inputAttachmentCount = 0,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = (VkAttachmentReference []) {
|
||||
{
|
||||
.attachment = 0,
|
||||
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
}
|
||||
},
|
||||
.pResolveAttachments = (VkAttachmentReference []) {
|
||||
{
|
||||
.attachment = VK_ATTACHMENT_UNUSED,
|
||||
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
}
|
||||
},
|
||||
.pDepthStencilAttachment = NULL,
|
||||
}
|
||||
},
|
||||
.dependencyCount = 0
|
||||
},
|
||||
NULL,
|
||||
&self->render_pass);
|
||||
{
|
||||
/* this is an offscreen */
|
||||
self->render_pass = gsk_vulkan_render_get_render_pass (render,
|
||||
gsk_vulkan_image_get_vk_format (target),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (fallback_pixels_quark == 0)
|
||||
@@ -182,7 +154,6 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context,
|
||||
void
|
||||
gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
|
||||
{
|
||||
VkDevice device = gdk_vulkan_context_get_device (self->vulkan);
|
||||
GskVulkanOp *op;
|
||||
gsize i;
|
||||
|
||||
@@ -197,7 +168,6 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
|
||||
g_object_unref (self->vulkan);
|
||||
g_object_unref (self->target);
|
||||
cairo_region_destroy (self->clip);
|
||||
vkDestroyRenderPass (device, self->render_pass, NULL);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ VkPipeline gsk_vulkan_render_get_pipeline (GskVulk
|
||||
const char *clip_type,
|
||||
VkFormat format,
|
||||
VkRenderPass render_pass);
|
||||
VkRenderPass gsk_vulkan_render_get_render_pass (GskVulkanRender *self,
|
||||
VkFormat format,
|
||||
VkImageLayout from_layout,
|
||||
VkImageLayout to_layout);
|
||||
gsize gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self,
|
||||
GskVulkanImage *source,
|
||||
GskVulkanRenderSampler render_sampler);
|
||||
|
||||
Reference in New Issue
Block a user