VkDescriptorPool descriptor_pool;
VkDescriptorSet descriptor_sets[N_DESCRIPTOR_SETS];
GHashTable *pipeline_cache;
+ GHashTable *render_pass_cache;
GskVulkanImage *target;
};
typedef struct _PipelineCacheKey PipelineCacheKey;
+typedef struct _RenderPassCacheKey RenderPassCacheKey;
struct _PipelineCacheKey
{
VkFormat format;
};
+struct _RenderPassCacheKey
+{
+ VkFormat format;
+ VkImageLayout from_layout;
+ VkImageLayout to_layout;
+};
+
static guint
pipeline_cache_key_hash (gconstpointer data)
{
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)
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");
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)
}
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);
gboolean is_root)
{
GskVulkanRenderPass *self;
- VkImageLayout final_layout;
self = g_new0 (GskVulkanRenderPass, 1);
self->vulkan = g_object_ref (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)
void
gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
{
- VkDevice device = gdk_vulkan_context_get_device (self->vulkan);
GskVulkanOp *op;
gsize i;
g_object_unref (self->vulkan);
g_object_unref (self->target);
cairo_region_destroy (self->clip);
- vkDestroyRenderPass (device, self->render_pass, NULL);
g_free (self);
}