Merge branch 'wip/otte/for-vulkan' into 'main'

vulkan: Fancy gradients

See merge request GNOME/gtk!6073
This commit is contained in:
Benjamin Otte 2023-06-08 21:57:07 +00:00
commit 83efe2b66c
32 changed files with 375 additions and 215 deletions

View File

@ -64,6 +64,13 @@ gsk_vulkan_buffer_new (GdkVulkanContext *context,
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
}
GskVulkanBuffer *
gsk_vulkan_buffer_new_storage (GdkVulkanContext *context,
gsize size)
{
return gsk_vulkan_buffer_new_internal (context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
}
GskVulkanBuffer *
gsk_vulkan_buffer_new_staging (GdkVulkanContext *context,
gsize size)

View File

@ -8,6 +8,8 @@ typedef struct _GskVulkanBuffer GskVulkanBuffer;
GskVulkanBuffer * gsk_vulkan_buffer_new (GdkVulkanContext *context,
gsize size);
GskVulkanBuffer * gsk_vulkan_buffer_new_storage (GdkVulkanContext *context,
gsize size);
GskVulkanBuffer * gsk_vulkan_buffer_new_staging (GdkVulkanContext *context,
gsize size);
GskVulkanBuffer * gsk_vulkan_buffer_new_download (GdkVulkanContext *context,

View File

@ -15,9 +15,8 @@ struct _GskVulkanLinearGradientInstance
float start[2];
float end[2];
gint32 repeating;
gint32 offset;
gint32 stop_count;
float offsets[GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS];
float colors[GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS][4];
};
G_DEFINE_TYPE (GskVulkanLinearGradientPipeline, gsk_vulkan_linear_gradient_pipeline, GSK_TYPE_VULKAN_PIPELINE)
@ -61,67 +60,13 @@ gsk_vulkan_linear_gradient_pipeline_get_input_state_create_info (GskVulkanPipeli
.location = 4,
.binding = 0,
.format = VK_FORMAT_R32_SINT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, stop_count),
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, offset),
},
{
.location = 5,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, offsets),
},
{
.location = 6,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, offsets) + sizeof (float) * 4,
},
{
.location = 7,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[0]),
},
{
.location = 8,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[1]),
},
{
.location = 9,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[2]),
},
{
.location = 10,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[3]),
},
{
.location = 11,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[4]),
},
{
.location = 12,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[5]),
},
{
.location = 13,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[6]),
},
{
.location = 14,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[7]),
.format = VK_FORMAT_R32_SINT,
.offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, stop_count),
}
};
static const VkPipelineVertexInputStateCreateInfo info = {
@ -169,23 +114,17 @@ gsk_vulkan_linear_gradient_pipeline_new (GdkVulkanContext *context,
void
gsk_vulkan_linear_gradient_pipeline_collect_vertex_data (GskVulkanLinearGradientPipeline *pipeline,
guchar *data,
const graphene_point_t *offset,
const graphene_rect_t *rect,
const graphene_point_t *start,
const graphene_point_t *end,
gboolean repeating,
gsize n_stops,
const GskColorStop *stops)
guchar *data,
const graphene_point_t *offset,
const graphene_rect_t *rect,
const graphene_point_t *start,
const graphene_point_t *end,
gboolean repeating,
gsize gradient_offset,
gsize n_stops)
{
GskVulkanLinearGradientInstance *instance = (GskVulkanLinearGradientInstance *) data;
gsize i;
if (n_stops > GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS)
{
g_warning ("Only %u color stops supported.", GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS);
n_stops = GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS;
}
instance->rect[0] = rect->origin.x + offset->x;
instance->rect[1] = rect->origin.y + offset->y;
instance->rect[2] = rect->size.width;
@ -195,15 +134,8 @@ gsk_vulkan_linear_gradient_pipeline_collect_vertex_data (GskVulkanLinearGradient
instance->end[0] = end->x + offset->x;
instance->end[1] = end->y + offset->y;
instance->repeating = repeating;
instance->offset = gradient_offset;
instance->stop_count = n_stops;
for (i = 0; i < n_stops; i++)
{
instance->offsets[i] = stops[i].offset;
instance->colors[i][0] = stops[i].color.red;
instance->colors[i][1] = stops[i].color.green;
instance->colors[i][2] = stops[i].color.blue;
instance->colors[i][3] = stops[i].color.alpha;
}
}
gsize

View File

@ -28,8 +28,8 @@ void gsk_vulkan_linear_gradient_pipeline_collect_vertex_data
const graphene_point_t *start,
const graphene_point_t *end,
gboolean repeating,
gsize n_stops,
const GskColorStop *stops);
gsize gradient_offset,
gsize n_stops);
gsize gsk_vulkan_linear_gradient_pipeline_draw (GskVulkanLinearGradientPipeline*pipeline,
VkCommandBuffer command_buffer,
gsize offset,

View File

@ -33,6 +33,14 @@
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
#define GDK_ARRAY_NAME gsk_descriptor_buffer_infos
#define GDK_ARRAY_TYPE_NAME GskDescriptorBufferInfos
#define GDK_ARRAY_ELEMENT_TYPE VkDescriptorBufferInfo
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 1024
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
struct _GskVulkanRender
{
GskRenderer *renderer;
@ -52,6 +60,7 @@ struct _GskVulkanRender
GskDescriptorImageInfos descriptor_images;
GskDescriptorImageInfos descriptor_samplers;
GskDescriptorBufferInfos descriptor_buffers;
VkDescriptorPool descriptor_pool;
VkDescriptorSet descriptor_set;
GskVulkanPipeline *pipelines[GSK_VULKAN_N_PIPELINES];
@ -59,6 +68,9 @@ struct _GskVulkanRender
GskVulkanImage *target;
VkSampler samplers[3];
GskVulkanBuffer *storage_buffer;
guchar *storage_buffer_memory;
gsize storage_buffer_used;
GList *render_passes;
GSList *cleanup_images;
@ -122,6 +134,7 @@ gsk_vulkan_render_new (GskRenderer *renderer,
self->framebuffers = g_hash_table_new (g_direct_hash, g_direct_equal);
gsk_descriptor_image_infos_init (&self->descriptor_images);
gsk_descriptor_image_infos_init (&self->descriptor_samplers);
gsk_descriptor_buffer_infos_init (&self->descriptor_buffers);
device = gdk_vulkan_context_get_device (self->vulkan);
@ -139,8 +152,8 @@ gsk_vulkan_render_new (GskRenderer *renderer,
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
.maxSets = 1,
.poolSizeCount = 2,
.pPoolSizes = (VkDescriptorPoolSize[2]) {
.poolSizeCount = 3,
.pPoolSizes = (VkDescriptorPoolSize[3]) {
{
.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS
@ -148,6 +161,10 @@ gsk_vulkan_render_new (GskRenderer *renderer,
{
.type = VK_DESCRIPTOR_TYPE_SAMPLER,
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS
},
{
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS
}
}
},
@ -197,9 +214,9 @@ gsk_vulkan_render_new (GskRenderer *renderer,
GSK_VK_CHECK (vkCreateDescriptorSetLayout, device,
&(VkDescriptorSetLayoutCreateInfo) {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 2,
.bindingCount = 3,
.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
.pBindings = (VkDescriptorSetLayoutBinding[2]) {
.pBindings = (VkDescriptorSetLayoutBinding[3]) {
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
@ -211,12 +228,21 @@ gsk_vulkan_render_new (GskRenderer *renderer,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
}
},
{
.binding = 2,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
},
},
.pNext = &(VkDescriptorSetLayoutBindingFlagsCreateInfo) {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
.bindingCount = 2,
.pBindingFlags = (VkDescriptorBindingFlags[2]) {
.bindingCount = 3,
.pBindingFlags = (VkDescriptorBindingFlags[3]) {
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
| VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
| VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
| VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
| VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
@ -520,10 +546,81 @@ gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self,
return result;
}
static void
gsk_vulkan_render_ensure_storage_buffer (GskVulkanRender *self)
{
if (self->storage_buffer_memory != NULL)
return;
if (self->storage_buffer == NULL)
{
self->storage_buffer = gsk_vulkan_buffer_new_storage (self->vulkan,
/* random */
sizeof (float) * 1024 * 1024);
}
self->storage_buffer_memory = gsk_vulkan_buffer_map (self->storage_buffer);
if (gsk_vulkan_render_get_buffer_descriptor (self, self->storage_buffer) != 0)
{
g_assert_not_reached ();
}
}
gsize
gsk_vulkan_render_get_buffer_descriptor (GskVulkanRender *self,
GskVulkanBuffer *buffer)
{
gsize result;
gsk_vulkan_render_ensure_storage_buffer (self);
result = gsk_descriptor_buffer_infos_get_size (&self->descriptor_buffers);
gsk_descriptor_buffer_infos_append (&self->descriptor_buffers,
&(VkDescriptorBufferInfo) {
.buffer = gsk_vulkan_buffer_get_buffer (buffer),
.offset = 0,
.range = VK_WHOLE_SIZE
});
g_assert (result < DESCRIPTOR_POOL_MAXITEMS);
return result;
}
static inline gsize
round_up (gsize number, gsize divisor)
{
return (number + divisor - 1) / divisor * divisor;
}
guchar *
gsk_vulkan_render_get_buffer_memory (GskVulkanRender *self,
gsize size,
gsize alignment,
gsize *out_offset)
{
guchar *result;
g_assert (alignment >= sizeof (float));
gsk_vulkan_render_ensure_storage_buffer (self);
self->storage_buffer_used = round_up (self->storage_buffer_used, alignment);
result = self->storage_buffer_memory + self->storage_buffer_used;
*out_offset = self->storage_buffer_used / sizeof (float);
self->storage_buffer_used += size;
return result;
}
static void
gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
{
VkDevice device;
VkWriteDescriptorSet descriptor_sets[3];
gsize n_descriptor_sets;
GList *l;
device = gdk_vulkan_context_get_device (self->vulkan);
@ -535,9 +632,16 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
}
if (gsk_descriptor_image_infos_get_size (&self->descriptor_samplers) == 0 &&
gsk_descriptor_image_infos_get_size (&self->descriptor_images) == 0)
gsk_descriptor_image_infos_get_size (&self->descriptor_images) == 0 &&
gsk_descriptor_buffer_infos_get_size (&self->descriptor_buffers) == 0)
return;
if (self->storage_buffer_memory)
{
gsk_vulkan_buffer_unmap (self->storage_buffer);
self->storage_buffer_memory = NULL;
}
GSK_VK_CHECK (vkAllocateDescriptorSets, device,
&(VkDescriptorSetAllocateInfo) {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
@ -550,33 +654,53 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
.pDescriptorCounts = (uint32_t[1]) {
gsk_descriptor_image_infos_get_size (&self->descriptor_images)
+ gsk_descriptor_image_infos_get_size (&self->descriptor_samplers)
+ gsk_descriptor_buffer_infos_get_size (&self->descriptor_buffers)
}
}
},
&self->descriptor_set);
n_descriptor_sets = 0;
if (gsk_descriptor_image_infos_get_size (&self->descriptor_images) > 0)
{
descriptor_sets[n_descriptor_sets++] = (VkWriteDescriptorSet) {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = self->descriptor_set,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_images),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_images)
};
}
if (gsk_descriptor_image_infos_get_size (&self->descriptor_samplers) > 0)
{
descriptor_sets[n_descriptor_sets++] = (VkWriteDescriptorSet) {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = self->descriptor_set,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_samplers),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_samplers)
};
}
if (gsk_descriptor_buffer_infos_get_size (&self->descriptor_buffers) > 0)
{
descriptor_sets[n_descriptor_sets++] = (VkWriteDescriptorSet) {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = self->descriptor_set,
.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = gsk_descriptor_buffer_infos_get_size (&self->descriptor_buffers),
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = gsk_descriptor_buffer_infos_get_data (&self->descriptor_buffers)
};
}
vkUpdateDescriptorSets (device,
2,
(VkWriteDescriptorSet[2]) {
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = self->descriptor_set,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_images),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_images)
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = self->descriptor_set,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_samplers),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_samplers)
}
},
n_descriptor_sets,
descriptor_sets,
0, NULL);
}
@ -672,6 +796,7 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
0);
gsk_descriptor_image_infos_set_size (&self->descriptor_images, 0);
gsk_descriptor_image_infos_set_size (&self->descriptor_samplers, 0);
gsk_descriptor_buffer_infos_set_size (&self->descriptor_buffers, 0);
g_list_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
self->render_passes = NULL;
@ -727,6 +852,7 @@ gsk_vulkan_render_free (GskVulkanRender *self)
NULL);
gsk_descriptor_image_infos_clear (&self->descriptor_images);
gsk_descriptor_image_infos_clear (&self->descriptor_samplers);
gsk_descriptor_buffer_infos_clear (&self->descriptor_buffers);
vkDestroyDescriptorSetLayout (device,
self->descriptor_set_layout,

View File

@ -77,6 +77,7 @@ struct _GskVulkanOpRender
gsize vertex_offset; /* offset into vertex buffer */
guint32 image_descriptor[2]; /* index into descriptor for the (image, sampler) */
guint32 image_descriptor2[2]; /* index into descriptor for the 2nd image (if relevant) */
gsize buffer_offset; /* offset into buffer */
graphene_rect_t source_rect; /* area that source maps to */
graphene_rect_t source2_rect; /* area that source2 maps to */
};
@ -406,10 +407,10 @@ gsk_vulkan_render_pass_add_color_node (GskVulkanRenderPass *self,
}
static inline gboolean
gsk_vulkan_render_pass_add_repeating_linear_gradient_node (GskVulkanRenderPass *self,
GskVulkanRender *render,
const GskVulkanParseState *state,
GskRenderNode *node)
gsk_vulkan_render_pass_add_linear_gradient_node (GskVulkanRenderPass *self,
GskVulkanRender *render,
const GskVulkanParseState *state,
GskRenderNode *node)
{
GskVulkanPipelineType pipeline_type;
GskVulkanOp op = {
@ -418,11 +419,6 @@ gsk_vulkan_render_pass_add_repeating_linear_gradient_node (GskVulkanRenderPass
.render.offset = state->offset,
};
if (gsk_linear_gradient_node_get_n_color_stops (node) > GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS)
FALLBACK ("Linear gradient with %zu color stops, hardcoded limit is %u",
gsk_linear_gradient_node_get_n_color_stops (node),
GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS);
if (gsk_vulkan_clip_contains_rect (&state->clip, &state->offset, &node->bounds))
pipeline_type = GSK_VULKAN_PIPELINE_LINEAR_GRADIENT;
else if (state->clip.type == GSK_VULKAN_CLIP_RECT)
@ -1138,8 +1134,8 @@ static const GskVulkanRenderPassNodeFunc nodes_vtable[N_RENDER_NODES] = {
[GSK_CONTAINER_NODE] = gsk_vulkan_render_pass_add_container_node,
[GSK_CAIRO_NODE] = gsk_vulkan_render_pass_add_cairo_node,
[GSK_COLOR_NODE] = gsk_vulkan_render_pass_add_color_node,
[GSK_LINEAR_GRADIENT_NODE] = gsk_vulkan_render_pass_add_repeating_linear_gradient_node,
[GSK_REPEATING_LINEAR_GRADIENT_NODE] = gsk_vulkan_render_pass_add_repeating_linear_gradient_node,
[GSK_LINEAR_GRADIENT_NODE] = gsk_vulkan_render_pass_add_linear_gradient_node,
[GSK_REPEATING_LINEAR_GRADIENT_NODE] = gsk_vulkan_render_pass_add_linear_gradient_node,
[GSK_RADIAL_GRADIENT_NODE] = NULL,
[GSK_REPEATING_RADIAL_GRADIENT_NODE] = NULL,
[GSK_CONIC_GRADIENT_NODE] = NULL,
@ -1896,8 +1892,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
gsk_linear_gradient_node_get_start (op->render.node),
gsk_linear_gradient_node_get_end (op->render.node),
gsk_render_node_get_node_type (op->render.node) == GSK_REPEATING_LINEAR_GRADIENT_NODE,
gsk_linear_gradient_node_get_n_color_stops (op->render.node),
gsk_linear_gradient_node_get_color_stops (op->render.node, NULL));
op->render.buffer_offset,
gsk_linear_gradient_node_get_n_color_stops (op->render.node));
break;
case GSK_VULKAN_OP_OPACITY:
@ -2125,11 +2121,25 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
}
break;
case GSK_VULKAN_OP_LINEAR_GRADIENT:
{
gsize n_stops = gsk_linear_gradient_node_get_n_color_stops (op->render.node);
guchar *mem;
mem = gsk_vulkan_render_get_buffer_memory (render,
n_stops * sizeof (GskColorStop),
G_ALIGNOF (GskColorStop),
&op->render.buffer_offset);
memcpy (mem,
gsk_linear_gradient_node_get_color_stops (op->render.node, NULL),
n_stops * sizeof (GskColorStop));
}
break;
default:
g_assert_not_reached ();
case GSK_VULKAN_OP_COLOR:
case GSK_VULKAN_OP_LINEAR_GRADIENT:
case GSK_VULKAN_OP_BORDER:
case GSK_VULKAN_OP_INSET_SHADOW:
case GSK_VULKAN_OP_OUTSET_SHADOW:

View File

@ -86,6 +86,12 @@ gsize gsk_vulkan_render_get_sampler_descriptor (GskVulk
GskVulkanRenderSampler render_sampler);
gsize gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self,
GskVulkanImage *source);
gsize gsk_vulkan_render_get_buffer_descriptor (GskVulkanRender *self,
GskVulkanBuffer *buffer);
guchar * gsk_vulkan_render_get_buffer_memory (GskVulkanRender *self,
gsize size,
gsize alignment,
gsize *out_offset);
VkDescriptorSet gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self);
void gsk_vulkan_render_draw (GskVulkanRender *self);

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"

View File

@ -1,5 +1,5 @@
#version 420 core
#version 450
#include "clip.vert.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.frag.glsl"
#include "rounded-rect.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.vert.glsl"
#include "rounded-rect.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.vert.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"

View File

@ -1,6 +1,10 @@
layout(set = 0, binding = 0) uniform texture2D textures[50000];
layout(set = 0, binding = 1) uniform sampler samplers[50000];
layout(set = 0, binding = 2) readonly buffer FloatBuffers {
float floats[];
} buffers[50000];
#define get_sampler(id) sampler2D(textures[id.x], samplers[id.y])
#define get_buffer(id) buffers[id]
#define get_float(id) get_buffer(0).floats[id]

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.frag.glsl"
#include "rounded-rect.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.vert.glsl"

View File

@ -1,36 +1,128 @@
#version 420 core
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
struct ColorStop {
float offset;
vec4 color;
};
#include "rect.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in float inGradientPos;
layout(location = 2) in flat int inRepeating;
layout(location = 3) in flat int inStopCount;
layout(location = 4) in flat ColorStop inStops[8];
layout(location = 1) in flat Rect inRect;
layout(location = 2) in float inGradientPos;
layout(location = 3) in flat int inRepeating;
layout(location = 4) in flat int inStopOffset;
layout(location = 5) in flat int inStopCount;
layout(location = 0) out vec4 outColor;
layout(location = 0) out vec4 color;
float
get_offset (int i)
{
return get_float (inStopOffset + i * 5);
}
vec4
get_color (int i)
{
i = clamp (i, 0, inStopCount - 1);
return color = vec4 (get_float (inStopOffset + i * 5 + 1),
get_float (inStopOffset + i * 5 + 2),
get_float (inStopOffset + i * 5 + 3),
get_float (inStopOffset + i * 5 + 4));
}
vec4
get_color_for_range_unscaled (float start,
float end)
{
vec4 result = vec4 (0);
float offset;
int i;
for (i = 0; i < inStopCount; i++)
{
offset = get_offset (i);
if (offset >= start)
break;
}
if (i == inStopCount)
offset = 1;
float last_offset = i > 0 ? get_offset (i - 1) : 0;
vec4 last_color = get_color (i - 1);
vec4 color = get_color (i);
if (last_offset < start)
{
last_color = mix (last_color, color, (start - last_offset) / (offset - last_offset));
last_offset = start;
}
if (end <= start)
return last_color;
for (; i < inStopCount; i++)
{
offset = get_offset (i);
color = get_color (i);
if (offset >= end)
break;
result += 0.5 * (color + last_color) * (offset - last_offset);
last_offset = offset;
last_color = color;
}
if (i == inStopCount)
{
offset = 1;
color = get_color (i);
}
if (offset > end)
{
color = mix (last_color, color, (end - last_offset) / (offset - last_offset));
offset = end;
}
result += 0.5 * (color + last_color) * (offset - last_offset);
return result;
}
vec4
get_color_for_range (float start,
float end)
{
return get_color_for_range_unscaled (start, end) / (end - start);
}
void main()
{
float pos;
if (inRepeating != 0)
pos = fract (inGradientPos);
else
pos = clamp (inGradientPos, 0, 1);
vec4 c;
float pos_start, pos_end;
float dPos = 0.5 * abs (fwidth (inGradientPos));
vec4 color = inStops[0].color;
int n = clamp (inStopCount, 2, 8);
for (int i = 1; i < n; i++)
if (inRepeating != 0)
{
if (inStops[i].offset > inStops[i-1].offset)
color = mix (color, inStops[i].color, clamp((pos - inStops[i-1].offset) / (inStops[i].offset - inStops[i-1].offset), 0, 1));
pos_start = inGradientPos - dPos;
pos_end = inGradientPos + dPos;
if (floor (pos_end) > floor (pos_start))
{
float fract_end = fract(pos_end);
float fract_start = fract(pos_start);
float n = floor (pos_end) - floor (pos_start);
if (fract_end > fract_start + 0.01)
c = get_color_for_range_unscaled (fract_start, fract_end);
else if (fract_start > fract_end + 0.01)
c = -get_color_for_range_unscaled (fract_end, fract_start);
c += get_color_for_range_unscaled (0.0, 1.0) * n;
c /= pos_end - pos_start;
}
else
{
c = get_color_for_range (fract (pos_start), fract (pos_end));
}
}
//outColor = vec4(pos, pos, pos, 1.0);
outColor = clip (inPos, color);
else
{
pos_start = clamp (inGradientPos - dPos, 0, 1);
pos_end = clamp (inGradientPos + dPos, 0, 1);
c = get_color_for_range (pos_start, pos_end);
}
float alpha = c.a * rect_coverage (inRect, inPos);
color = clip_scaled (inPos, vec4(c.rgb, 1) * alpha);
}

View File

@ -1,6 +1,7 @@
#version 420 core
#version 450
#include "clip.vert.glsl"
#include "common.vert.glsl"
#include "rect.vert.glsl"
struct ColorStop {
float offset;
@ -11,62 +12,32 @@ layout(location = 0) in vec4 inRect;
layout(location = 1) in vec2 inStart;
layout(location = 2) in vec2 inEnd;
layout(location = 3) in int inRepeating;
layout(location = 4) in int inStopCount;
layout(location = 5) in vec4 inOffsets0;
layout(location = 6) in vec4 inOffsets1;
layout(location = 7) in vec4 inColors0;
layout(location = 8) in vec4 inColors1;
layout(location = 9) in vec4 inColors2;
layout(location = 10) in vec4 inColors3;
layout(location = 11) in vec4 inColors4;
layout(location = 12) in vec4 inColors5;
layout(location = 13) in vec4 inColors6;
layout(location = 14) in vec4 inColors7;
layout(location = 4) in int inStopOffset;
layout(location = 5) in int inStopCount;
layout(location = 0) out vec2 outPos;
layout(location = 1) out float outGradientPos;
layout(location = 2) out flat int outRepeating;
layout(location = 3) out flat int outStopCount;
layout(location = 4) out flat ColorStop outStops[8];
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0) };
layout(location = 1) out flat Rect outRect;
layout(location = 2) out float outGradientPos;
layout(location = 3) out flat int outRepeating;
layout(location = 4) out flat int outStopOffset;
layout(location = 5) out flat int outStopCount;
float
get_gradient_pos (vec2 pos)
{
pos = pos - inStart;
vec2 grad = inEnd - inStart;
pos = pos - inStart * push.scale;
vec2 grad = (inEnd - inStart) * push.scale;
return dot (pos, grad) / dot (grad, grad);
}
void main() {
vec4 rect = clip (inRect);
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
Rect r = rect_from_gsk (inRect);
vec2 pos = set_position_from_rect (r);
outPos = pos;
outRect = r;
outGradientPos = get_gradient_pos (pos);
outRepeating = inRepeating;
outStopOffset = inStopOffset;
outStopCount = inStopCount;
outStops[0].offset = inOffsets0[0];
outStops[0].color = inColors0 * vec4(inColors0.aaa, 1.0);
outStops[1].offset = inOffsets0[1];
outStops[1].color = inColors1 * vec4(inColors1.aaa, 1.0);
outStops[2].offset = inOffsets0[2];
outStops[2].color = inColors2 * vec4(inColors2.aaa, 1.0);
outStops[3].offset = inOffsets0[3];
outStops[3].color = inColors3 * vec4(inColors3.aaa, 1.0);
outStops[4].offset = inOffsets1[0];
outStops[4].color = inColors4 * vec4(inColors4.aaa, 1.0);
outStops[5].offset = inOffsets1[1];
outStops[5].color = inColors5 * vec4(inColors5.aaa, 1.0);
outStops[6].offset = inOffsets1[2];
outStops[6].color = inColors6 * vec4(inColors6.aaa, 1.0);
outStops[7].offset = inOffsets1[3];
outStops[7].color = inColors7 * vec4(inColors7.aaa, 1.0);
}

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.vert.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.frag.glsl"
#include "rounded-rect.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "clip.vert.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"

View File

@ -1,4 +1,4 @@
#version 420 core
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"

View File

@ -0,0 +1,9 @@
transform {
transform: scale(10);
child: repeating-linear-gradient {
bounds: 0 0 5 5;
start: 0 0;
end: 0 1;
stops: 0 white, 0.5 white, 0.5 black, 1 black;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

View File

@ -80,6 +80,7 @@ compare_render_tests = [
'repeat-empty-child-bounds',
'repeat-negative-coords',
'repeat-texture',
'repeating-gradient-scaled',
'scale-textures-negative-ngl',
'scale-up-down',
'scaled-cairo',