From: Benjamin Otte Date: Sat, 24 Jun 2023 22:56:13 +0000 (+0200) Subject: vulkan: Add new renderops for texture rendering X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~60^2~84 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=94a64329c29e0172ff73e45faca397ec052f1721;p=gtk4.git vulkan: Add new renderops for texture rendering Adds 2 ops: - Upload Creates a new Vulkan image and uploads data into it - Texture Draws a given image These 2 ops are then used for GskTextureNodes. --- diff --git a/gsk/meson.build b/gsk/meson.build index e5c51a72ae..b24108c6b2 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -132,6 +132,8 @@ if have_vulkan 'vulkan/gskvulkanshader.c', 'vulkan/gskvulkantextpipeline.c', 'vulkan/gskvulkantexturepipeline.c', + 'vulkan/gskvulkantextureop.c', + 'vulkan/gskvulkanuploadop.c', ]) subdir('vulkan/resources') diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index d13ecbc432..bd31143b93 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -1082,3 +1082,10 @@ gsk_vulkan_image_get_vk_format (GskVulkanImage *self) { return self->vk_format; } + +GdkMemoryFormat +gsk_vulkan_image_get_format (GskVulkanImage *self) +{ + return self->format; +} + diff --git a/gsk/vulkan/gskvulkanimageprivate.h b/gsk/vulkan/gskvulkanimageprivate.h index 44423341e1..b70019eead 100644 --- a/gsk/vulkan/gskvulkanimageprivate.h +++ b/gsk/vulkan/gskvulkanimageprivate.h @@ -82,6 +82,7 @@ gsize gsk_vulkan_image_get_height (GskVulk VkImage gsk_vulkan_image_get_image (GskVulkanImage *self); VkImageView gsk_vulkan_image_get_image_view (GskVulkanImage *self); VkFormat gsk_vulkan_image_get_vk_format (GskVulkanImage *self); +GdkMemoryFormat gsk_vulkan_image_get_format (GskVulkanImage *self); G_END_DECLS diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index ab2443415e..500afc1d8f 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -20,12 +20,14 @@ #include "gskvulkaneffectpipelineprivate.h" #include "gskvulkanlineargradientpipelineprivate.h" #include "gskvulkanopprivate.h" +#include "gskvulkanrendererprivate.h" #include "gskvulkantextpipelineprivate.h" #include "gskvulkantexturepipelineprivate.h" #include "gskvulkanimageprivate.h" #include "gskvulkanpushconstantsprivate.h" #include "gskvulkanscissoropprivate.h" -#include "gskvulkanrendererprivate.h" +#include "gskvulkantextureopprivate.h" +#include "gskvulkanuploadopprivate.h" #include "gskprivate.h" #include "gdk/gdkvulkancontextprivate.h" @@ -52,7 +54,6 @@ typedef enum { GSK_VULKAN_OP_FALLBACK, GSK_VULKAN_OP_FALLBACK_CLIP, GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP, - GSK_VULKAN_OP_TEXTURE, GSK_VULKAN_OP_TEXTURE_SCALE, GSK_VULKAN_OP_COLOR, GSK_VULKAN_OP_LINEAR_GRADIENT, @@ -530,11 +531,9 @@ gsk_vulkan_render_pass_add_texture_node (GskVulkanRenderPass *self, GskRenderNode *node) { GskVulkanPipelineType pipeline_type; - GskVulkanOpRender op = { - .type = GSK_VULKAN_OP_TEXTURE, - .node = node, - .offset = state->offset, - }; + GskVulkanImage *image; + GskVulkanRenderer *renderer; + GdkTexture *texture; if (gsk_vulkan_clip_contains_rect (&state->clip, &state->offset, &node->bounds)) pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE; @@ -543,8 +542,24 @@ gsk_vulkan_render_pass_add_texture_node (GskVulkanRenderPass *self, else pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP_ROUNDED; - op.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type); - gsk_vulkan_render_pass_add_op (self, (GskVulkanOp *) &op); + renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)); + texture = gsk_texture_node_get_texture (node); + image = gsk_vulkan_renderer_get_texture_image (renderer, texture); + if (image == NULL) + { + image = gsk_vulkan_upload_op_init_texture (gsk_vulkan_render_pass_alloc_op (self, gsk_vulkan_upload_op_size ()), + self->vulkan, + texture); + gsk_vulkan_renderer_add_texture_image (renderer, texture, image); + } + + gsk_vulkan_texture_op_init (gsk_vulkan_render_pass_alloc_op (self, gsk_vulkan_texture_op_size ()), + gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type), + image, + GSK_VULKAN_SAMPLER_DEFAULT, + &node->bounds, + &state->offset, + &GRAPHENE_RECT_INIT(0, 0, 1, 1)); return TRUE; } @@ -1632,16 +1647,6 @@ gsk_vulkan_render_op_upload (GskVulkanOp *op_, } break; - case GSK_VULKAN_OP_TEXTURE: - { - op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), - gsk_texture_node_get_texture (op->render.node), - uploader); - op->render.source_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1); - gsk_vulkan_render_add_cleanup_image (render, op->render.source); - } - break; - case GSK_VULKAN_OP_TEXTURE_SCALE: { op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), @@ -1869,7 +1874,6 @@ gsk_vulkan_render_op_count_vertex_data (GskVulkanOp *op_, case GSK_VULKAN_OP_FALLBACK: case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: - case GSK_VULKAN_OP_TEXTURE: case GSK_VULKAN_OP_TEXTURE_SCALE: case GSK_VULKAN_OP_REPEAT: case GSK_VULKAN_OP_COLOR: @@ -1935,7 +1939,6 @@ gsk_vulkan_render_op_collect_vertex_data (GskVulkanOp *op_, case GSK_VULKAN_OP_FALLBACK: case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: - case GSK_VULKAN_OP_TEXTURE: case GSK_VULKAN_OP_TEXTURE_SCALE: gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE (op->render.pipeline), data + op->render.vertex_offset, @@ -2189,7 +2192,6 @@ gsk_vulkan_render_op_reserve_descriptor_sets (GskVulkanOp *op_, case GSK_VULKAN_OP_FALLBACK: case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: - case GSK_VULKAN_OP_TEXTURE: case GSK_VULKAN_OP_OPACITY: case GSK_VULKAN_OP_BLUR: case GSK_VULKAN_OP_COLOR_MATRIX: @@ -2321,7 +2323,6 @@ gsk_vulkan_render_op_get_pipeline (GskVulkanOp *op_) case GSK_VULKAN_OP_FALLBACK: case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: - case GSK_VULKAN_OP_TEXTURE: case GSK_VULKAN_OP_TEXTURE_SCALE: case GSK_VULKAN_OP_REPEAT: case GSK_VULKAN_OP_COLOR: @@ -2361,7 +2362,6 @@ gsk_vulkan_render_op_command (GskVulkanOp *op_, case GSK_VULKAN_OP_FALLBACK: case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: - case GSK_VULKAN_OP_TEXTURE: case GSK_VULKAN_OP_TEXTURE_SCALE: case GSK_VULKAN_OP_REPEAT: if (!op->render.source) diff --git a/gsk/vulkan/gskvulkantextureop.c b/gsk/vulkan/gskvulkantextureop.c new file mode 100644 index 0000000000..3dee37cf39 --- /dev/null +++ b/gsk/vulkan/gskvulkantextureop.c @@ -0,0 +1,147 @@ +#include "config.h" + +#include "gskvulkantextureopprivate.h" + +#include "gskvulkantexturepipelineprivate.h" + +typedef struct _GskVulkanTextureOp GskVulkanTextureOp; + +struct _GskVulkanTextureOp +{ + GskVulkanOp op; + + GskVulkanImage *image; + GskVulkanRenderSampler sampler; + graphene_rect_t rect; + graphene_rect_t tex_rect; + + guint32 image_descriptor; + guint32 sampler_descriptor; + GskVulkanPipeline *pipeline; + gsize vertex_offset; +}; + +static void +gsk_vulkan_texture_op_finish (GskVulkanOp *op) +{ + GskVulkanTextureOp *self = (GskVulkanTextureOp *) op; + + g_object_unref (self->image); +} + +static void +gsk_vulkan_texture_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_texture_op_count_vertex_data (GskVulkanOp *op, + gsize n_bytes) +{ + GskVulkanTextureOp *self = (GskVulkanTextureOp *) op; + gsize vertex_stride; + + vertex_stride = gsk_vulkan_pipeline_get_vertex_stride (self->pipeline); + n_bytes = round_up (n_bytes, vertex_stride); + self->vertex_offset = n_bytes; + n_bytes += vertex_stride; + return n_bytes; +} + +static void +gsk_vulkan_texture_op_collect_vertex_data (GskVulkanOp *op, + GskVulkanRenderPass *pass, + GskVulkanRender *render, + guchar *data) +{ + GskVulkanTextureOp *self = (GskVulkanTextureOp *) op; + + gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE (self->pipeline), + data + self->vertex_offset, + (guint32[2]) { + self->image_descriptor, + self->sampler_descriptor, + }, + graphene_point_zero (), + &self->rect, + &self->tex_rect); +} + +static void +gsk_vulkan_texture_op_reserve_descriptor_sets (GskVulkanOp *op, + GskVulkanRender *render) +{ + GskVulkanTextureOp *self = (GskVulkanTextureOp *) op; + + self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render, self->image); + self->sampler_descriptor = gsk_vulkan_render_get_sampler_descriptor (render, self->sampler); +} + +static GskVulkanPipeline * +gsk_vulkan_texture_op_get_pipeline (GskVulkanOp *op) +{ + GskVulkanTextureOp *self = (GskVulkanTextureOp *) op; + + return self->pipeline; +} + +static void +gsk_vulkan_texture_op_command (GskVulkanOp *op, + VkPipelineLayout pipeline_layout, + VkCommandBuffer command_buffer) +{ + GskVulkanTextureOp *self = (GskVulkanTextureOp *) op; + + gsk_vulkan_texture_pipeline_draw (GSK_VULKAN_TEXTURE_PIPELINE (self->pipeline), + command_buffer, + self->vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (self->pipeline), + 1); +} + +static const GskVulkanOpClass GSK_VULKAN_TEXTURE_OP_CLASS = { + GSK_VULKAN_OP_SIZE (GskVulkanTextureOp), + gsk_vulkan_texture_op_finish, + gsk_vulkan_texture_op_upload, + gsk_vulkan_texture_op_count_vertex_data, + gsk_vulkan_texture_op_collect_vertex_data, + gsk_vulkan_texture_op_reserve_descriptor_sets, + gsk_vulkan_texture_op_get_pipeline, + gsk_vulkan_texture_op_command +}; + +gsize +gsk_vulkan_texture_op_size (void) +{ + return GSK_VULKAN_TEXTURE_OP_CLASS.size; +} + +void +gsk_vulkan_texture_op_init (GskVulkanOp *op, + GskVulkanPipeline *pipeline, + GskVulkanImage *image, + GskVulkanRenderSampler sampler, + const graphene_rect_t *rect, + const graphene_point_t *offset, + const graphene_rect_t *tex_rect) +{ + GskVulkanTextureOp *self = (GskVulkanTextureOp *) op; + + gsk_vulkan_op_init (op, &GSK_VULKAN_TEXTURE_OP_CLASS); + + self->pipeline = pipeline; + self->image = g_object_ref (image); + self->sampler = sampler; + graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect); + self->tex_rect = *tex_rect; +} diff --git a/gsk/vulkan/gskvulkantextureopprivate.h b/gsk/vulkan/gskvulkantextureopprivate.h new file mode 100644 index 0000000000..eb8e9f283f --- /dev/null +++ b/gsk/vulkan/gskvulkantextureopprivate.h @@ -0,0 +1,19 @@ +#pragma once + +#include "gskvulkanopprivate.h" + +G_BEGIN_DECLS + +gsize gsk_vulkan_texture_op_size (void) G_GNUC_CONST; + +void gsk_vulkan_texture_op_init (GskVulkanOp *op, + GskVulkanPipeline *pipeline, + GskVulkanImage *image, + GskVulkanRenderSampler sampler, + const graphene_rect_t *rect, + const graphene_point_t *offset, + const graphene_rect_t *tex_rect); + + +G_END_DECLS + diff --git a/gsk/vulkan/gskvulkanuploadop.c b/gsk/vulkan/gskvulkanuploadop.c new file mode 100644 index 0000000000..ae912c8d38 --- /dev/null +++ b/gsk/vulkan/gskvulkanuploadop.c @@ -0,0 +1,111 @@ +#include "config.h" + +#include "gskvulkanuploadopprivate.h" + +typedef struct _GskVulkanUploadOp GskVulkanUploadOp; + +struct _GskVulkanUploadOp +{ + GskVulkanOp op; + + GskVulkanImage *image; + GdkTexture *texture; +}; + +static void +gsk_vulkan_upload_op_finish (GskVulkanOp *op) +{ + GskVulkanUploadOp *self = (GskVulkanUploadOp *) op; + + g_object_unref (self->image); + g_object_unref (self->texture); +} + +static void +gsk_vulkan_upload_op_upload (GskVulkanOp *op, + GskVulkanRenderPass *pass, + GskVulkanRender *render, + GskVulkanUploader *uploader, + const graphene_rect_t *clip, + const graphene_vec2_t *scale) +{ + GskVulkanUploadOp *self = (GskVulkanUploadOp *) op; + GdkTextureDownloader *downloader; + GskVulkanImageMap map; + + downloader = gdk_texture_downloader_new (self->texture); + gdk_texture_downloader_set_format (downloader, gsk_vulkan_image_get_format (self->image)); + gsk_vulkan_image_map_memory (self->image, uploader, GSK_VULKAN_WRITE, &map); + gdk_texture_downloader_download_into (downloader, map.data, map.stride); + gsk_vulkan_image_unmap_memory (self->image, uploader, &map); + gdk_texture_downloader_free (downloader); +} + +static gsize +gsk_vulkan_upload_op_count_vertex_data (GskVulkanOp *op, + gsize n_bytes) +{ + return n_bytes; +} + +static void +gsk_vulkan_upload_op_collect_vertex_data (GskVulkanOp *op, + GskVulkanRenderPass *pass, + GskVulkanRender *render, + guchar *data) +{ +} + +static void +gsk_vulkan_upload_op_reserve_descriptor_sets (GskVulkanOp *op, + GskVulkanRender *render) +{ +} + +static GskVulkanPipeline * +gsk_vulkan_upload_op_get_pipeline (GskVulkanOp *op) +{ + return NULL; +} + +static void +gsk_vulkan_upload_op_command (GskVulkanOp *op, + VkPipelineLayout pipeline_layout, + VkCommandBuffer command_buffer) +{ +} + +static const GskVulkanOpClass GSK_VULKAN_UPLOAD_OP_CLASS = { + GSK_VULKAN_OP_SIZE (GskVulkanUploadOp), + gsk_vulkan_upload_op_finish, + gsk_vulkan_upload_op_upload, + gsk_vulkan_upload_op_count_vertex_data, + gsk_vulkan_upload_op_collect_vertex_data, + gsk_vulkan_upload_op_reserve_descriptor_sets, + gsk_vulkan_upload_op_get_pipeline, + gsk_vulkan_upload_op_command +}; + +gsize +gsk_vulkan_upload_op_size (void) +{ + return GSK_VULKAN_UPLOAD_OP_CLASS.size; +} + +GskVulkanImage * +gsk_vulkan_upload_op_init_texture (GskVulkanOp *op, + GdkVulkanContext *context, + GdkTexture *texture) +{ + GskVulkanUploadOp *self = (GskVulkanUploadOp *) op; + + gsk_vulkan_op_init (op, &GSK_VULKAN_UPLOAD_OP_CLASS); + + self->texture = g_object_ref (texture); + self->image = gsk_vulkan_image_new_for_upload (context, + gdk_texture_get_format (texture), + gdk_texture_get_width (texture), + gdk_texture_get_height (texture)); + + return self->image; +} diff --git a/gsk/vulkan/gskvulkanuploadopprivate.h b/gsk/vulkan/gskvulkanuploadopprivate.h new file mode 100644 index 0000000000..4e72bc62ea --- /dev/null +++ b/gsk/vulkan/gskvulkanuploadopprivate.h @@ -0,0 +1,15 @@ +#pragma once + +#include "gskvulkanopprivate.h" + +G_BEGIN_DECLS + +gsize gsk_vulkan_upload_op_size (void) G_GNUC_CONST; + +GskVulkanImage * gsk_vulkan_upload_op_init_texture (GskVulkanOp *op, + GdkVulkanContext *context, + GdkTexture *texture); + + +G_END_DECLS +