From: Benjamin Otte Date: Sat, 1 Jul 2023 04:14:48 +0000 (+0200) Subject: vulkan: Port blend mode to new ops X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~60^2~63 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=594595d9cd8b97ff361462571998c3c61ecef363;p=gtk4.git vulkan: Port blend mode to new ops --- diff --git a/gsk/meson.build b/gsk/meson.build index 2ef5fae5ae..f17b1c3552 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -107,7 +107,7 @@ gsk_private_vulkan_shader_headers = [] if have_vulkan gsk_private_sources += files([ - 'vulkan/gskvulkanblendmodepipeline.c', + 'vulkan/gskvulkanblendmodeop.c', 'vulkan/gskvulkanblurpipeline.c', 'vulkan/gskvulkanborderpipeline.c', 'vulkan/gskvulkanboxshadowpipeline.c', diff --git a/gsk/vulkan/gskvulkanblendmodeop.c b/gsk/vulkan/gskvulkanblendmodeop.c new file mode 100644 index 0000000000..150d18b4e3 --- /dev/null +++ b/gsk/vulkan/gskvulkanblendmodeop.c @@ -0,0 +1,159 @@ +#include "config.h" + +#include "gskvulkanblendmodeopprivate.h" + +#include "vulkan/resources/blend-mode.vert.h" + +typedef struct _GskVulkanBlendModeOp GskVulkanBlendModeOp; + +struct _GskVulkanBlendModeOp +{ + GskVulkanOp op; + + graphene_rect_t bounds; + GskBlendMode blend_mode; + + struct { + GskVulkanImage *image; + graphene_rect_t rect; + graphene_rect_t tex_rect; + guint32 image_descriptor; + } top, bottom; + + gsize vertex_offset; +}; + +static void +gsk_vulkan_blend_mode_op_finish (GskVulkanOp *op) +{ + GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op; + + g_object_unref (self->top.image); + g_object_unref (self->bottom.image); +} + +static void +gsk_vulkan_blend_mode_op_upload (GskVulkanOp *op, + GskVulkanRenderPass *pass, + GskVulkanRender *render, + GskVulkanUploader *uploader, + const graphene_rect_t *clip, + const graphene_vec2_t *scale) +{ +} + +static inline gsize +round_up (gsize number, gsize divisor) +{ + return (number + divisor - 1) / divisor * divisor; +} + +static gsize +gsk_vulkan_blend_mode_op_count_vertex_data (GskVulkanOp *op, + gsize n_bytes) +{ + GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op; + gsize vertex_stride; + + vertex_stride = gsk_vulkan_blend_mode_info.pVertexBindingDescriptions[0].stride; + n_bytes = round_up (n_bytes, vertex_stride); + self->vertex_offset = n_bytes; + n_bytes += vertex_stride; + return n_bytes; +} + +static void +gsk_vulkan_blend_mode_op_collect_vertex_data (GskVulkanOp *op, + GskVulkanRenderPass *pass, + GskVulkanRender *render, + guchar *data) +{ + GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op; + GskVulkanBlendModeInstance *instance = (GskVulkanBlendModeInstance *) (data + self->vertex_offset); + + gsk_vulkan_rect_to_float (&self->bounds, instance->rect); + gsk_vulkan_rect_to_float (&self->top.rect, instance->top_rect); + gsk_vulkan_rect_to_float (&self->bottom.rect, instance->bottom_rect); + gsk_vulkan_rect_to_float (&self->top.tex_rect, instance->top_tex_rect); + gsk_vulkan_rect_to_float (&self->bottom.tex_rect, instance->bottom_tex_rect); + + instance->top_tex_id = self->top.image_descriptor; + instance->bottom_tex_id = self->bottom.image_descriptor; + instance->blend_mode = self->blend_mode; +} + +static void +gsk_vulkan_blend_mode_op_reserve_descriptor_sets (GskVulkanOp *op, + GskVulkanRender *render) +{ + GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op; + + self->top.image_descriptor = gsk_vulkan_render_get_image_descriptor (render, + self->top.image, + GSK_VULKAN_SAMPLER_DEFAULT); + self->bottom.image_descriptor = gsk_vulkan_render_get_image_descriptor (render, + self->bottom.image, + GSK_VULKAN_SAMPLER_DEFAULT); +} + +static VkPipeline +gsk_vulkan_blend_mode_op_get_pipeline (GskVulkanOp *op) +{ + return VK_NULL_HANDLE; +} + +static void +gsk_vulkan_blend_mode_op_command (GskVulkanOp *op, + GskVulkanRender *render, + VkPipelineLayout pipeline_layout, + VkCommandBuffer command_buffer) +{ + GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op; + + vkCmdDraw (command_buffer, + 6, 1, + 0, self->vertex_offset / gsk_vulkan_blend_mode_info.pVertexBindingDescriptions[0].stride); +} + +static const GskVulkanShaderOpClass GSK_VULKAN_BLEND_MODE_OP_CLASS = { + GSK_VULKAN_OP_SIZE (GskVulkanBlendModeOp), + "blend-mode", + &gsk_vulkan_blend_mode_info, + gsk_vulkan_blend_mode_op_finish, + gsk_vulkan_blend_mode_op_upload, + gsk_vulkan_blend_mode_op_count_vertex_data, + gsk_vulkan_blend_mode_op_collect_vertex_data, + gsk_vulkan_blend_mode_op_reserve_descriptor_sets, + gsk_vulkan_blend_mode_op_get_pipeline, + gsk_vulkan_blend_mode_op_command +}; + +void +gsk_vulkan_blend_mode_op (GskVulkanRenderPass *render_pass, + const char *clip_type, + const graphene_rect_t *bounds, + const graphene_point_t *offset, + GskBlendMode blend_mode, + GskVulkanImage *top_image, + const graphene_rect_t *top_rect, + const graphene_rect_t *top_tex_rect, + GskVulkanImage *bottom_image, + const graphene_rect_t *bottom_rect, + const graphene_rect_t *bottom_tex_rect) +{ + GskVulkanBlendModeOp *self; + + self = (GskVulkanBlendModeOp *) gsk_vulkan_op_alloc (render_pass, &GSK_VULKAN_BLEND_MODE_OP_CLASS); + + ((GskVulkanOp *) self)->clip_type = g_intern_string (clip_type); + graphene_rect_offset_r (bounds, offset->x, offset->y, &self->bounds); + self->blend_mode = blend_mode; + + self->top.image = g_object_ref (top_image); + graphene_rect_offset_r (top_rect, offset->x, offset->y, &self->top.rect); + gsk_vulkan_normalize_tex_coords (&self->top.tex_rect, bounds, top_tex_rect); + + self->bottom.image = g_object_ref (bottom_image); + graphene_rect_offset_r (bottom_rect, offset->x, offset->y, &self->bottom.rect); + gsk_vulkan_normalize_tex_coords (&self->bottom.tex_rect, bounds, bottom_tex_rect); +} diff --git a/gsk/vulkan/gskvulkanblendmodeopprivate.h b/gsk/vulkan/gskvulkanblendmodeopprivate.h new file mode 100644 index 0000000000..2a2b7c76c5 --- /dev/null +++ b/gsk/vulkan/gskvulkanblendmodeopprivate.h @@ -0,0 +1,21 @@ +#pragma once + +#include "gskvulkanopprivate.h" + +G_BEGIN_DECLS + +void gsk_vulkan_blend_mode_op (GskVulkanRenderPass *render_pass, + const char *clip_type, + const graphene_rect_t *bounds, + const graphene_point_t *offset, + GskBlendMode blend_mode, + GskVulkanImage *top_image, + const graphene_rect_t *top_rect, + const graphene_rect_t *top_tex_rect, + GskVulkanImage *bottom_image, + const graphene_rect_t *bottom_rect, + const graphene_rect_t *bottom_tex_rect); + + +G_END_DECLS + diff --git a/gsk/vulkan/gskvulkanblendmodepipeline.c b/gsk/vulkan/gskvulkanblendmodepipeline.c deleted file mode 100644 index 2bd18bc587..0000000000 --- a/gsk/vulkan/gskvulkanblendmodepipeline.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "config.h" - -#include "gskvulkanblendmodepipelineprivate.h" - -#include "vulkan/resources/blend-mode.vert.h" - -struct _GskVulkanBlendModePipeline -{ - GObject parent_instance; -}; - -typedef struct _GskVulkanBlendModeInstance GskVulkanBlendModeInstance; - -G_DEFINE_TYPE (GskVulkanBlendModePipeline, gsk_vulkan_blend_mode_pipeline, GSK_TYPE_VULKAN_PIPELINE) - -static const VkPipelineVertexInputStateCreateInfo * -gsk_vulkan_blend_mode_pipeline_get_input_state_create_info (GskVulkanPipeline *self) -{ - return &gsk_vulkan_blend_mode_info; -} - -static void -gsk_vulkan_blend_mode_pipeline_finalize (GObject *gobject) -{ - //GskVulkanBlendModePipeline *self = GSK_VULKAN_BLUR_PIPELINE (gobject); - - G_OBJECT_CLASS (gsk_vulkan_blend_mode_pipeline_parent_class)->finalize (gobject); -} - -static void -gsk_vulkan_blend_mode_pipeline_class_init (GskVulkanBlendModePipelineClass *klass) -{ - GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass); - - G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_blend_mode_pipeline_finalize; - - pipeline_class->get_input_state_create_info = gsk_vulkan_blend_mode_pipeline_get_input_state_create_info; -} - -static void -gsk_vulkan_blend_mode_pipeline_init (GskVulkanBlendModePipeline *self) -{ -} - -GskVulkanPipeline * -gsk_vulkan_blend_mode_pipeline_new (GdkVulkanContext *context, - VkPipelineLayout layout, - const char *shader_name, - VkRenderPass render_pass) -{ - return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BLEND_MODE_PIPELINE, context, layout, shader_name, render_pass); -} - -void -gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *pipeline, - guchar *data, - guint32 top_tex_id, - guint32 bottom_tex_id, - const graphene_point_t *offset, - const graphene_rect_t *bounds, - const graphene_rect_t *top_bounds, - const graphene_rect_t *bottom_bounds, - const graphene_rect_t *top_tex_rect, - const graphene_rect_t *bottom_tex_rect, - GskBlendMode blend_mode) -{ - GskVulkanBlendModeInstance *instance = (GskVulkanBlendModeInstance *) data; - - instance->rect[0] = bounds->origin.x + offset->x; - instance->rect[1] = bounds->origin.y + offset->y; - instance->rect[2] = bounds->size.width; - instance->rect[3] = bounds->size.height; - - instance->top_rect[0] = top_bounds->origin.x + offset->x; - instance->top_rect[1] = top_bounds->origin.y + offset->y; - instance->top_rect[2] = top_bounds->size.width; - instance->top_rect[3] = top_bounds->size.height; - - instance->bottom_rect[0] = bottom_bounds->origin.x + offset->x; - instance->bottom_rect[1] = bottom_bounds->origin.y + offset->y; - instance->bottom_rect[2] = bottom_bounds->size.width; - instance->bottom_rect[3] = bottom_bounds->size.height; - - instance->top_tex_rect[0] = top_tex_rect->origin.x; - instance->top_tex_rect[1] = top_tex_rect->origin.y; - instance->top_tex_rect[2] = top_tex_rect->size.width; - instance->top_tex_rect[3] = top_tex_rect->size.height; - - instance->bottom_tex_rect[0] = bottom_tex_rect->origin.x; - instance->bottom_tex_rect[1] = bottom_tex_rect->origin.y; - instance->bottom_tex_rect[2] = bottom_tex_rect->size.width; - instance->bottom_tex_rect[3] = bottom_tex_rect->size.height; - - instance->top_tex_id = top_tex_id; - instance->bottom_tex_id = bottom_tex_id; - instance->blend_mode = blend_mode; -} - -gsize -gsk_vulkan_blend_mode_pipeline_draw (GskVulkanBlendModePipeline *pipeline, - VkCommandBuffer command_buffer, - gsize offset, - gsize n_commands) -{ - vkCmdDraw (command_buffer, - 6, n_commands, - 0, offset); - - return n_commands; -} diff --git a/gsk/vulkan/gskvulkanblendmodepipelineprivate.h b/gsk/vulkan/gskvulkanblendmodepipelineprivate.h deleted file mode 100644 index e06f28ae90..0000000000 --- a/gsk/vulkan/gskvulkanblendmodepipelineprivate.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -#include "gskvulkanpipelineprivate.h" -#include "gskenums.h" - -G_BEGIN_DECLS - -typedef struct _GskVulkanBlendModePipelineLayout GskVulkanBlendModePipelineLayout; - -#define GSK_TYPE_VULKAN_BLEND_MODE_PIPELINE (gsk_vulkan_blend_mode_pipeline_get_type ()) - -G_DECLARE_FINAL_TYPE (GskVulkanBlendModePipeline, gsk_vulkan_blend_mode_pipeline, GSK, VULKAN_BLEND_MODE_PIPELINE, GskVulkanPipeline) - -GskVulkanPipeline * gsk_vulkan_blend_mode_pipeline_new (GdkVulkanContext *context, - VkPipelineLayout layout, - const char *shader_name, - VkRenderPass render_pass); - -void gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *pipeline, - guchar *data, - guint32 top_tex_id, - guint32 bottom_tex_id, - const graphene_point_t *offset, - const graphene_rect_t *bounds, - const graphene_rect_t *top_bounds, - const graphene_rect_t *bottom_bounds, - const graphene_rect_t *top_tex_rect, - const graphene_rect_t *bottom_tex_rect, - GskBlendMode blend_mode); -gsize gsk_vulkan_blend_mode_pipeline_draw (GskVulkanBlendModePipeline *pipeline, - VkCommandBuffer command_buffer, - gsize offset, - gsize n_commands); - - -G_END_DECLS - diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index b05b2f7a66..c2a834b9dd 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -10,7 +10,6 @@ #include "gskvulkanpipelineprivate.h" #include "gskvulkanrenderpassprivate.h" -#include "gskvulkanblendmodepipelineprivate.h" #include "gskvulkanblurpipelineprivate.h" #include "gskvulkanborderpipelineprivate.h" #include "gskvulkanboxshadowpipelineprivate.h" @@ -522,9 +521,6 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self, { "texture", 1, gsk_vulkan_color_text_pipeline_new }, { "texture-clip", 1, gsk_vulkan_color_text_pipeline_new }, { "texture-clip-rounded", 1, gsk_vulkan_color_text_pipeline_new }, - { "blend-mode", 2, gsk_vulkan_blend_mode_pipeline_new }, - { "blend-mode-clip", 2, gsk_vulkan_blend_mode_pipeline_new }, - { "blend-mode-clip-rounded", 2, gsk_vulkan_blend_mode_pipeline_new }, }; g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL); diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 3be521878c..fbe7b7f6d4 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -9,7 +9,7 @@ #include "gskrendererprivate.h" #include "gskroundedrectprivate.h" #include "gsktransform.h" -#include "gskvulkanblendmodepipelineprivate.h" +#include "gskvulkanblendmodeopprivate.h" #include "gskvulkanblurpipelineprivate.h" #include "gskvulkanborderpipelineprivate.h" #include "gskvulkanboxshadowpipelineprivate.h" @@ -57,7 +57,6 @@ typedef enum { GSK_VULKAN_OP_BORDER, GSK_VULKAN_OP_INSET_SHADOW, GSK_VULKAN_OP_OUTSET_SHADOW, - GSK_VULKAN_OP_BLEND_MODE, /* GskVulkanOpText */ GSK_VULKAN_OP_TEXT, GSK_VULKAN_OP_COLOR_TEXT, @@ -1118,22 +1117,47 @@ gsk_vulkan_render_pass_add_blend_node (GskVulkanRenderPass *self, const GskVulkanParseState *state, GskRenderNode *node) { - GskVulkanPipelineType pipeline_type; - GskVulkanOpRender op = { - .type = GSK_VULKAN_OP_BLEND_MODE, - .node = node, - .offset = state->offset, - }; + GskRenderNode *top_child, *bottom_child; + GskVulkanImage *top_image, *bottom_image; + graphene_rect_t top_tex_rect, bottom_tex_rect; - if (gsk_vulkan_clip_contains_rect (&state->clip, &state->offset, &node->bounds)) - pipeline_type = GSK_VULKAN_PIPELINE_BLEND_MODE; - else if (state->clip.type == GSK_VULKAN_CLIP_RECT) - pipeline_type = GSK_VULKAN_PIPELINE_BLEND_MODE_CLIP; - else - pipeline_type = GSK_VULKAN_PIPELINE_BLEND_MODE_CLIP_ROUNDED; + top_child = gsk_blend_node_get_top_child (node); + top_image = gsk_vulkan_render_pass_get_node_as_image (self, + render, + state, + top_child, + &top_tex_rect); + bottom_child = gsk_blend_node_get_bottom_child (node); + bottom_image = gsk_vulkan_render_pass_get_node_as_image (self, + render, + state, + bottom_child, + &bottom_tex_rect); + if (top_image == NULL) + { + if (bottom_image == NULL) + return TRUE; - op.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type); - gsk_vulkan_render_pass_add_op (self, (GskVulkanOp *) &op); + top_image = bottom_image; + top_tex_rect = *graphene_rect_zero (); + } + else if (bottom_image == NULL) + { + bottom_image = top_image; + bottom_tex_rect = *graphene_rect_zero (); + } + + gsk_vulkan_blend_mode_op (self, + gsk_vulkan_clip_get_clip_type (&state->clip, &state->offset, &node->bounds), + &node->bounds, + &state->offset, + gsk_blend_node_get_blend_mode (node), + top_image, + &top_child->bounds, + &top_tex_rect, + bottom_image, + &bottom_child->bounds, + &bottom_tex_rect); return TRUE; } @@ -1674,44 +1698,6 @@ gsk_vulkan_render_op_upload (GskVulkanOp *op_, } break; - case GSK_VULKAN_OP_BLEND_MODE: - { - GskRenderNode *top = gsk_blend_node_get_top_child (op->render.node); - GskRenderNode *bottom = gsk_blend_node_get_bottom_child (op->render.node); - graphene_rect_t tex_bounds; - - op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self, - render, - uploader, - top, - scale, - clip, - &op->render.offset, - &tex_bounds); - gsk_vulkan_normalize_tex_coords (&op->render.source_rect, &op->render.node->bounds, &tex_bounds); - - op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self, - render, - uploader, - bottom, - scale, - clip, - &op->render.offset, - &tex_bounds); - gsk_vulkan_normalize_tex_coords (&op->render.source2_rect, &op->render.node->bounds, &tex_bounds); - if (!op->render.source) - { - op->render.source = op->render.source2; - op->render.source_rect = *graphene_rect_zero(); - } - if (!op->render.source2) - { - op->render.source2 = op->render.source; - op->render.source2_rect = *graphene_rect_zero(); - } - } - break; - default: g_assert_not_reached (); case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: @@ -1755,7 +1741,6 @@ gsk_vulkan_render_op_count_vertex_data (GskVulkanOp *op_, case GSK_VULKAN_OP_BORDER: case GSK_VULKAN_OP_INSET_SHADOW: case GSK_VULKAN_OP_OUTSET_SHADOW: - case GSK_VULKAN_OP_BLEND_MODE: vertex_stride = gsk_vulkan_pipeline_get_vertex_stride (op->render.pipeline); n_bytes = round_up (n_bytes, vertex_stride); op->render.vertex_offset = n_bytes; @@ -1898,20 +1883,6 @@ gsk_vulkan_render_op_collect_vertex_data (GskVulkanOp *op_, gsk_outset_shadow_node_get_blur_radius (op->render.node)); break; - case GSK_VULKAN_OP_BLEND_MODE: - gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GSK_VULKAN_BLEND_MODE_PIPELINE (op->render.pipeline), - data + op->render.vertex_offset, - op->render.image_descriptor, - op->render.image_descriptor2, - &op->render.offset, - &op->render.node->bounds, - &gsk_blend_node_get_top_child (op->render.node)->bounds, - &gsk_blend_node_get_bottom_child (op->render.node)->bounds, - &op->render.source_rect, - &op->render.source2_rect, - gsk_blend_node_get_blend_mode (op->render.node)); - break; - default: g_assert_not_reached (); case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: @@ -1996,18 +1967,6 @@ gsk_vulkan_render_op_reserve_descriptor_sets (GskVulkanOp *op_, GSK_VULKAN_SAMPLER_DEFAULT); break; - case GSK_VULKAN_OP_BLEND_MODE: - if (op->render.source && op->render.source2) - { - op->render.image_descriptor = gsk_vulkan_render_get_image_descriptor (render, - op->render.source, - GSK_VULKAN_SAMPLER_DEFAULT); - op->render.image_descriptor2 = gsk_vulkan_render_get_image_descriptor (render, - op->render.source2, - GSK_VULKAN_SAMPLER_DEFAULT); - } - break; - case GSK_VULKAN_OP_LINEAR_GRADIENT: { gsize n_stops = gsk_linear_gradient_node_get_n_color_stops (op->render.node); @@ -2097,7 +2056,6 @@ gsk_vulkan_render_op_get_pipeline (GskVulkanOp *op_) case GSK_VULKAN_OP_BORDER: case GSK_VULKAN_OP_INSET_SHADOW: case GSK_VULKAN_OP_OUTSET_SHADOW: - case GSK_VULKAN_OP_BLEND_MODE: return gsk_vulkan_pipeline_get_pipeline (op->render.pipeline); case GSK_VULKAN_OP_TEXT: @@ -2176,15 +2134,6 @@ gsk_vulkan_render_op_command (GskVulkanOp *op_, &op->constants.clip); break; - case GSK_VULKAN_OP_BLEND_MODE: - if (!op->render.source || !op->render.source2) - break; - gsk_vulkan_blend_mode_pipeline_draw (GSK_VULKAN_BLEND_MODE_PIPELINE (op->render.pipeline), - command_buffer, - op->render.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (op->render.pipeline), - 1); - break; - default: g_assert_not_reached (); break; diff --git a/gsk/vulkan/gskvulkanrenderprivate.h b/gsk/vulkan/gskvulkanrenderprivate.h index c61a9fa7da..62833ecb39 100644 --- a/gsk/vulkan/gskvulkanrenderprivate.h +++ b/gsk/vulkan/gskvulkanrenderprivate.h @@ -32,9 +32,6 @@ typedef enum { GSK_VULKAN_PIPELINE_COLOR_TEXT, GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP, GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED, - GSK_VULKAN_PIPELINE_BLEND_MODE, - GSK_VULKAN_PIPELINE_BLEND_MODE_CLIP, - GSK_VULKAN_PIPELINE_BLEND_MODE_CLIP_ROUNDED, /* add more */ GSK_VULKAN_N_PIPELINES } GskVulkanPipelineType;