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:
@@ -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',
|
||||
|
||||
100
gsk/vulkan/gskvulkanconvertop.c
Normal file
100
gsk/vulkan/gskvulkanconvertop.c
Normal 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);
|
||||
}
|
||||
16
gsk/vulkan/gskvulkanconvertopprivate.h
Normal file
16
gsk/vulkan/gskvulkanconvertopprivate.h
Normal 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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
29
gsk/vulkan/resources/convert.frag
Normal file
29
gsk/vulkan/resources/convert.frag
Normal 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);
|
||||
}
|
||||
26
gsk/vulkan/resources/convert.vert
Normal file
26
gsk/vulkan/resources/convert.vert
Normal 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;
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user