From 7d837a2ae662ebfdc4202db63dcc0cd4b96ca5f3 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 14 Dec 2016 08:00:58 +0100 Subject: [PATCH] vulkan: Split PipelineLayout into its own object This way, we can share the layout between different pipelines. --- gsk/gskvulkanpipeline.c | 151 ++++++++++++++++++++----------- gsk/gskvulkanpipelineprivate.h | 21 ++++- gsk/gskvulkanrender.c | 11 ++- gsk/gskvulkanrenderpass.c | 8 +- gsk/gskvulkanrenderpassprivate.h | 2 +- 5 files changed, 129 insertions(+), 64 deletions(-) diff --git a/gsk/gskvulkanpipeline.c b/gsk/gskvulkanpipeline.c index d1b1ed3138..2888c628b3 100644 --- a/gsk/gskvulkanpipeline.c +++ b/gsk/gskvulkanpipeline.c @@ -7,15 +7,22 @@ #include +struct _GskVulkanPipelineLayout +{ + volatile gint ref_count; + GdkVulkanContext *vulkan; + + VkPipelineLayout pipeline_layout; + VkDescriptorSetLayout descriptor_set_layout; +}; + struct _GskVulkanPipeline { GObject parent_instance; - GdkVulkanContext *vulkan; + GskVulkanPipelineLayout *layout; VkPipeline pipeline; - VkPipelineLayout pipeline_layout; - VkDescriptorSetLayout descriptor_set_layout; GskVulkanShader *vertex_shader; GskVulkanShader *fragment_shader; @@ -27,7 +34,7 @@ static void gsk_vulkan_pipeline_finalize (GObject *gobject) { GskVulkanPipeline *self = GSK_VULKAN_PIPELINE (gobject); - VkDevice device = gdk_vulkan_context_get_device (self->vulkan); + VkDevice device = gdk_vulkan_context_get_device (self->layout->vulkan); vkDestroyPipeline (device, self->pipeline, @@ -36,15 +43,7 @@ gsk_vulkan_pipeline_finalize (GObject *gobject) g_clear_pointer (&self->fragment_shader, gsk_vulkan_shader_free); g_clear_pointer (&self->vertex_shader, gsk_vulkan_shader_free); - vkDestroyPipelineLayout (device, - self->pipeline_layout, - NULL); - - vkDestroyDescriptorSetLayout (device, - self->descriptor_set_layout, - NULL); - - g_clear_object (&self->vulkan); + g_clear_pointer (&self->layout, gsk_vulkan_pipeline_layout_unref); G_OBJECT_CLASS (gsk_vulkan_pipeline_parent_class)->finalize (gobject); } @@ -61,50 +60,25 @@ gsk_vulkan_pipeline_init (GskVulkanPipeline *self) } GskVulkanPipeline * -gsk_vulkan_pipeline_new (GdkVulkanContext *context, - VkRenderPass render_pass) +gsk_vulkan_pipeline_new (GskVulkanPipelineLayout *layout, + const char *shader_name, + VkRenderPass render_pass) { GskVulkanPipeline *self; VkDevice device; - g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), NULL); + g_return_val_if_fail (layout != NULL, NULL); + g_return_val_if_fail (shader_name != NULL, NULL); g_return_val_if_fail (render_pass != VK_NULL_HANDLE, NULL); - device = gdk_vulkan_context_get_device (context); - self = g_object_new (GSK_TYPE_VULKAN_PIPELINE, NULL); - self->vulkan = g_object_ref (context); + self->layout = gsk_vulkan_pipeline_layout_ref (layout); - GSK_VK_CHECK (vkCreateDescriptorSetLayout, device, - &(VkDescriptorSetLayoutCreateInfo) { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = 1, - .pBindings = (VkDescriptorSetLayoutBinding[1]) { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT - } - } - }, - NULL, - &self->descriptor_set_layout); + device = gdk_vulkan_context_get_device (layout->vulkan); - GSK_VK_CHECK (vkCreatePipelineLayout, device, - &(VkPipelineLayoutCreateInfo) { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = &self->descriptor_set_layout, - .pushConstantRangeCount = gst_vulkan_push_constants_get_range_count (), - .pPushConstantRanges = gst_vulkan_push_constants_get_ranges () - }, - NULL, - &self->pipeline_layout); - - self->vertex_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_VERTEX, "blit", NULL); - self->fragment_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_FRAGMENT, "blit", NULL); + self->vertex_shader = gsk_vulkan_shader_new_from_resource (layout->vulkan, GSK_VULKAN_SHADER_VERTEX, shader_name, NULL); + self->fragment_shader = gsk_vulkan_shader_new_from_resource (layout->vulkan, GSK_VULKAN_SHADER_FRAGMENT, shader_name, NULL); GSK_VK_CHECK (vkCreateGraphicsPipelines, device, VK_NULL_HANDLE, @@ -196,7 +170,7 @@ gsk_vulkan_pipeline_new (GdkVulkanContext *context, VK_DYNAMIC_STATE_SCISSOR }, }, - .layout = self->pipeline_layout, + .layout = gsk_vulkan_pipeline_layout_get_pipeline_layout (self->layout), .renderPass = render_pass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, @@ -205,7 +179,6 @@ gsk_vulkan_pipeline_new (GdkVulkanContext *context, NULL, &self->pipeline); - return self; } @@ -215,14 +188,90 @@ gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self) return self->pipeline; } +/*** GskVulkanPipelineLayout ***/ + +GskVulkanPipelineLayout * +gsk_vulkan_pipeline_layout_new (GdkVulkanContext *context) +{ + GskVulkanPipelineLayout *self; + VkDevice device; + + self = g_slice_new0 (GskVulkanPipelineLayout); + self->ref_count = 1; + self->vulkan = g_object_ref (context); + + device = gdk_vulkan_context_get_device (context); + + GSK_VK_CHECK (vkCreateDescriptorSetLayout, device, + &(VkDescriptorSetLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = 1, + .pBindings = (VkDescriptorSetLayoutBinding[1]) { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT + } + } + }, + NULL, + &self->descriptor_set_layout); + + GSK_VK_CHECK (vkCreatePipelineLayout, device, + &(VkPipelineLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &self->descriptor_set_layout, + .pushConstantRangeCount = gst_vulkan_push_constants_get_range_count (), + .pPushConstantRanges = gst_vulkan_push_constants_get_ranges () + }, + NULL, + &self->pipeline_layout); + + return self; +} + +GskVulkanPipelineLayout * +gsk_vulkan_pipeline_layout_ref (GskVulkanPipelineLayout *self) +{ + self->ref_count++; + + return self; +} + +void +gsk_vulkan_pipeline_layout_unref (GskVulkanPipelineLayout *self) +{ + VkDevice device; + + self->ref_count--; + + if (self->ref_count > 0) + return; + + device = gdk_vulkan_context_get_device (self->vulkan); + + vkDestroyPipelineLayout (device, + self->pipeline_layout, + NULL); + + vkDestroyDescriptorSetLayout (device, + self->descriptor_set_layout, + NULL); + + g_slice_free (GskVulkanPipelineLayout, self); +} + + VkPipelineLayout -gsk_vulkan_pipeline_get_pipeline_layout (GskVulkanPipeline *self) +gsk_vulkan_pipeline_layout_get_pipeline_layout (GskVulkanPipelineLayout *self) { return self->pipeline_layout; } VkDescriptorSetLayout -gsk_vulkan_pipeline_get_descriptor_set_layout (GskVulkanPipeline *self) +gsk_vulkan_pipeline_layout_get_descriptor_set_layout (GskVulkanPipelineLayout *self) { return self->descriptor_set_layout; } diff --git a/gsk/gskvulkanpipelineprivate.h b/gsk/gskvulkanpipelineprivate.h index 8395a2dab4..75a57db378 100644 --- a/gsk/gskvulkanpipelineprivate.h +++ b/gsk/gskvulkanpipelineprivate.h @@ -7,6 +7,8 @@ G_BEGIN_DECLS +typedef struct _GskVulkanPipelineLayout GskVulkanPipelineLayout; + #define GSK_TYPE_VULKAN_PIPELINE (gsk_vulkan_pipeline_get_type ()) G_DECLARE_FINAL_TYPE (GskVulkanPipeline, gsk_vulkan_pipeline, GSK, VULKAN_PIPELINE, GObject) @@ -24,12 +26,21 @@ gsk_vulkan_handle_result (VkResult res, #define GSK_VK_CHECK(func, ...) gsk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func)) -GskVulkanPipeline * gsk_vulkan_pipeline_new (GdkVulkanContext *context, - VkRenderPass render_pass); +GskVulkanPipelineLayout * gsk_vulkan_pipeline_layout_new (GdkVulkanContext *context); +GskVulkanPipelineLayout * gsk_vulkan_pipeline_layout_ref (GskVulkanPipelineLayout *self); +void gsk_vulkan_pipeline_layout_unref (GskVulkanPipelineLayout *self); -VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self); -VkPipelineLayout gsk_vulkan_pipeline_get_pipeline_layout (GskVulkanPipeline *self); -VkDescriptorSetLayout gsk_vulkan_pipeline_get_descriptor_set_layout (GskVulkanPipeline *self); +VkPipelineLayout gsk_vulkan_pipeline_layout_get_pipeline_layout + (GskVulkanPipelineLayout *self); +VkDescriptorSetLayout gsk_vulkan_pipeline_layout_get_descriptor_set_layout + (GskVulkanPipelineLayout *self); + + +GskVulkanPipeline * gsk_vulkan_pipeline_new (GskVulkanPipelineLayout *layout, + const char *shader_name, + VkRenderPass render_pass); + +VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self); G_END_DECLS diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index 8727cde02b..1c27648a9a 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -27,6 +27,7 @@ struct _GskVulkanRender VkCommandPool command_pool; VkFence fence; VkRenderPass render_pass; + GskVulkanPipelineLayout *layout; GHashTable *descriptor_set_indexes; VkDescriptorPool descriptor_pool; @@ -161,7 +162,9 @@ gsk_vulkan_render_new (GskRenderer *renderer, NULL, &self->render_pass); - self->pipeline = gsk_vulkan_pipeline_new (self->vulkan, self->render_pass); + self->layout = gsk_vulkan_pipeline_layout_new (self->vulkan); + + self->pipeline = gsk_vulkan_pipeline_new (self->layout, "blit", self->render_pass); return self; } @@ -369,7 +372,7 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self, VkDescriptorSetLayout layouts[needed_sets]; for (i = 0; i < needed_sets; i++) { - layouts[i] = gsk_vulkan_pipeline_get_descriptor_set_layout (self->pipeline); + layouts[i] = gsk_vulkan_pipeline_layout_get_descriptor_set_layout (self->layout); } GSK_VK_CHECK (vkAllocateDescriptorSets, device, &(VkDescriptorSetAllocateInfo) { @@ -466,7 +469,7 @@ gsk_vulkan_render_draw (GskVulkanRender *self, for (l = self->render_passes; l; l = l->next) { - gsk_vulkan_render_pass_draw (l->data, self, self->pipeline, self->command_buffer); + gsk_vulkan_render_pass_draw (l->data, self, self->layout, self->command_buffer); } vkCmdEndRenderPass (self->command_buffer); @@ -565,6 +568,8 @@ gsk_vulkan_render_free (GskVulkanRender *self) g_clear_object (&self->pipeline); + g_clear_pointer (&self->layout, gsk_vulkan_pipeline_layout_unref); + vkDestroyRenderPass (device, self->render_pass, NULL); diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index f3de2f675d..a786fbb948 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -328,7 +328,7 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, void gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, GskVulkanRender *render, - GskVulkanPipeline *pipeline, + GskVulkanPipelineLayout *layout, VkCommandBuffer command_buffer) { GskVulkanOp *op; @@ -345,7 +345,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, case GSK_VULKAN_OP_TEXTURE: vkCmdBindDescriptorSets (command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - gsk_vulkan_pipeline_get_pipeline_layout (pipeline), + gsk_vulkan_pipeline_layout_get_pipeline_layout (layout), 0, 1, (VkDescriptorSet[1]) { @@ -362,13 +362,13 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: gsk_vulkan_push_constants_push_vertex (&op->constants.constants, command_buffer, - gsk_vulkan_pipeline_get_pipeline_layout (pipeline)); + gsk_vulkan_pipeline_layout_get_pipeline_layout (layout)); break; case GSK_VULKAN_OP_PUSH_FRAGMENT_CONSTANTS: gsk_vulkan_push_constants_push_fragment (&op->constants.constants, command_buffer, - gsk_vulkan_pipeline_get_pipeline_layout (pipeline)); + gsk_vulkan_pipeline_layout_get_pipeline_layout (layout)); break; default: diff --git a/gsk/gskvulkanrenderpassprivate.h b/gsk/gskvulkanrenderpassprivate.h index 5bb8d0193f..0ce7b8d385 100644 --- a/gsk/gskvulkanrenderpassprivate.h +++ b/gsk/gskvulkanrenderpassprivate.h @@ -32,7 +32,7 @@ void gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulk GskVulkanRender *render); void gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, GskVulkanRender *render, - GskVulkanPipeline *pipeline, + GskVulkanPipelineLayout *layout, VkCommandBuffer command_buffer); G_END_DECLS