vulkan: Add premultiply step to texture upload

When a GdkMemoryFormat is not supported natively and there's
postprocessing required, add a way to mark a VulkanImage as such via the
new postprocess flags.

Also allow texting such iamges only with new_for_upload() and detect
when that is the case and then run a postprocessing step that converts
that image to a suitable format.
This is done with a new "convert" shader/op.

This now supports all formats natively, no conversions happen on the CPU
anymore (unless the GPU is old).
This commit is contained in:
Benjamin Otte
2023-07-19 06:14:55 +02:00
parent 65224f4533
commit 4d9e7d30b0
10 changed files with 354 additions and 69 deletions

View File

@@ -116,6 +116,7 @@ if have_vulkan
'vulkan/gskvulkancolormatrixop.c',
'vulkan/gskvulkancolorop.c',
'vulkan/gskvulkancommandpool.c',
'vulkan/gskvulkanconvertop.c',
'vulkan/gskvulkancrossfadeop.c',
'vulkan/gskvulkandownloadop.c',
'vulkan/gskvulkanglyphcache.c',

View File

@@ -0,0 +1,100 @@
#include "config.h"
#include "gskvulkanconvertopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/convert.vert.h"
typedef struct _GskVulkanConvertOp GskVulkanConvertOp;
struct _GskVulkanConvertOp
{
GskVulkanShaderOp op;
graphene_rect_t rect;
graphene_rect_t tex_rect;
guint32 image_descriptor;
};
static void
gsk_vulkan_convert_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanConvertOp *self = (GskVulkanConvertOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append (string, "convert ");
print_image (string, shader->images[0]);
print_newline (string);
}
static void
gsk_vulkan_convert_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanConvertOp *self = (GskVulkanConvertOp *) op;
GskVulkanConvertInstance *instance = (GskVulkanConvertInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
instance->rect[0] = self->rect.origin.x;
instance->rect[1] = self->rect.origin.y;
instance->rect[2] = self->rect.size.width;
instance->rect[3] = self->rect.size.height;
instance->tex_rect[0] = self->tex_rect.origin.x;
instance->tex_rect[1] = self->tex_rect.origin.y;
instance->tex_rect[2] = self->tex_rect.size.width;
instance->tex_rect[3] = self->tex_rect.size.height;
instance->tex_id = self->image_descriptor;
instance->postprocess = gsk_vulkan_image_get_postprocess (shader->images[0]);
}
static void
gsk_vulkan_convert_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanConvertOp *self = (GskVulkanConvertOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render, shader->images[0], GSK_VULKAN_SAMPLER_NEAREST);
}
static const GskVulkanShaderOpClass GSK_VULKAN_CONVERT_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanConvertOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_convert_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_convert_op_collect_vertex_data,
gsk_vulkan_convert_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"convert",
1,
&gsk_vulkan_convert_info,
};
void
gsk_vulkan_convert_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect)
{
GskVulkanConvertOp *self;
self = (GskVulkanConvertOp *) gsk_vulkan_shader_op_alloc (render,
&GSK_VULKAN_CONVERT_OP_CLASS,
clip,
&image);
graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect);
gsk_vulkan_normalize_tex_coords (&self->tex_rect, rect, tex_rect);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_convert_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect);
G_END_DECLS

View File

@@ -24,6 +24,7 @@ struct _GskVulkanImage
VkImage vk_image;
VkImageView vk_image_view;
VkFramebuffer vk_framebuffer;
GskVulkanImagePostprocess postprocess;
VkPipelineStageFlags vk_pipeline_stage;
VkImageLayout vk_image_layout;
@@ -40,6 +41,7 @@ struct _GskMemoryFormatInfo
{
VkFormat format;
VkComponentMapping components;
GskVulkanImagePostprocess postprocess;
};
static const GskMemoryFormatInfo *
@@ -52,8 +54,8 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_B8G8R8A8_UNORM, DEFAULT_SWIZZLE },
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(B, G, R, A) },
{ VK_FORMAT_B8G8R8A8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(B, G, R, A), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -62,7 +64,7 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(G, B, A, R) },
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(G, B, A, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -71,23 +73,53 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, DEFAULT_SWIZZLE },
{ VK_FORMAT_R8G8B8A8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
#if 0
GDK_MEMORY_B8G8R8A8,
GDK_MEMORY_A8R8G8B8,
GDK_MEMORY_R8G8B8A8,
GDK_MEMORY_A8B8G8R8,
#endif
case GDK_MEMORY_B8G8R8A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_B8G8R8A8_UNORM, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(B, G, R, A), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A8R8G8B8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(G, B, A, R), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R8G8B8A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A8B8G8R8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(A, B, G, R), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R8G8B8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8_UNORM, DEFAULT_SWIZZLE },
{ VK_FORMAT_R8G8B8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -96,8 +128,8 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_B8G8R8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_B8G8R8_UNORM, DEFAULT_SWIZZLE },
{ VK_FORMAT_R8G8B8_UNORM, SWIZZLE(B, G, R, A) },
{ VK_FORMAT_B8G8R8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_R8G8B8_UNORM, SWIZZLE(B, G, R, A), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -106,7 +138,7 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_R16G16B16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16_UNORM, DEFAULT_SWIZZLE },
{ VK_FORMAT_R16G16B16_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -115,20 +147,25 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_UNORM, DEFAULT_SWIZZLE },
{ VK_FORMAT_R16G16B16A16_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
#if 0
GDK_MEMORY_R16G16B16A16,
#endif
case GDK_MEMORY_R16G16B16A16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_UNORM, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R16G16B16_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16_SFLOAT, DEFAULT_SWIZZLE },
{ VK_FORMAT_R16G16B16_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -137,20 +174,25 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_SFLOAT, DEFAULT_SWIZZLE },
{ VK_FORMAT_R16G16B16A16_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
#if 0
GDK_MEMORY_R16G16B16A16_FLOAT,
#endif
case GDK_MEMORY_R16G16B16A16_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_SFLOAT, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R32G32B32_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R32G32B32_SFLOAT, DEFAULT_SWIZZLE },
{ VK_FORMAT_R32G32B32_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -159,33 +201,43 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R32G32B32A32_SFLOAT, DEFAULT_SWIZZLE },
{ VK_FORMAT_R32G32B32A32_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
#if 0
GDK_MEMORY_R32G32B32A32_FLOAT,
#endif
case GDK_MEMORY_R32G32B32A32_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R32G32B32A32_SFLOAT, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G8A8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8_UNORM, SWIZZLE (R, R, R, G) },
{ VK_FORMAT_R8G8_UNORM, SWIZZLE (R, R, R, G), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
#if 0
GDK_MEMORY_G8A8,
#endif
case GDK_MEMORY_G8A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8_UNORM, SWIZZLE (R, R, R, G), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, ONE) },
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, ONE), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -194,20 +246,25 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_G16A16_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16_UNORM, SWIZZLE (R, R, R, G) },
{ VK_FORMAT_R16G16_UNORM, SWIZZLE (R, R, R, G), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
#if 0
GDK_MEMORY_G16A16
#endif
case GDK_MEMORY_G16A16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16_UNORM, SWIZZLE (R, R, R, G), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, ONE) },
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, ONE), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -216,7 +273,7 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, R) },
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -225,23 +282,7 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
case GDK_MEMORY_A16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, R) },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
case GDK_MEMORY_R16G16B16A16:
case GDK_MEMORY_R16G16B16A16_FLOAT:
case GDK_MEMORY_R32G32B32A32_FLOAT:
case GDK_MEMORY_G8A8:
case GDK_MEMORY_G16A16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
@@ -361,16 +402,17 @@ gsk_vulkan_image_create_view (GskVulkanImage *self,
}
static GskVulkanImage *
gsk_vulkan_image_new (GdkVulkanContext *context,
GdkMemoryFormat format,
gsize width,
gsize height,
VkImageTiling tiling,
VkImageUsageFlags usage,
VkPipelineStageFlags stage,
VkImageLayout layout,
VkAccessFlags access,
VkMemoryPropertyFlags memory)
gsk_vulkan_image_new (GdkVulkanContext *context,
GdkMemoryFormat format,
gsize width,
gsize height,
GskVulkanImagePostprocess allowed_postprocess,
VkImageTiling tiling,
VkImageUsageFlags usage,
VkPipelineStageFlags stage,
VkImageLayout layout,
VkAccessFlags access,
VkMemoryPropertyFlags memory)
{
VkMemoryRequirements requirements;
GskVulkanImage *self;
@@ -384,6 +426,9 @@ gsk_vulkan_image_new (GdkVulkanContext *context,
vk_format->format != VK_FORMAT_UNDEFINED;
vk_format++)
{
if (vk_format->postprocess & ~allowed_postprocess)
continue;
if (gsk_vulkan_context_supports_format (context, vk_format->format))
break;
}
@@ -398,6 +443,7 @@ gsk_vulkan_image_new (GdkVulkanContext *context,
self->vulkan = g_object_ref (context);
self->format = format;
self->vk_format = vk_format->format;
self->postprocess = vk_format->postprocess;
self->width = width;
self->height = height;
self->vk_usage = usage;
@@ -454,6 +500,7 @@ gsk_vulkan_image_new_for_upload (GdkVulkanContext *context,
format,
width,
height,
-1,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT,
@@ -555,6 +602,7 @@ gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
GDK_MEMORY_DEFAULT,
width,
height,
0,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
@@ -577,6 +625,7 @@ gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
preferred_format,
width,
height,
0,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT |
@@ -663,6 +712,12 @@ gsk_vulkan_image_get_height (GskVulkanImage *self)
return self->height;
}
GskVulkanImagePostprocess
gsk_vulkan_image_get_postprocess (GskVulkanImage *self)
{
return self->postprocess;
}
VkImage
gsk_vulkan_image_get_vk_image (GskVulkanImage *self)
{

View File

@@ -8,6 +8,12 @@
G_BEGIN_DECLS
/* required postprocessing steps before the image van be used */
typedef enum
{
GSK_VULKAN_IMAGE_PREMULTIPLY = (1 << 0),
} GskVulkanImagePostprocess;
#define GSK_TYPE_VULKAN_IMAGE (gsk_vulkan_image_get_type ())
G_DECLARE_FINAL_TYPE (GskVulkanImage, gsk_vulkan_image, GSK, VULKAN_IMAGE, GObject)
@@ -48,6 +54,8 @@ void gsk_vulkan_image_unmap (GskVulk
gsize gsk_vulkan_image_get_width (GskVulkanImage *self);
gsize gsk_vulkan_image_get_height (GskVulkanImage *self);
GskVulkanImagePostprocess
gsk_vulkan_image_get_postprocess (GskVulkanImage *self);
VkPipelineStageFlags gsk_vulkan_image_get_vk_pipeline_stage (GskVulkanImage *self);
VkImageLayout gsk_vulkan_image_get_vk_image_layout (GskVulkanImage *self);
VkAccessFlags gsk_vulkan_image_get_vk_access (GskVulkanImage *self);

View File

@@ -16,6 +16,7 @@
#include "gskvulkanclipprivate.h"
#include "gskvulkancolormatrixopprivate.h"
#include "gskvulkancoloropprivate.h"
#include "gskvulkanconvertopprivate.h"
#include "gskvulkancrossfadeopprivate.h"
#include "gskvulkanglyphopprivate.h"
#include "gskvulkaninsetshadowopprivate.h"
@@ -140,6 +141,52 @@ gsk_vulkan_parse_rect_is_integer (const GskVulkanParseState *state,
&& int_rect->height == rect->size.height * scale_y;
}
static GskVulkanImage *
gsk_vulkan_render_pass_upload_texture (GskVulkanRender *render,
GdkTexture *texture)
{
GskVulkanImage *image, *better_image;
int width, height;
GskVulkanImagePostprocess postproc;
graphene_matrix_t projection;
graphene_vec2_t scale;
image = gsk_vulkan_upload_texture_op (render, texture);
postproc = gsk_vulkan_image_get_postprocess (image);
if (postproc == 0)
return image;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
better_image = gsk_vulkan_image_new_for_offscreen (gsk_vulkan_render_get_context (render),
gdk_texture_get_format (texture),
width, height);
gsk_vulkan_render_pass_begin_op (render,
g_object_ref (better_image),
&(cairo_rectangle_int_t) { 0, 0, width, height },
&GRAPHENE_SIZE_INIT(width, height),
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
gsk_vulkan_scissor_op (render, &(cairo_rectangle_int_t) { 0, 0, width, height });
graphene_matrix_init_ortho (&projection,
0, width,
0, height,
2 * ORTHO_NEAR_PLANE - ORTHO_FAR_PLANE,
ORTHO_FAR_PLANE);
graphene_vec2_init (&scale, 1.0, 1.0);
gsk_vulkan_push_constants_op (render, &scale, &projection, &GSK_ROUNDED_RECT_INIT(0, 0, width, height));
gsk_vulkan_convert_op (render,
GSK_VULKAN_SHADER_CLIP_NONE,
image,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_RECT_INIT (0, 0, width, height));
gsk_vulkan_render_pass_end_op (render,
better_image,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
return better_image;
}
static GskVulkanImage *
gsk_vulkan_render_pass_get_node_as_image (GskVulkanRenderPass *self,
GskVulkanRender *render,
@@ -158,7 +205,7 @@ gsk_vulkan_render_pass_get_node_as_image (GskVulkanRenderPass *self,
result = gsk_vulkan_renderer_get_texture_image (renderer, texture);
if (result == NULL)
{
result = gsk_vulkan_upload_texture_op (render, texture);
result = gsk_vulkan_render_pass_upload_texture (render, texture);
gsk_vulkan_renderer_add_texture_image (renderer, texture, result);
}
@@ -433,7 +480,7 @@ gsk_vulkan_render_pass_add_texture_node (GskVulkanRenderPass *self,
image = gsk_vulkan_renderer_get_texture_image (renderer, texture);
if (image == NULL)
{
image = gsk_vulkan_upload_texture_op (render, texture);
image = gsk_vulkan_render_pass_upload_texture (render, texture);
gsk_vulkan_renderer_add_texture_image (renderer, texture, image);
}
@@ -476,7 +523,7 @@ gsk_vulkan_render_pass_add_texture_scale_node (GskVulkanRenderPass *self,
image = gsk_vulkan_renderer_get_texture_image (renderer, texture);
if (image == NULL)
{
image = gsk_vulkan_upload_texture_op (render, texture);
image = gsk_vulkan_render_pass_upload_texture (render, texture);
gsk_vulkan_renderer_add_texture_image (renderer, texture, image);
}

View File

@@ -339,6 +339,7 @@ gsk_vulkan_upload_cairo_op (GskVulkanRender *render,
GDK_MEMORY_DEFAULT,
ceil (graphene_vec2_get_x (scale) * viewport->size.width),
ceil (graphene_vec2_get_y (scale) * viewport->size.height));
g_assert (gsk_vulkan_image_get_postprocess (self->image) == 0);
self->viewport = *viewport;
return self->image;

View File

@@ -0,0 +1,29 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
#include "rect.frag.glsl"
#define GSK_VULKAN_IMAGE_PREMULTIPLY (1 << 0)
#
layout(location = 0) in vec2 in_pos;
layout(location = 1) in Rect in_rect;
layout(location = 2) in vec2 in_tex_coord;
layout(location = 3) flat in uint in_tex_id;
layout(location = 4) in flat uint in_postprocess;
layout(location = 0) out vec4 color;
void main()
{
float alpha = rect_coverage (in_rect, in_pos);
/* warning: This breaks with filters other than nearest,
as linear filtering needs premultiplied alpha */
vec4 pixel = texture (get_sampler (in_tex_id), in_tex_coord);
if ((in_postprocess & GSK_VULKAN_IMAGE_PREMULTIPLY) != 0)
pixel.rgb *= pixel.a;
color = clip_scaled (in_pos, pixel * alpha);
}

View File

@@ -0,0 +1,26 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 in_rect;
layout(location = 1) in vec4 in_tex_rect;
layout(location = 2) in uint in_tex_id;
layout(location = 3) in uint in_postprocess;
layout(location = 0) out vec2 out_pos;
layout(location = 1) out flat Rect out_rect;
layout(location = 2) out vec2 out_tex_coord;
layout(location = 3) out flat uint out_tex_id;
layout(location = 4) out flat uint out_postprocess;
void main() {
Rect r = rect_from_gsk (in_rect);
vec2 pos = set_position_from_rect (r);
out_pos = pos;
out_rect = r;
out_tex_coord = scale_tex_coord (pos, r, in_tex_rect);
out_tex_id = in_tex_id;
out_postprocess = in_postprocess;
}

View File

@@ -17,6 +17,7 @@ gsk_private_vulkan_fragment_shaders = [
'border.frag',
'color.frag',
'color-matrix.frag',
'convert.frag',
'cross-fade.frag',
'glyph.frag',
'inset-shadow.frag',
@@ -32,6 +33,7 @@ gsk_private_vulkan_vertex_shaders = [
'border.vert',
'color.vert',
'color-matrix.vert',
'convert.vert',
'cross-fade.vert',
'glyph.vert',
'inset-shadow.vert',