From bb2cd7225eb2eeaf2ab343af916eaeef1ceebb78 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 12 Jul 2023 09:26:24 +0200 Subject: [PATCH] vulkan: Add a clear op The op emits a vkCmdClearAttachments() with a given color. That can be used with color nodes that are pixel-aligned and opaque to significantly speed up rendering when the window background is a solid color. However, currently this fails a bit outside of fullscreen when rounded clip rectangles are in use to draw rounded corners. --- gsk/meson.build | 1 + gsk/vulkan/gskvulkanclearop.c | 124 +++++++++++++++++++++++++++ gsk/vulkan/gskvulkanclearopprivate.h | 13 +++ gsk/vulkan/gskvulkanrenderpass.c | 42 ++++++++- 4 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 gsk/vulkan/gskvulkanclearop.c create mode 100644 gsk/vulkan/gskvulkanclearopprivate.h diff --git a/gsk/meson.build b/gsk/meson.build index 224573db42..7422b8eac3 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -111,6 +111,7 @@ if have_vulkan 'vulkan/gskvulkanblurop.c', 'vulkan/gskvulkanborderop.c', 'vulkan/gskvulkanbuffer.c', + 'vulkan/gskvulkanclearop.c', 'vulkan/gskvulkanclip.c', 'vulkan/gskvulkancolormatrixop.c', 'vulkan/gskvulkancolorop.c', diff --git a/gsk/vulkan/gskvulkanclearop.c b/gsk/vulkan/gskvulkanclearop.c new file mode 100644 index 0000000000..edb1ad3c68 --- /dev/null +++ b/gsk/vulkan/gskvulkanclearop.c @@ -0,0 +1,124 @@ +#include "config.h" + +#include "gskvulkanclearopprivate.h" + +#include "gskvulkanprivate.h" + +typedef struct _GskVulkanClearOp GskVulkanClearOp; + +struct _GskVulkanClearOp +{ + GskVulkanOp op; + + cairo_rectangle_int_t rect; + GdkRGBA color; +}; + +static void +gsk_vulkan_clear_op_finish (GskVulkanOp *op) +{ +} + +static void +gsk_vulkan_clear_op_print (GskVulkanOp *op, + GString *string, + guint indent) +{ + GskVulkanClearOp *self = (GskVulkanClearOp *) op; + + print_indent (string, indent); + print_int_rect (string, &self->rect); + g_string_append_printf (string, "clear "); + print_rgba (string, &self->color); + print_newline (string); +} + +static void +gsk_vulkan_clear_op_upload (GskVulkanOp *op, + GskVulkanUploader *uploader) +{ +} + +static gsize +gsk_vulkan_clear_op_count_vertex_data (GskVulkanOp *op, + gsize n_bytes) +{ + return n_bytes; +} + +static void +gsk_vulkan_clear_op_collect_vertex_data (GskVulkanOp *op, + guchar *data) +{ +} + +static void +gsk_vulkan_clear_op_reserve_descriptor_sets (GskVulkanOp *op, + GskVulkanRender *render) +{ +} + +static void +gsk_vulkan_init_clear_value (VkClearValue *value, + const GdkRGBA *rgba) +{ + gsk_vulkan_rgba_to_float (rgba, value->color.float32); +} + +static GskVulkanOp * +gsk_vulkan_clear_op_command (GskVulkanOp *op, + GskVulkanRender *render, + VkPipelineLayout pipeline_layout, + VkCommandBuffer command_buffer) +{ + GskVulkanClearOp *self = (GskVulkanClearOp *) op; + VkClearValue clear_value; + + gsk_vulkan_init_clear_value (&clear_value, &self->color); + + vkCmdClearAttachments (command_buffer, + 1, + &(VkClearAttachment) { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + clear_value, + }, + 1, + &(VkClearRect) { + { + { self->rect.x, self->rect.y }, + { self->rect.width, self->rect.height }, + }, + 0, + 1 + }); + + return op->next; +} + +static const GskVulkanOpClass GSK_VULKAN_SCISSOR_OP_CLASS = { + GSK_VULKAN_OP_SIZE (GskVulkanClearOp), + GSK_VULKAN_STAGE_COMMAND, + NULL, + NULL, + gsk_vulkan_clear_op_finish, + gsk_vulkan_clear_op_print, + gsk_vulkan_clear_op_upload, + gsk_vulkan_clear_op_count_vertex_data, + gsk_vulkan_clear_op_collect_vertex_data, + gsk_vulkan_clear_op_reserve_descriptor_sets, + gsk_vulkan_clear_op_command +}; + +void +gsk_vulkan_clear_op (GskVulkanRender *render, + const cairo_rectangle_int_t *rect, + const GdkRGBA *color) +{ + GskVulkanClearOp *self; + + self = (GskVulkanClearOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_SCISSOR_OP_CLASS); + + self->rect = *rect; + self->color = *color; +} diff --git a/gsk/vulkan/gskvulkanclearopprivate.h b/gsk/vulkan/gskvulkanclearopprivate.h new file mode 100644 index 0000000000..92f3351175 --- /dev/null +++ b/gsk/vulkan/gskvulkanclearopprivate.h @@ -0,0 +1,13 @@ +#pragma once + +#include "gskvulkanopprivate.h" + +G_BEGIN_DECLS + +void gsk_vulkan_clear_op (GskVulkanRender *render, + const cairo_rectangle_int_t *rect, + const GdkRGBA *color); + + +G_END_DECLS + diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index ec3d987814..4d331ddfc1 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -12,6 +12,7 @@ #include "gskvulkanblendmodeopprivate.h" #include "gskvulkanbluropprivate.h" #include "gskvulkanborderopprivate.h" +#include "gskvulkanclearopprivate.h" #include "gskvulkanclipprivate.h" #include "gskvulkancolormatrixopprivate.h" #include "gskvulkancoloropprivate.h" @@ -349,11 +350,46 @@ gsk_vulkan_render_pass_add_color_node (GskVulkanRenderPass *self, const GskVulkanParseState *state, GskRenderNode *node) { + cairo_rectangle_int_t int_clipped; + graphene_rect_t rect, clipped; + const GdkRGBA *color; + + color = gsk_color_node_get_color (node); + graphene_rect_offset_r (&node->bounds, + state->offset.x, state->offset.y, + &rect); + graphene_rect_intersection (&state->clip.rect.bounds, &rect, &clipped); + + if (gdk_rgba_is_opaque (color) && + gsk_vulkan_parse_rect_is_integer (state, &clipped, &int_clipped)) + { + /* now handle all the clip */ + if (!gdk_rectangle_intersect (&int_clipped, &state->scissor, &int_clipped)) + return TRUE; + + /* we have handled the bounds, now do the corners */ + if (state->clip.type != GSK_VULKAN_CLIP_ROUNDED || + gsk_vulkan_clip_contains_rect (&state->clip, + graphene_point_zero (), + &GRAPHENE_RECT_INIT ( + int_clipped.x / graphene_vec2_get_x (&state->scale), + int_clipped.y / graphene_vec2_get_y (&state->scale), + int_clipped.width / graphene_vec2_get_x (&state->scale), + int_clipped.height / graphene_vec2_get_y (&state->scale) + ))) + { + gsk_vulkan_clear_op (render, + &int_clipped, + color); + return TRUE; + } + } + gsk_vulkan_color_op (render, gsk_vulkan_clip_get_clip_type (&state->clip, &state->offset, &node->bounds), - &node->bounds, - &state->offset, - gsk_color_node_get_color (node)); + &rect, + graphene_point_zero (), + color); return TRUE; } -- 2.30.2