diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index 1c27648a9a..9eec621484 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -34,7 +34,7 @@ struct _GskVulkanRender uint32_t descriptor_pool_maxsets; VkDescriptorSet *descriptor_sets; gsize n_descriptor_sets; - GskVulkanPipeline *pipeline; + GskVulkanPipeline *pipelines[GSK_VULKAN_N_PIPELINES]; VkCommandBuffer command_buffer; @@ -164,8 +164,6 @@ gsk_vulkan_render_new (GskRenderer *renderer, self->layout = gsk_vulkan_pipeline_layout_new (self->vulkan); - self->pipeline = gsk_vulkan_pipeline_new (self->layout, "blit", self->render_pass); - return self; } @@ -289,6 +287,29 @@ gsk_vulkan_render_collect_vertices (GskVulkanRender *self) return buffer; } +GskVulkanPipeline * +gsk_vulkan_render_get_pipeline (GskVulkanRender *self, + GskVulkanPipelineType type) +{ + static const struct { + const char *name; + } pipeline_info[GSK_VULKAN_N_PIPELINES] = { + { "blit" }, + { "color" } + }; + + g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL); + + if (self->pipelines[type] == NULL) + { + self->pipelines[type] = gsk_vulkan_pipeline_new (self->layout, + pipeline_info[type].name, + self->render_pass); + } + + return self->pipelines[type]; +} + VkDescriptorSet gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self, gsize id) @@ -455,10 +476,6 @@ gsk_vulkan_render_draw (GskVulkanRender *self, }, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline (self->command_buffer, - VK_PIPELINE_BIND_POINT_GRAPHICS, - gsk_vulkan_pipeline_get_pipeline (self->pipeline)); - vkCmdBindVertexBuffers (self->command_buffer, 0, 1, @@ -547,6 +564,7 @@ gsk_vulkan_render_free (GskVulkanRender *self) GHashTableIter iter; gpointer key, value; VkDevice device; + guint i; gsk_vulkan_render_cleanup (self); @@ -566,7 +584,8 @@ gsk_vulkan_render_free (GskVulkanRender *self) } g_hash_table_unref (self->framebuffers); - g_clear_object (&self->pipeline); + for (i = 0; i < GSK_VULKAN_N_PIPELINES; i++) + g_clear_object (&self->pipelines[i]); g_clear_pointer (&self->layout, gsk_vulkan_pipeline_layout_unref); diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index a786fbb948..a2d66c8cf5 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -17,6 +17,7 @@ typedef enum { GSK_VULKAN_OP_FALLBACK, GSK_VULKAN_OP_SURFACE, GSK_VULKAN_OP_TEXTURE, + GSK_VULKAN_OP_COLOR, /* GskVulkanOpPushConstants */ GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS, GSK_VULKAN_OP_PUSH_FRAGMENT_CONSTANTS @@ -26,6 +27,7 @@ struct _GskVulkanOpRender { GskVulkanOpType type; GskRenderNode *node; /* node that's the source of this op */ + GskVulkanPipeline *pipeline; /* pipeline to use */ GskVulkanImage *source; /* source image to render */ gsize vertex_offset; /* offset into vertex buffer */ gsize vertex_count; /* number of vertices */ @@ -93,16 +95,30 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, default: op.type = GSK_VULKAN_OP_FALLBACK; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT); g_array_append_val (self->render_ops, op); break; case GSK_CAIRO_NODE: op.type = GSK_VULKAN_OP_SURFACE; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT); g_array_append_val (self->render_ops, op); break; case GSK_TEXTURE_NODE: op.type = GSK_VULKAN_OP_TEXTURE; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT); + g_array_append_val (self->render_ops, op); + break; + + case GSK_COLOR_NODE: + op.type = GSK_VULKAN_OP_PUSH_FRAGMENT_CONSTANTS; + gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants); + gsk_vulkan_push_constants_set_color (&op.constants.constants, gsk_color_node_peek_color (node)); + g_array_append_val (self->render_ops, op); + + op.type = GSK_VULKAN_OP_COLOR; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_COLOR); g_array_append_val (self->render_ops, op); break; @@ -125,6 +141,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants); gsk_vulkan_push_constants_multiply_mvp (&op.constants.constants, &transform); g_array_append_val (self->render_ops, op); + gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, gsk_transform_node_get_child (node)); gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants); g_array_append_val (self->render_ops, op); @@ -228,6 +245,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, default: g_assert_not_reached (); + case GSK_VULKAN_OP_COLOR: case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: case GSK_VULKAN_OP_PUSH_FRAGMENT_CONSTANTS: break; @@ -279,6 +297,7 @@ gsk_vulkan_render_pass_collect_vertices (GskVulkanRenderPass *self, case GSK_VULKAN_OP_FALLBACK: case GSK_VULKAN_OP_SURFACE: case GSK_VULKAN_OP_TEXTURE: + case GSK_VULKAN_OP_COLOR: op->render.vertex_offset = offset + n; op->render.vertex_count = gsk_vulkan_render_op_collect_vertices (&op->render, vertices + n + offset); break; @@ -318,6 +337,7 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, default: g_assert_not_reached (); + case GSK_VULKAN_OP_COLOR: case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: case GSK_VULKAN_OP_PUSH_FRAGMENT_CONSTANTS: break; @@ -331,6 +351,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, GskVulkanPipelineLayout *layout, VkCommandBuffer command_buffer) { + GskVulkanPipeline *current_pipeline = NULL; GskVulkanOp *op; guint i; @@ -353,6 +374,15 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, }, 0, NULL); + /* fall through */ + case GSK_VULKAN_OP_COLOR: + if (current_pipeline != op->render.pipeline) + { + current_pipeline = op->render.pipeline; + vkCmdBindPipeline (command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + gsk_vulkan_pipeline_get_pipeline (current_pipeline)); + } vkCmdDraw (command_buffer, op->render.vertex_count, 1, diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index 1791245991..a85ee95772 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -9,6 +9,13 @@ G_BEGIN_DECLS +typedef enum { + GSK_VULKAN_PIPELINE_BLIT, + GSK_VULKAN_PIPELINE_COLOR, + /* add more */ + GSK_VULKAN_N_PIPELINES +} GskVulkanPipelineType; + typedef struct _GskVulkanRender GskVulkanRender; typedef struct _GskVulkanVertex GskVulkanVertex; @@ -38,6 +45,8 @@ void gsk_vulkan_render_add_node (GskVulk void gsk_vulkan_render_upload (GskVulkanRender *self); +GskVulkanPipeline * gsk_vulkan_render_get_pipeline (GskVulkanRender *self, + GskVulkanPipelineType pipeline_type); VkDescriptorSet gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self, gsize id); gsize gsk_vulkan_render_reserve_descriptor_set (GskVulkanRender *self, diff --git a/gsk/resources/vulkan/color.frag.glsl b/gsk/resources/vulkan/color.frag.glsl new file mode 100644 index 0000000000..952f9b7f21 --- /dev/null +++ b/gsk/resources/vulkan/color.frag.glsl @@ -0,0 +1,17 @@ +#version 420 core + +layout(location = 0) in vec2 inTexCoord; + +layout(set = 0, binding = 0) uniform sampler2D inTexture; + +layout(push_constant) uniform PushConstants { + mat4 mvp; + vec4 color; +} push; + +layout(location = 0) out vec4 color; + +void main() +{ + color = push.color; +} diff --git a/gsk/resources/vulkan/color.frag.spv b/gsk/resources/vulkan/color.frag.spv new file mode 100644 index 0000000000..45ffde52a7 Binary files /dev/null and b/gsk/resources/vulkan/color.frag.spv differ diff --git a/gsk/resources/vulkan/color.vert.glsl b/gsk/resources/vulkan/color.vert.glsl new file mode 100644 index 0000000000..2522b7e0ef --- /dev/null +++ b/gsk/resources/vulkan/color.vert.glsl @@ -0,0 +1,19 @@ +#version 420 core + +layout(location = 0) in vec2 inPosition; +layout(location = 1) in vec2 inTexCoord; + +layout(push_constant) uniform PushConstants { + mat4 mvp; +} push; + +layout(location = 0) out vec2 outTexCoord; + +out gl_PerVertex { + vec4 gl_Position; +}; + +void main() { + gl_Position = push.mvp * vec4 (inPosition, 0.0, 1.0); + outTexCoord = inTexCoord; +} diff --git a/gsk/resources/vulkan/color.vert.spv b/gsk/resources/vulkan/color.vert.spv new file mode 100644 index 0000000000..3deee1c8e2 Binary files /dev/null and b/gsk/resources/vulkan/color.vert.spv differ