gpu: Add float array to shaders and add an ubershader

... and use it for a naive color node implementation using both
so I can test it actually works.
This commit is contained in:
Benjamin Otte
2023-08-30 21:57:41 +02:00
parent 9df265acdc
commit c6e19f0384
21 changed files with 504 additions and 8 deletions

View File

@@ -90,3 +90,10 @@ gsk_gl_buffer_bind (GskGLBuffer *self)
glBindBuffer (self->target, self->buffer_id);
}
void
gsk_gl_buffer_bind_base (GskGLBuffer *self,
GLuint index)
{
glBindBufferBase (self->target, index, self->buffer_id);
}

View File

@@ -15,6 +15,8 @@ GskGpuBuffer * gsk_gl_buffer_new (GLenum
GLenum access);
void gsk_gl_buffer_bind (GskGLBuffer *self);
void gsk_gl_buffer_bind_base (GskGLBuffer *self,
GLuint index);
G_END_DECLS

View File

@@ -69,9 +69,17 @@ gsk_gl_frame_create_vertex_buffer (GskGpuFrame *frame,
return gsk_gl_buffer_new (GL_ARRAY_BUFFER, size, GL_WRITE_ONLY);
}
static GskGpuBuffer *
gsk_gl_frame_create_storage_buffer (GskGpuFrame *frame,
gsize size)
{
return gsk_gl_buffer_new (GL_UNIFORM_BUFFER, size, GL_WRITE_ONLY);
}
static void
gsk_gl_frame_submit (GskGpuFrame *frame,
GskGpuBuffer *vertex_buffer,
GskGpuBuffer *storage_buffer,
GskGpuOp *op)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
@@ -86,7 +94,12 @@ gsk_gl_frame_submit (GskGpuFrame *frame,
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation (GL_FUNC_ADD);
gsk_gl_buffer_bind (GSK_GL_BUFFER (vertex_buffer));
if (vertex_buffer)
gsk_gl_buffer_bind (GSK_GL_BUFFER (vertex_buffer));
if (storage_buffer)
gsk_gl_buffer_bind_base (GSK_GL_BUFFER (storage_buffer), 1);
/* The globals buffer must be the last bound buffer,
* the globsals op relies on that. */
glBindBufferBase (GL_UNIFORM_BUFFER, 0, self->globals_buffer_id);
glBufferData (GL_UNIFORM_BUFFER,
sizeof (GskGpuGlobalsInstance),
@@ -121,6 +134,7 @@ gsk_gl_frame_class_init (GskGLFrameClass *klass)
gpu_frame_class->cleanup = gsk_gl_frame_cleanup;
gpu_frame_class->get_image_descriptor = gsk_gl_frame_get_image_descriptor;
gpu_frame_class->create_vertex_buffer = gsk_gl_frame_create_vertex_buffer;
gpu_frame_class->create_storage_buffer = gsk_gl_frame_create_storage_buffer;
gpu_frame_class->submit = gsk_gl_frame_submit;
object_class->finalize = gsk_gl_frame_finalize;

View File

@@ -0,0 +1,68 @@
#include "config.h"
#include "gskgpubufferwriterprivate.h"
#include <string.h>
gsize
gsk_gpu_buffer_writer_commit (GskGpuBufferWriter *self)
{
return self->finish (self, TRUE);
}
void
gsk_gpu_buffer_writer_abort (GskGpuBufferWriter *self)
{
self->finish (self, FALSE);
}
void
gsk_gpu_buffer_writer_ensure_size (GskGpuBufferWriter *self,
gsize size)
{
if (size <= self->allocated)
return;
self->ensure_size (self, size);
}
static inline gsize
round_up (gsize number, gsize divisor)
{
return (number + divisor - 1) / divisor * divisor;
}
void
gsk_gpu_buffer_writer_append (GskGpuBufferWriter *self,
gsize align,
const guchar *data,
gsize size)
{
gsize aligned_size = round_up (self->size, align);
gsk_gpu_buffer_writer_ensure_size (self, aligned_size + size);
memcpy (self->data + aligned_size, data, size);
self->size = aligned_size + size;
}
void
gsk_gpu_buffer_writer_append_float (GskGpuBufferWriter *self,
float f)
{
gsk_gpu_buffer_writer_append (self, G_ALIGNOF (float), (guchar *) &f, sizeof (float));
}
void
gsk_gpu_buffer_writer_append_int (GskGpuBufferWriter *self,
gint32 i)
{
gsk_gpu_buffer_writer_append (self, G_ALIGNOF (gint32), (guchar *) &i, sizeof (gint32));
}
void
gsk_gpu_buffer_writer_append_uint (GskGpuBufferWriter *self,
guint32 u)
{
gsk_gpu_buffer_writer_append (self, G_ALIGNOF (guint32), (guchar *) &u, sizeof (guint32));
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include "gskgputypesprivate.h"
G_BEGIN_DECLS
typedef struct _GskGpuBufferWriter GskGpuBufferWriter;
struct _GskGpuBufferWriter
{
gpointer user_data;
void (* ensure_size) (GskGpuBufferWriter *self,
gsize size);
gsize (* finish) (GskGpuBufferWriter *self,
gboolean commit);
guchar *data;
gsize size;
gsize allocated;
};
gsize gsk_gpu_buffer_writer_commit (GskGpuBufferWriter *self);
void gsk_gpu_buffer_writer_abort (GskGpuBufferWriter *self);
void gsk_gpu_buffer_writer_ensure_size (GskGpuBufferWriter *self,
gsize size);
void gsk_gpu_buffer_writer_append (GskGpuBufferWriter *self,
gsize align,
const guchar *data,
gsize size);
void gsk_gpu_buffer_writer_append_float (GskGpuBufferWriter *self,
float f);
void gsk_gpu_buffer_writer_append_int (GskGpuBufferWriter *self,
gint32 i);
void gsk_gpu_buffer_writer_append_uint (GskGpuBufferWriter *self,
guint32 u);
G_END_DECLS

View File

@@ -71,4 +71,3 @@ gsk_gpu_device_create_upload_image (GskGpuDevice *self,
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_upload_image (self, format, width, height);
}

View File

@@ -16,6 +16,9 @@
#define DEFAULT_VERTEX_BUFFER_SIZE 128 * 1024
/* GL_MAX_UNIFORM_BLOCK_SIZE is at least this size */
#define DEFAULT_STORAGE_BUFFER_SIZE 16 * 1024
#define GDK_ARRAY_NAME gsk_gpu_ops
#define GDK_ARRAY_TYPE_NAME GskGpuOps
#define GDK_ARRAY_ELEMENT_TYPE guchar
@@ -35,6 +38,9 @@ struct _GskGpuFramePrivate
GskGpuBuffer *vertex_buffer;
guchar *vertex_buffer_data;
gsize vertex_buffer_used;
GskGpuBuffer *storage_buffer;
guchar *storage_buffer_data;
gsize storage_buffer_used;
};
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuFrame, gsk_gpu_frame, G_TYPE_OBJECT)
@@ -85,6 +91,7 @@ gsk_gpu_frame_finalize (GObject *object)
gsk_gpu_ops_clear (&priv->ops);
g_clear_object (&priv->vertex_buffer);
g_clear_object (&priv->storage_buffer);
g_object_unref (priv->device);
@@ -312,6 +319,13 @@ gsk_gpu_frame_create_vertex_buffer (GskGpuFrame *self,
return GSK_GPU_FRAME_GET_CLASS (self)->create_vertex_buffer (self, size);
}
static GskGpuBuffer *
gsk_gpu_frame_create_storage_buffer (GskGpuFrame *self,
gsize size)
{
return GSK_GPU_FRAME_GET_CLASS (self)->create_storage_buffer (self, size);
}
static inline gsize
round_up (gsize number, gsize divisor)
{
@@ -363,6 +377,20 @@ gsk_gpu_frame_get_vertex_data (GskGpuFrame *self,
return priv->vertex_buffer_data + offset;
}
static void
gsk_gpu_frame_ensure_storage_buffer (GskGpuFrame *self)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
if (priv->storage_buffer_data != NULL)
return;
if (priv->storage_buffer == NULL)
priv->storage_buffer = gsk_gpu_frame_create_storage_buffer (self, DEFAULT_STORAGE_BUFFER_SIZE);
priv->storage_buffer_data = gsk_gpu_buffer_map (priv->storage_buffer);
}
guint32
gsk_gpu_frame_get_image_descriptor (GskGpuFrame *self,
GskGpuImage *image,
@@ -371,6 +399,48 @@ gsk_gpu_frame_get_image_descriptor (GskGpuFrame *self,
return GSK_GPU_FRAME_GET_CLASS (self)->get_image_descriptor (self, image, sampler);
}
static void
gsk_gpu_frame_buffer_memory_ensure_size (GskGpuBufferWriter *writer,
gsize size)
{
/* FIXME: implement */
g_assert_not_reached ();
}
static gsize
gsk_gpu_frame_buffer_memory_finish (GskGpuBufferWriter *writer,
gboolean commit)
{
GskGpuFrame *self = GSK_GPU_FRAME (writer->user_data);
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
gsize offset;
if (!commit)
return 0;
offset = priv->storage_buffer_used;
priv->storage_buffer_used = writer->size;
return offset;
}
void
gsk_gpu_frame_write_buffer_memory (GskGpuFrame *self,
GskGpuBufferWriter *writer)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
gsk_gpu_frame_ensure_storage_buffer (self);
writer->user_data = self;
writer->ensure_size = gsk_gpu_frame_buffer_memory_ensure_size;
writer->finish = gsk_gpu_frame_buffer_memory_finish;
writer->data = priv->storage_buffer_data;
writer->size = priv->storage_buffer_used;
writer->allocated = gsk_gpu_buffer_get_size (priv->storage_buffer);
}
gboolean
gsk_gpu_frame_is_busy (GskGpuFrame *self)
{
@@ -445,8 +515,16 @@ gsk_gpu_frame_submit (GskGpuFrame *self)
priv->vertex_buffer_used = 0;
}
if (priv->storage_buffer_data)
{
gsk_gpu_buffer_unmap (priv->storage_buffer);
priv->storage_buffer_data = NULL;
priv->storage_buffer_used = 0;
}
GSK_GPU_FRAME_GET_CLASS (self)->submit (self,
priv->vertex_buffer,
priv->storage_buffer,
priv->first_op);
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "gskgpubufferwriterprivate.h"
#include "gskgpurenderer.h"
#include "gskgputypesprivate.h"
@@ -31,8 +32,11 @@ struct _GskGpuFrameClass
GskGpuSampler sampler);
GskGpuBuffer * (* create_vertex_buffer) (GskGpuFrame *self,
gsize size);
GskGpuBuffer * (* create_storage_buffer) (GskGpuFrame *self,
gsize size);
void (* submit) (GskGpuFrame *self,
GskGpuBuffer *vertex_buffer,
GskGpuBuffer *storage_buffer,
GskGpuOp *op);
};
@@ -55,6 +59,8 @@ guchar * gsk_gpu_frame_get_vertex_data (GskGpuF
guint32 gsk_gpu_frame_get_image_descriptor (GskGpuFrame *self,
GskGpuImage *image,
GskGpuSampler sampler);
void gsk_gpu_frame_write_buffer_memory (GskGpuFrame *self,
GskGpuBufferWriter *writer);
gboolean gsk_gpu_frame_is_busy (GskGpuFrame *self);

View File

@@ -6,6 +6,7 @@
#include "gskgpuframeprivate.h"
#include "gskgpuglobalsopprivate.h"
#include "gskgpuimageprivate.h"
#include "gskgpuuberopprivate.h"
#include "gskgpuscissoropprivate.h"
#include "gskgputextureopprivate.h"
#include "gskgpuuploadopprivate.h"
@@ -574,6 +575,34 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
self->pending_globals |= GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP;
}
static void
gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
GskRenderNode *node)
{
GskGpuBufferWriter writer;
const GdkRGBA *rgba;
guint32 pattern_id;
gsk_gpu_frame_write_buffer_memory (self->frame, &writer);
rgba = gsk_color_node_get_color (node);
#define GSK_GPU_PATTERN_COLOR 0
gsk_gpu_buffer_writer_append_uint (&writer, GSK_GPU_PATTERN_COLOR);
gsk_gpu_buffer_writer_append_float (&writer, rgba->red);
gsk_gpu_buffer_writer_append_float (&writer, rgba->green);
gsk_gpu_buffer_writer_append_float (&writer, rgba->blue);
gsk_gpu_buffer_writer_append_float (&writer, rgba->alpha);
pattern_id = gsk_gpu_buffer_writer_commit (&writer) / sizeof (float);
gsk_gpu_uber_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
&node->bounds,
&self->offset,
pattern_id);
}
static void
gsk_gpu_node_processor_add_container_node (GskGpuNodeProcessor *self,
GskRenderNode *node)
@@ -602,7 +631,7 @@ static const struct
},
[GSK_COLOR_NODE] = {
0,
NULL,
gsk_gpu_node_processor_add_color_node,
},
[GSK_LINEAR_GRADIENT_NODE] = {
0,

70
gsk/gpu/gskgpuuberop.c Normal file
View File

@@ -0,0 +1,70 @@
#include "config.h"
#include "gskgpuuberopprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuprintprivate.h"
#include "gskgpushaderopprivate.h"
#include "gskrectprivate.h"
#include "gpu/shaders/gskgpuuberinstance.h"
typedef struct _GskGpuUberOp GskGpuUberOp;
struct _GskGpuUberOp
{
GskGpuShaderOp op;
};
static void
gsk_gpu_uber_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuUberInstance *instance;
instance = (GskGpuUberInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "uber");
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_UBER_OP_CLASS = {
{
GSK_GPU_OP_SIZE (GskGpuUberOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_uber_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
gsk_gpu_shader_op_gl_command
},
"gskgpuuber",
sizeof (GskGpuUberInstance),
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_uber_info,
#endif
gsk_gpu_uber_setup_vao
};
void
gsk_gpu_uber_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const graphene_rect_t *rect,
const graphene_point_t *offset,
guint32 pattern_id)
{
GskGpuUberInstance *instance;
gsk_gpu_shader_op_alloc (frame,
&GSK_GPU_UBER_OP_CLASS,
clip,
&instance);
gsk_gpu_rect_to_float (rect, offset, instance->rect);
instance->pattern_id = pattern_id;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "gskgputypesprivate.h"
#include <graphene.h>
G_BEGIN_DECLS
void gsk_gpu_uber_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
const graphene_rect_t *rect,
const graphene_point_t *offset,
guint32 pattern_id);
G_END_DECLS

View File

@@ -161,6 +161,23 @@ gsk_vulkan_frame_get_image_descriptor (GskGpuFrame *frame,
return result;
}
static guint32
gsk_vulkan_frame_get_buffer_descriptor (GskVulkanFrame *self,
GskGpuBuffer *buffer)
{
guint32 result;
result = gsk_descriptor_buffer_infos_get_size (&self->descriptor_buffers);
gsk_descriptor_buffer_infos_append (&self->descriptor_buffers,
&(VkDescriptorBufferInfo) {
.buffer = gsk_vulkan_buffer_get_vk_buffer (GSK_VULKAN_BUFFER (buffer)),
.offset = 0,
.range = VK_WHOLE_SIZE
});
return result;
}
static void
gsk_vulkan_frame_prepare_descriptor_sets (GskVulkanFrame *self)
{
@@ -241,13 +258,28 @@ gsk_vulkan_frame_create_vertex_buffer (GskGpuFrame *frame,
return gsk_vulkan_buffer_new_vertex (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)), size);
}
static GskGpuBuffer *
gsk_vulkan_frame_create_storage_buffer (GskGpuFrame *frame,
gsize size)
{
return gsk_vulkan_buffer_new_storage (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)), size);
}
static void
gsk_vulkan_frame_submit (GskGpuFrame *frame,
GskGpuBuffer *vertex_buffer,
GskGpuBuffer *storage_buffer,
GskGpuOp *op)
{
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
if (storage_buffer)
{
G_GNUC_UNUSED guint32 descriptor;
descriptor = gsk_vulkan_frame_get_buffer_descriptor (self, storage_buffer);
g_assert (descriptor == 0);
}
GSK_VK_CHECK (vkBeginCommandBuffer, self->vk_command_buffer,
&(VkCommandBufferBeginInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@@ -321,6 +353,7 @@ gsk_vulkan_frame_class_init (GskVulkanFrameClass *klass)
gpu_frame_class->cleanup = gsk_vulkan_frame_cleanup;
gpu_frame_class->get_image_descriptor = gsk_vulkan_frame_get_image_descriptor;
gpu_frame_class->create_vertex_buffer = gsk_vulkan_frame_create_vertex_buffer;
gpu_frame_class->create_storage_buffer = gsk_vulkan_frame_create_storage_buffer;
gpu_frame_class->submit = gsk_vulkan_frame_submit;
object_class->finalize = gsk_vulkan_frame_finalize;

View File

@@ -0,0 +1,16 @@
#ifndef _COLOR_
#define _COLOR_
vec4
color_premultiply (vec4 color)
{
return vec4 (color.rgb, 1.0) * color.a;
}
vec4
color_unpremultiply (vec4 color)
{
return color.a > 0.0 ? color / vec4 (color.aaa, 1.0) : color;
}
#endif /* _COLOR_ */

View File

@@ -14,6 +14,18 @@ uniform PushConstants
vec2 scale;
} push;
#if defined(GSK_GLES) && __VERSION__ < 310
layout(std140)
#else
layout(std140, binding = 1)
#endif
uniform Floats
{
vec4 really_just_floats[1024];
} floats;
uniform sampler2D textures[16];
#define GSK_VERTEX_INDEX gl_VertexID
@@ -28,8 +40,21 @@ uniform PushConstants
#define PASS(_loc) in
#define PASS_FLAT(_loc) flat in
uniform sampler2D textures[16];
float
gsk_get_float (int id)
{
return floats.really_just_floats[id >> 2][id & 3];
}
float
gsk_get_float (uint id)
{
return gsk_get_float (int (id));
}
#define gsk_get_texture(id) textures[id]
#define gsk_get_int(id) (floatBitsToInt(gsk_get_float(id)))
#define gsk_get_uint(id) (floatBitsToUint(gsk_get_float(id)))
#ifdef GSK_GLES
void

View File

@@ -33,10 +33,10 @@ layout(set = 1, binding = 0) readonly buffer FloatBuffers {
layout(location = 0) out vec4 out_color;
#define gsk_get_texture(id) textures[nonuniformEXT (id)]
#if 0
#define get_buffer(id) buffers[nonuniformEXT (id)]
#define get_float(id) get_buffer(0).floats[nonuniformEXT (id)]
#endif
#define gsk_get_buffer(id) buffers[nonuniformEXT (id)]
#define gsk_get_float(id) gsk_get_buffer(0).floats[id]
#define gsk_get_int(id) (floatBitsToInt(gsk_get_float(id)))
#define gsk_get_uint(id) (floatBitsToUint(gsk_get_float(id)))
void
gsk_set_output_color (vec4 color)

View File

@@ -13,6 +13,7 @@ void main_clip_rounded (void);
#include "common-gl.glsl"
#endif
#include "color.glsl"
#include "rect.glsl"
#include "roundedrect.glsl"

View File

@@ -5,4 +5,6 @@
#define GSK_GPU_SHADER_CLIP_RECT 1u
#define GSK_GPU_SHADER_CLIP_ROUNDED 2u
#define GSK_GPU_PATTERN_COLOR 0
#endif

View File

@@ -0,0 +1,41 @@
#include "common.glsl"
#include "pattern.glsl"
PASS(0) vec2 _pos;
PASS_FLAT(1) Rect _rect;
PASS_FLAT(2) uint _pattern_id;
#ifdef GSK_VERTEX_SHADER
IN(0) vec4 in_rect;
IN(1) uint in_pattern_id;
void
run (out vec2 pos)
{
Rect r = rect_from_gsk (in_rect);
pos = rect_get_position (r);
_pos = pos;
_rect = r;
_pattern_id = in_pattern_id;
}
#endif
#ifdef GSK_FRAGMENT_SHADER
void
run (out vec4 color,
out vec2 position)
{
color = pattern (_pattern_id, _pos);
color.a *= rect_coverage (_rect, _pos);
position = _pos;
}
#endif

View File

@@ -1,14 +1,17 @@
gsk_private_gpu_include_shaders = files([
'color.glsl',
'common.glsl',
'common-gl.glsl',
'common-vulkan.glsl',
'ellipse.glsl',
'enums.glsl',
'pattern.glsl',
'rect.glsl',
'roundedrect.glsl',
])
gsk_private_gpu_shaders = files([
'gskgpuuber.glsl',
'gskgputexture.glsl',
])

View File

@@ -0,0 +1,42 @@
#ifndef _PATTERN_
#define _PATTERN_
#include "common.glsl"
#ifdef GSK_FRAGMENT_SHADER
vec4
gsk_get_vec4 (uint id)
{
return vec4 (gsk_get_float (id),
gsk_get_float (id + 1),
gsk_get_float (id + 2),
gsk_get_float (id + 3));
}
vec4
color_pattern (uint pattern)
{
vec4 color = gsk_get_vec4 (pattern);
return color_premultiply (color);
}
vec4
pattern (uint pattern,
vec2 pos)
{
uint type = gsk_get_uint (pattern);
switch (type)
{
case GSK_GPU_PATTERN_COLOR:
return color_pattern (pattern + 1);
default:
return vec4 (1.0, 0.0, 0.8, 1.0); /* pink */
}
}
#endif
#endif

View File

@@ -73,6 +73,7 @@ gsk_private_sources = files([
'gpu/gskglimage.c',
'gpu/gskgpublitop.c',
'gpu/gskgpubuffer.c',
'gpu/gskgpubufferwriter.c',
'gpu/gskgpuclip.c',
'gpu/gskgpudownloadop.c',
'gpu/gskgpudevice.c',
@@ -87,6 +88,7 @@ gsk_private_sources = files([
'gpu/gskgpushaderop.c',
'gpu/gskgpuscissorop.c',
'gpu/gskgputextureop.c',
'gpu/gskgpuuberop.c',
'gpu/gskgpuuploadop.c',
'gpu/gsknglrenderer.c',
])