From cfe0da1eedda4d03cf355b83096be32399610a3b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 11 Aug 2024 08:10:59 +0200 Subject: [PATCH] gpu: Add GskGpuLoadOp We want to differentiate between CLEAR, DONT_CARE and LOAD in the future, and the current boolean doesn't allow that. Also implement support for the the different ops in the Vulkan renderpass code. --- gsk/gpu/gskgpunodeprocessor.c | 5 +++ gsk/gpu/gskgpurenderpassop.c | 64 +++++++++++++++++++++-------- gsk/gpu/gskgpurenderpassopprivate.h | 3 +- gsk/gpu/gskgputypesprivate.h | 7 ++++ gsk/gpu/gskvulkandevice.c | 19 +++++---- gsk/gpu/gskvulkandeviceprivate.h | 1 + 6 files changed, 75 insertions(+), 24 deletions(-) diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index b611f9fbc7..70d43a6389 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -325,6 +325,7 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self, gsk_gpu_render_pass_begin_op (frame, image, &area, + GSK_GPU_LOAD_OP_CLEAR, GSK_VEC4_TRANSPARENT, GSK_RENDER_PASS_OFFSCREEN); @@ -750,6 +751,7 @@ gsk_gpu_copy_image (GskGpuFrame *frame, gsk_gpu_render_pass_begin_op (other.frame, copy, &(cairo_rectangle_int_t) { 0, 0, width, height }, + GSK_GPU_LOAD_OP_DONT_CARE, NULL, GSK_RENDER_PASS_OFFSCREEN); @@ -1105,6 +1107,8 @@ gsk_gpu_first_node_begin_rendering (GskGpuNodeProcessor *self, gsk_gpu_render_pass_begin_op (self->frame, info->target, &self->scissor, + clear_color ? GSK_GPU_LOAD_OP_CLEAR + : GSK_GPU_LOAD_OP_DONT_CARE, clear_color, info->pass_type); } @@ -4279,6 +4283,7 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame, gsk_gpu_render_pass_begin_op (frame, target, &rect, + GSK_GPU_LOAD_OP_DONT_CARE, NULL, pass_type); diff --git a/gsk/gpu/gskgpurenderpassop.c b/gsk/gpu/gskgpurenderpassop.c index 07743961f8..8894f4229d 100644 --- a/gsk/gpu/gskgpurenderpassop.c +++ b/gsk/gpu/gskgpurenderpassop.c @@ -21,7 +21,7 @@ struct _GskGpuRenderPassOp GskGpuImage *target; cairo_rectangle_int_t area; - gboolean clear; + GskGpuLoadOp load_op; float clear_color[4]; GskRenderPassType pass_type; }; @@ -45,8 +45,21 @@ gsk_gpu_render_pass_op_print (GskGpuOp *op, gsk_gpu_print_op (string, indent, "begin-render-pass"); gsk_gpu_print_image (string, self->target); gsk_gpu_print_int_rect (string, &self->area); - if (self->clear) - gsk_gpu_print_rgba (string, self->clear_color); + switch (self->load_op) + { + case GSK_GPU_LOAD_OP_LOAD: + gsk_gpu_print_string (string, "load"); + break; + case GSK_GPU_LOAD_OP_CLEAR: + gsk_gpu_print_rgba (string, self->clear_color); + break; + case GSK_GPU_LOAD_OP_DONT_CARE: + gsk_gpu_print_string (string, "dont-care"); + break; + default: + g_assert_not_reached (); + break; + } gsk_gpu_print_newline (string); } @@ -100,6 +113,21 @@ gsk_gpu_render_pass_op_do_barriers (GskGpuRenderPassOp *self, } } +static VkAttachmentLoadOp +gsk_gpu_load_op_to_vk_load_op (GskGpuLoadOp op) +{ + switch (op) + { + case GSK_GPU_LOAD_OP_LOAD: + return VK_ATTACHMENT_LOAD_OP_LOAD; + case GSK_GPU_LOAD_OP_CLEAR: + return VK_ATTACHMENT_LOAD_OP_CLEAR; + case GSK_GPU_LOAD_OP_DONT_CARE: + return VK_ATTACHMENT_LOAD_OP_DONT_CARE; + default: + g_return_val_if_reached (VK_ATTACHMENT_LOAD_OP_DONT_CARE); + } +} static GskGpuOp * gsk_gpu_render_pass_op_vk_command (GskGpuOp *op, GskGpuFrame *frame, @@ -115,6 +143,7 @@ gsk_gpu_render_pass_op_vk_command (GskGpuOp *op, state->vk_format = gsk_vulkan_image_get_vk_format (GSK_VULKAN_IMAGE (self->target)); state->vk_render_pass = gsk_vulkan_device_get_vk_render_pass (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)), state->vk_format, + gsk_gpu_load_op_to_vk_load_op (self->load_op), gsk_vulkan_image_get_vk_image_layout (GSK_VULKAN_IMAGE (self->target)), gsk_gpu_render_pass_type_to_vk_image_layout (self->pass_type)); @@ -141,19 +170,19 @@ gsk_gpu_render_pass_op_vk_command (GskGpuOp *op, { self->area.x, self->area.y }, { self->area.width, self->area.height } }, - .clearValueCount = 1, - .pClearValues = (VkClearValue [1]) { + .clearValueCount = self->load_op == GSK_GPU_LOAD_OP_CLEAR ? 1 : 0, + .pClearValues = self->load_op == GSK_GPU_LOAD_OP_CLEAR ? (VkClearValue [1]) { { .color = { .float32 = { - self->clear ? self->clear_color[0] : 0, - self->clear ? self->clear_color[1] : 0, - self->clear ? self->clear_color[2] : 0, - self->clear ? self->clear_color[3] : 0 + self->clear_color[0], + self->clear_color[1], + self->clear_color[2], + self->clear_color[3] } } - } - } + } + } : NULL, }, VK_SUBPASS_CONTENTS_INLINE); @@ -194,7 +223,7 @@ gsk_gpu_render_pass_op_gl_command (GskGpuOp *op, glScissor (self->area.x, state->flip_y - self->area.y - self->area.height, self->area.width, self->area.height); else glScissor (self->area.x, self->area.y, self->area.width, self->area.height); - if (self->clear) + if (self->load_op == GSK_GPU_LOAD_OP_CLEAR) { glClearColor (self->clear_color[0], self->clear_color[1], self->clear_color[2], self->clear_color[3]); glClear (GL_COLOR_BUFFER_BIT); @@ -329,18 +358,21 @@ void gsk_gpu_render_pass_begin_op (GskGpuFrame *frame, GskGpuImage *image, const cairo_rectangle_int_t *area, - float clear_color_or_null[4], + GskGpuLoadOp load_op, + float clear_color[4], GskRenderPassType pass_type) { GskGpuRenderPassOp *self; + g_assert (load_op != GSK_GPU_LOAD_OP_CLEAR || clear_color != NULL); + self = (GskGpuRenderPassOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_RENDER_PASS_OP_CLASS); self->target = g_object_ref (image); self->area = *area; - self->clear = clear_color_or_null != NULL; - if (clear_color_or_null) - gsk_gpu_vec4_to_float (clear_color_or_null, self->clear_color); + self->load_op = load_op; + if (self->load_op == GSK_GPU_LOAD_OP_CLEAR) + gsk_gpu_vec4_to_float (clear_color, self->clear_color); self->pass_type = pass_type; } diff --git a/gsk/gpu/gskgpurenderpassopprivate.h b/gsk/gpu/gskgpurenderpassopprivate.h index cdfa3aa5ff..569ee2e482 100644 --- a/gsk/gpu/gskgpurenderpassopprivate.h +++ b/gsk/gpu/gskgpurenderpassopprivate.h @@ -11,7 +11,8 @@ G_BEGIN_DECLS void gsk_gpu_render_pass_begin_op (GskGpuFrame *frame, GskGpuImage *image, const cairo_rectangle_int_t *area, - float clear_color_or_null[4], + GskGpuLoadOp load_op, + float clear_color[4], GskRenderPassType pass_type); void gsk_gpu_render_pass_end_op (GskGpuFrame *frame, GskGpuImage *image, diff --git a/gsk/gpu/gskgputypesprivate.h b/gsk/gpu/gskgputypesprivate.h index 9c9751cdcb..a73d797c59 100644 --- a/gsk/gpu/gskgputypesprivate.h +++ b/gsk/gpu/gskgputypesprivate.h @@ -64,6 +64,13 @@ typedef enum GSK_RENDER_PASS_EXPORT } GskRenderPassType; +typedef enum +{ + GSK_GPU_LOAD_OP_LOAD, + GSK_GPU_LOAD_OP_CLEAR, + GSK_GPU_LOAD_OP_DONT_CARE +} GskGpuLoadOp; + typedef enum { GSK_GPU_PATTERN_DONE, GSK_GPU_PATTERN_COLOR, diff --git a/gsk/gpu/gskvulkandevice.c b/gsk/gpu/gskvulkandevice.c index 6323af3d70..9cea4d2748 100644 --- a/gsk/gpu/gskvulkandevice.c +++ b/gsk/gpu/gskvulkandevice.c @@ -74,6 +74,7 @@ struct _PipelineCacheKey struct _RenderPassCacheKey { VkFormat format; + VkAttachmentLoadOp vk_load_op; VkImageLayout from_layout; VkImageLayout to_layout; VkRenderPass render_pass; @@ -114,8 +115,9 @@ render_pass_cache_key_hash (gconstpointer data) { const RenderPassCacheKey *key = data; - return (key->from_layout << 20) ^ - (key->to_layout << 16) ^ + return (key->from_layout << 26) ^ + (key->to_layout << 18) ^ + (key->vk_load_op << 16) ^ (key->format); } @@ -128,6 +130,7 @@ render_pass_cache_key_equal (gconstpointer a, return keya->from_layout == keyb->from_layout && keya->to_layout == keyb->to_layout && + keya->vk_load_op == keyb->vk_load_op && keya->format == keyb->format; } @@ -706,10 +709,11 @@ gsk_vulkan_device_remove_ycbcr (GskVulkanDevice *self, } VkRenderPass -gsk_vulkan_device_get_vk_render_pass (GskVulkanDevice *self, - VkFormat format, - VkImageLayout from_layout, - VkImageLayout to_layout) +gsk_vulkan_device_get_vk_render_pass (GskVulkanDevice *self, + VkFormat format, + VkAttachmentLoadOp vk_load_op, + VkImageLayout from_layout, + VkImageLayout to_layout) { RenderPassCacheKey cache_key; RenderPassCacheKey *cached_result; @@ -718,6 +722,7 @@ gsk_vulkan_device_get_vk_render_pass (GskVulkanDevice *self, cache_key = (RenderPassCacheKey) { .format = format, + .vk_load_op = vk_load_op, .from_layout = from_layout, .to_layout = to_layout, }; @@ -735,7 +740,7 @@ gsk_vulkan_device_get_vk_render_pass (GskVulkanDevice *self, { .format = format, .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .loadOp = vk_load_op, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, .initialLayout = from_layout, .finalLayout = to_layout diff --git a/gsk/gpu/gskvulkandeviceprivate.h b/gsk/gpu/gskvulkandeviceprivate.h index 5125badb32..c9e9e18132 100644 --- a/gsk/gpu/gskvulkandeviceprivate.h +++ b/gsk/gpu/gskvulkandeviceprivate.h @@ -53,6 +53,7 @@ void gsk_vulkan_device_remove_ycbcr (GskVulk VkRenderPass gsk_vulkan_device_get_vk_render_pass (GskVulkanDevice *self, VkFormat format, + VkAttachmentLoadOp vk_load_op, VkImageLayout from_layout, VkImageLayout to_layout); VkPipeline gsk_vulkan_device_get_vk_pipeline (GskVulkanDevice *self,