From: Benjamin Otte Date: Mon, 3 Jul 2023 05:53:22 +0000 (+0200) Subject: vulkan: Add a glyph shader X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~60^2~57 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2d6ebbb4d51ce185d75f9ac4ddc13c439a5205b7;p=gtk4.git vulkan: Add a glyph shader This shader is an updated version of the mask shader, but I want to use the mask name for the mask node and that's a different functionality. Also, add an operation for it and partially implement the mask node using it, so we can test that this shader works. Replacing the shader used for text rendering is the next step. --- diff --git a/gsk/meson.build b/gsk/meson.build index e1c06513f1..bfb09d7d0b 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -118,6 +118,7 @@ if have_vulkan 'vulkan/gskvulkancommandpool.c', 'vulkan/gskvulkancrossfadeop.c', 'vulkan/gskvulkanglyphcache.c', + 'vulkan/gskvulkanglyphop.c', 'vulkan/gskvulkanimage.c', 'vulkan/gskvulkaninsetshadowop.c', 'vulkan/gskvulkanlineargradientop.c', diff --git a/gsk/vulkan/gskvulkanglyphop.c b/gsk/vulkan/gskvulkanglyphop.c new file mode 100644 index 0000000000..4617806928 --- /dev/null +++ b/gsk/vulkan/gskvulkanglyphop.c @@ -0,0 +1,132 @@ +#include "config.h" + +#include "gskvulkanglyphopprivate.h" + +#include "vulkan/resources/glyph.vert.h" + +typedef struct _GskVulkanGlyphOp GskVulkanGlyphOp; + +struct _GskVulkanGlyphOp +{ + GskVulkanOp op; + + GskVulkanImage *image; + graphene_rect_t rect; + graphene_rect_t tex_rect; + GdkRGBA color; + + guint32 image_descriptor; + gsize vertex_offset; +}; + +static void +gsk_vulkan_glyph_op_finish (GskVulkanOp *op) +{ + GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op; + + g_object_unref (self->image); +} + +static void +gsk_vulkan_glyph_op_upload (GskVulkanOp *op, + GskVulkanRenderPass *pass, + GskVulkanRender *render, + GskVulkanUploader *uploader) +{ +} + +static inline gsize +round_up (gsize number, gsize divisor) +{ + return (number + divisor - 1) / divisor * divisor; +} + +static gsize +gsk_vulkan_glyph_op_count_vertex_data (GskVulkanOp *op, + gsize n_bytes) +{ + GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op; + gsize vertex_stride; + + vertex_stride = gsk_vulkan_glyph_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_glyph_op_collect_vertex_data (GskVulkanOp *op, + GskVulkanRenderPass *pass, + GskVulkanRender *render, + guchar *data) +{ + GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op; + GskVulkanGlyphInstance *instance = (GskVulkanGlyphInstance *) (data + self->vertex_offset); + + gsk_vulkan_rect_to_float (&self->rect, instance->rect); + gsk_vulkan_rect_to_float (&self->tex_rect, instance->tex_rect); + instance->tex_id = self->image_descriptor; + gsk_vulkan_rgba_to_float (&self->color, instance->color); +} + +static void +gsk_vulkan_glyph_op_reserve_descriptor_sets (GskVulkanOp *op, + GskVulkanRender *render) +{ + GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op; + + self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render, self->image, GSK_VULKAN_SAMPLER_DEFAULT); +} + +static VkPipeline +gsk_vulkan_glyph_op_get_pipeline (GskVulkanOp *op) +{ + return VK_NULL_HANDLE; +} + +static void +gsk_vulkan_glyph_op_command (GskVulkanOp *op, + GskVulkanRender *render, + VkPipelineLayout pipeline_layout, + VkCommandBuffer command_buffer) +{ + GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op; + + vkCmdDraw (command_buffer, + 6, 1, + 0, self->vertex_offset / gsk_vulkan_glyph_info.pVertexBindingDescriptions[0].stride); +} + +static const GskVulkanOpClass GSK_VULKAN_GLYPH_OP_CLASS = { + GSK_VULKAN_OP_SIZE (GskVulkanGlyphOp), + "glyph", + &gsk_vulkan_glyph_info, + gsk_vulkan_glyph_op_finish, + gsk_vulkan_glyph_op_upload, + gsk_vulkan_glyph_op_count_vertex_data, + gsk_vulkan_glyph_op_collect_vertex_data, + gsk_vulkan_glyph_op_reserve_descriptor_sets, + gsk_vulkan_glyph_op_get_pipeline, + gsk_vulkan_glyph_op_command +}; + +void +gsk_vulkan_glyph_op (GskVulkanRenderPass *render_pass, + const char *clip_type, + GskVulkanImage *image, + const graphene_rect_t *rect, + const graphene_point_t *offset, + const graphene_rect_t *tex_rect, + const GdkRGBA *color) +{ + GskVulkanGlyphOp *self; + + self = (GskVulkanGlyphOp *) gsk_vulkan_op_alloc (render_pass, &GSK_VULKAN_GLYPH_OP_CLASS); + + ((GskVulkanOp *) self)->clip_type = g_intern_string (clip_type); + self->image = g_object_ref (image); + graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect); + gsk_vulkan_normalize_tex_coords (&self->tex_rect, rect, tex_rect); + self->color = *color; +} diff --git a/gsk/vulkan/gskvulkanglyphopprivate.h b/gsk/vulkan/gskvulkanglyphopprivate.h new file mode 100644 index 0000000000..deb64b902f --- /dev/null +++ b/gsk/vulkan/gskvulkanglyphopprivate.h @@ -0,0 +1,17 @@ +#pragma once + +#include "gskvulkanopprivate.h" + +G_BEGIN_DECLS + +void gsk_vulkan_glyph_op (GskVulkanRenderPass *render_pass, + const char *clip_type, + GskVulkanImage *image, + const graphene_rect_t *rect, + const graphene_point_t *offset, + const graphene_rect_t *tex_rect, + const GdkRGBA *color); + + +G_END_DECLS + diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index b4989ec6a0..4a33d21fd2 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -17,6 +17,7 @@ #include "gskvulkancoloropprivate.h" #include "gskvulkancolortextpipelineprivate.h" #include "gskvulkancrossfadeopprivate.h" +#include "gskvulkanglyphopprivate.h" #include "gskvulkaninsetshadowopprivate.h" #include "gskvulkanlineargradientopprivate.h" #include "gskvulkanopprivate.h" @@ -1297,6 +1298,52 @@ gsk_vulkan_render_pass_add_blur_node (GskVulkanRenderPass *self, return TRUE; } +static inline gboolean +gsk_vulkan_render_pass_add_mask_node (GskVulkanRenderPass *self, + GskVulkanRender *render, + const GskVulkanParseState *state, + GskRenderNode *node) +{ + GskVulkanImage *mask_image; + graphene_rect_t mask_tex_rect; + GskRenderNode *source, *mask; + GskMaskMode mode; + + mode = gsk_mask_node_get_mask_mode (node); + source = gsk_mask_node_get_source (node); + mask = gsk_mask_node_get_mask (node); + mask_image = gsk_vulkan_render_pass_get_node_as_image (self, + render, + state, + mask, + &mask_tex_rect); + if (mask_image == NULL) + { + if (mode == GSK_MASK_MODE_INVERTED_ALPHA) + gsk_vulkan_render_pass_add_node (self, render, state, source); + + return TRUE; + } + + /* Use the glyph shader as an optimization */ + if (mode == GSK_MASK_MODE_ALPHA && + gsk_render_node_get_node_type (source) == GSK_COLOR_NODE) + { + graphene_rect_t bounds; + if (graphene_rect_intersection (&source->bounds, &mask->bounds, &bounds)) + gsk_vulkan_glyph_op (self, + gsk_vulkan_clip_get_clip_type (&state->clip, &state->offset, &bounds), + mask_image, + &bounds, + &state->offset, + &mask_tex_rect, + gsk_color_node_get_color (source)); + return TRUE; + } + + return FALSE; +} + static inline gboolean gsk_vulkan_render_pass_add_debug_node (GskVulkanRenderPass *self, GskVulkanRender *render, @@ -1343,7 +1390,7 @@ static const GskVulkanRenderPassNodeFunc nodes_vtable[] = { [GSK_DEBUG_NODE] = gsk_vulkan_render_pass_add_debug_node, [GSK_GL_SHADER_NODE] = NULL, [GSK_TEXTURE_SCALE_NODE] = gsk_vulkan_render_pass_add_texture_scale_node, - [GSK_MASK_NODE] = NULL, + [GSK_MASK_NODE] = gsk_vulkan_render_pass_add_mask_node, }; static void diff --git a/gsk/vulkan/resources/glyph-clip-rounded.frag.spv b/gsk/vulkan/resources/glyph-clip-rounded.frag.spv new file mode 100644 index 0000000000..ff2212a266 Binary files /dev/null and b/gsk/vulkan/resources/glyph-clip-rounded.frag.spv differ diff --git a/gsk/vulkan/resources/glyph-clip-rounded.vert.spv b/gsk/vulkan/resources/glyph-clip-rounded.vert.spv new file mode 100644 index 0000000000..d177868088 Binary files /dev/null and b/gsk/vulkan/resources/glyph-clip-rounded.vert.spv differ diff --git a/gsk/vulkan/resources/glyph-clip.frag.spv b/gsk/vulkan/resources/glyph-clip.frag.spv new file mode 100644 index 0000000000..bfd95cdd2e Binary files /dev/null and b/gsk/vulkan/resources/glyph-clip.frag.spv differ diff --git a/gsk/vulkan/resources/glyph-clip.vert.spv b/gsk/vulkan/resources/glyph-clip.vert.spv new file mode 100644 index 0000000000..d177868088 Binary files /dev/null and b/gsk/vulkan/resources/glyph-clip.vert.spv differ diff --git a/gsk/vulkan/resources/glyph.frag b/gsk/vulkan/resources/glyph.frag new file mode 100644 index 0000000000..0f87adcd51 --- /dev/null +++ b/gsk/vulkan/resources/glyph.frag @@ -0,0 +1,20 @@ +#version 450 + +#include "common.frag.glsl" +#include "clip.frag.glsl" +#include "rect.frag.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in flat Rect inRect; +layout(location = 2) in vec2 inTexCoord; +layout(location = 3) in flat uint inTexId; +layout(location = 4) in flat vec4 inColor; + +layout(location = 0) out vec4 color; + +void main() +{ + float alpha = inColor.a * rect_coverage (inRect, inPos); + alpha *= texture(get_sampler (inTexId), inTexCoord).a; + color = clip_scaled (inPos, vec4(inColor.rgb, 1) * alpha); +} diff --git a/gsk/vulkan/resources/glyph.frag.spv b/gsk/vulkan/resources/glyph.frag.spv new file mode 100644 index 0000000000..bfd95cdd2e Binary files /dev/null and b/gsk/vulkan/resources/glyph.frag.spv differ diff --git a/gsk/vulkan/resources/glyph.vert b/gsk/vulkan/resources/glyph.vert new file mode 100644 index 0000000000..0f9b647e14 --- /dev/null +++ b/gsk/vulkan/resources/glyph.vert @@ -0,0 +1,26 @@ +#version 450 + +#include "common.vert.glsl" +#include "rect.vert.glsl" + +layout(location = 0) in vec4 inRect; +layout(location = 1) in vec4 inTexRect; +layout(location = 2) in vec4 inColor; +layout(location = 3) in uint inTexId; + +layout(location = 0) out vec2 outPos; +layout(location = 1) out flat Rect outRect; +layout(location = 2) out vec2 outTexCoord; +layout(location = 3) out flat uint outTexId; +layout(location = 4) out flat vec4 outColor; + +void main() { + Rect r = rect_from_gsk (inRect); + vec2 pos = set_position_from_rect (r); + + outPos = pos; + outRect = r; + outTexCoord = scale_tex_coord (pos, r, inTexRect); + outTexId = inTexId; + outColor = inColor; +} diff --git a/gsk/vulkan/resources/glyph.vert.spv b/gsk/vulkan/resources/glyph.vert.spv new file mode 100644 index 0000000000..e92bf9249a Binary files /dev/null and b/gsk/vulkan/resources/glyph.vert.spv differ diff --git a/gsk/vulkan/resources/meson.build b/gsk/vulkan/resources/meson.build index 5075f97b83..8881eb1b6b 100644 --- a/gsk/vulkan/resources/meson.build +++ b/gsk/vulkan/resources/meson.build @@ -18,6 +18,7 @@ gsk_private_vulkan_fragment_shaders = [ 'color.frag', 'color-matrix.frag', 'cross-fade.frag', + 'glyph.frag', 'inset-shadow.frag', 'linear.frag', 'mask.frag', @@ -32,6 +33,7 @@ gsk_private_vulkan_vertex_shaders = [ 'color.vert', 'color-matrix.vert', 'cross-fade.vert', + 'glyph.vert', 'inset-shadow.vert', 'linear.vert', 'mask.vert',