Merge branch 'wip/otte/global-globals' into 'main'

ngl: Use a single buffer for globals

See merge request GNOME/gtk!7753
This commit is contained in:
Benjamin Otte
2024-09-30 17:09:52 +00:00
11 changed files with 120 additions and 36 deletions

View File

@@ -63,10 +63,16 @@ gsk_gl_buffer_bind (GskGLBuffer *self)
}
void
gsk_gl_buffer_bind_base (GskGLBuffer *self,
GLuint index)
gsk_gl_buffer_bind_range (GskGLBuffer *self,
GLuint index,
GLintptr offset,
GLsizeiptr size)
{
glBindBufferBase (self->target, index, self->buffer_id);
glBindBufferRange (self->target,
index,
self->buffer_id,
offset,
size);
}
static void

View File

@@ -20,8 +20,10 @@ GskGpuBuffer * gsk_gl_copied_buffer_new (GLenum
gsize size);
void gsk_gl_buffer_bind (GskGLBuffer *self);
void gsk_gl_buffer_bind_base (GskGLBuffer *self,
GLuint index);
void gsk_gl_buffer_bind_range (GskGLBuffer *self,
GLuint index,
GLintptr offset,
GLsizeiptr size);
G_END_DECLS

View File

@@ -17,7 +17,6 @@ struct _GskGLFrame
{
GskGpuFrame parent_instance;
GLuint globals_buffer_id;
guint next_texture_slot;
GLsync sync;
@@ -142,6 +141,17 @@ gsk_gl_frame_create_vertex_buffer (GskGpuFrame *frame,
return gsk_gl_copied_buffer_new (GL_ARRAY_BUFFER, size);
}
static GskGpuBuffer *
gsk_gl_frame_create_globals_buffer (GskGpuFrame *frame,
gsize size)
{
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_BUFFER_STORAGE))
return gsk_gl_mapped_buffer_new (GL_UNIFORM_BUFFER, size);
else
return gsk_gl_copied_buffer_new (GL_UNIFORM_BUFFER, size);
}
static GskGpuBuffer *
gsk_gl_frame_create_storage_buffer (GskGpuFrame *frame,
gsize size)
@@ -166,12 +176,14 @@ static void
gsk_gl_frame_submit (GskGpuFrame *frame,
GskRenderPassType pass_type,
GskGpuBuffer *vertex_buffer,
GskGpuBuffer *globals_buffer,
GskGpuOp *op)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
GskGLCommandState state = {
/* rest is 0 */
.current_samplers = { GSK_GPU_SAMPLER_N_SAMPLERS, GSK_GPU_SAMPLER_N_SAMPLERS }
.current_samplers = { GSK_GPU_SAMPLER_N_SAMPLERS, GSK_GPU_SAMPLER_N_SAMPLERS },
.globals = globals_buffer,
};
glEnable (GL_SCISSOR_TEST);
@@ -182,12 +194,6 @@ gsk_gl_frame_submit (GskGpuFrame *frame,
if (vertex_buffer)
gsk_gl_buffer_bind (GSK_GL_BUFFER (vertex_buffer));
gsk_gl_frame_bind_globals (self);
glBufferData (GL_UNIFORM_BUFFER,
sizeof (GskGpuGlobalsInstance),
NULL,
GL_STREAM_DRAW);
while (op)
{
op = gsk_gpu_op_gl_command (op, frame, &state);
@@ -202,8 +208,6 @@ gsk_gl_frame_finalize (GObject *object)
GskGLFrame *self = GSK_GL_FRAME (object);
g_hash_table_unref (self->vaos);
if (self->globals_buffer_id != 0)
glDeleteBuffers (1, &self->globals_buffer_id);
G_OBJECT_CLASS (gsk_gl_frame_parent_class)->finalize (object);
}
@@ -219,6 +223,7 @@ gsk_gl_frame_class_init (GskGLFrameClass *klass)
gpu_frame_class->cleanup = gsk_gl_frame_cleanup;
gpu_frame_class->upload_texture = gsk_gl_frame_upload_texture;
gpu_frame_class->create_vertex_buffer = gsk_gl_frame_create_vertex_buffer;
gpu_frame_class->create_globals_buffer = gsk_gl_frame_create_globals_buffer;
gpu_frame_class->create_storage_buffer = gsk_gl_frame_create_storage_buffer;
gpu_frame_class->write_texture_vertex_data = gsk_gl_frame_write_texture_vertex_data;
gpu_frame_class->submit = gsk_gl_frame_submit;
@@ -266,12 +271,3 @@ gsk_gl_frame_use_program (GskGLFrame *self,
g_hash_table_insert (self->vaos, (gpointer) op_class, GUINT_TO_POINTER (vao));
}
void
gsk_gl_frame_bind_globals (GskGLFrame *self)
{
if (self->globals_buffer_id == 0)
glGenBuffers (1, &self->globals_buffer_id);
glBindBufferBase (GL_UNIFORM_BUFFER, 0, self->globals_buffer_id);
}

View File

@@ -14,6 +14,4 @@ void gsk_gl_frame_use_program (GskGLFr
GskGpuColorStates color_states,
guint32 variation);
void gsk_gl_frame_bind_globals (GskGLFrame *self);
G_END_DECLS

View File

@@ -6,6 +6,7 @@
#include "gskgpucacheprivate.h"
#include "gskgpudeviceprivate.h"
#include "gskgpudownloadopprivate.h"
#include "gskgpuglobalsopprivate.h"
#include "gskgpuimageprivate.h"
#include "gskgpunodeprocessorprivate.h"
#include "gskgpuopprivate.h"
@@ -24,6 +25,8 @@
/* GL_MAX_UNIFORM_BLOCK_SIZE is at 16384 */
#define DEFAULT_STORAGE_BUFFER_SIZE 16 * 1024 * 64
#define DEFAULT_N_GLOBALS (16384 / sizeof (GskGpuGlobalsInstance))
#define GDK_ARRAY_NAME gsk_gpu_ops
#define GDK_ARRAY_TYPE_NAME GskGpuOps
#define GDK_ARRAY_ELEMENT_TYPE guchar
@@ -47,6 +50,9 @@ struct _GskGpuFramePrivate
GskGpuBuffer *vertex_buffer;
guchar *vertex_buffer_data;
gsize vertex_buffer_used;
GskGpuBuffer *globals_buffer;
GskGpuGlobalsInstance *globals_buffer_data;
gsize n_globals;
GskGpuBuffer *storage_buffer;
guchar *storage_buffer_data;
gsize storage_buffer_used;
@@ -66,6 +72,8 @@ gsk_gpu_frame_default_cleanup (GskGpuFrame *self)
GskGpuOp *op;
gsize i;
priv->n_globals = 0;
for (i = 0; i < gsk_gpu_ops_get_size (&priv->ops); i += op->op_class->size)
{
op = (GskGpuOp *) gsk_gpu_ops_index (&priv->ops, i);
@@ -139,6 +147,7 @@ gsk_gpu_frame_finalize (GObject *object)
gsk_gpu_ops_clear (&priv->ops);
g_clear_object (&priv->vertex_buffer);
g_clear_object (&priv->globals_buffer);
g_clear_object (&priv->storage_buffer);
g_object_unref (priv->device);
@@ -505,6 +514,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_globals_buffer (GskGpuFrame *self,
gsize size)
{
return GSK_GPU_FRAME_GET_CLASS (self)->create_globals_buffer (self, size);
}
static GskGpuBuffer *
gsk_gpu_frame_create_storage_buffer (GskGpuFrame *self,
gsize size)
@@ -560,6 +576,48 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
return size_needed - size;
}
gsize
gsk_gpu_frame_add_globals (GskGpuFrame *self,
const GskGpuGlobalsInstance *globals)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
gsize size_needed, result;
if (priv->globals_buffer == NULL)
{
priv->globals_buffer = gsk_gpu_frame_create_globals_buffer (self, sizeof (GskGpuGlobalsInstance) * DEFAULT_N_GLOBALS);
if (priv->globals_buffer == NULL)
return 0;
}
if (priv->globals_buffer_data == NULL)
priv->globals_buffer_data = (GskGpuGlobalsInstance *) gsk_gpu_buffer_map (priv->globals_buffer);
size_needed = sizeof (GskGpuGlobalsInstance) * (priv->n_globals + 1);
if (gsk_gpu_buffer_get_size (priv->globals_buffer) < size_needed)
{
gsize old_size = gsk_gpu_buffer_get_size (priv->globals_buffer);
GskGpuBuffer *new_buffer = gsk_gpu_frame_create_globals_buffer (self, old_size * 2);
GskGpuGlobalsInstance *new_data = (GskGpuGlobalsInstance *) gsk_gpu_buffer_map (new_buffer);
if (priv->globals_buffer_data)
{
memcpy (new_data, priv->globals_buffer_data, old_size);
gsk_gpu_buffer_unmap (priv->globals_buffer, old_size);
}
g_object_unref (priv->globals_buffer);
priv->globals_buffer = new_buffer;
priv->globals_buffer_data = new_data;
}
result = priv->n_globals;
priv->globals_buffer_data[priv->n_globals] = *globals;
priv->n_globals++;
return result;
}
guchar *
gsk_gpu_frame_get_vertex_data (GskGpuFrame *self,
gsize offset)
@@ -691,6 +749,12 @@ gsk_gpu_frame_submit (GskGpuFrame *self,
priv->vertex_buffer_used = 0;
}
if (priv->globals_buffer)
{
gsk_gpu_buffer_unmap (priv->globals_buffer, sizeof (GskGpuGlobalsInstance) * priv->n_globals);
priv->globals_buffer_data = NULL;
}
if (priv->storage_buffer_data)
{
gsk_gpu_buffer_unmap (priv->storage_buffer, priv->storage_buffer_used);
@@ -701,6 +765,7 @@ gsk_gpu_frame_submit (GskGpuFrame *self,
GSK_GPU_FRAME_GET_CLASS (self)->submit (self,
pass_type,
priv->vertex_buffer,
priv->globals_buffer,
priv->first_op);
}

View File

@@ -39,6 +39,8 @@ struct _GskGpuFrameClass
GdkTexture *texture);
GskGpuBuffer * (* create_vertex_buffer) (GskGpuFrame *self,
gsize size);
GskGpuBuffer * (* create_globals_buffer) (GskGpuFrame *self,
gsize size);
GskGpuBuffer * (* create_storage_buffer) (GskGpuFrame *self,
gsize size);
void (* write_texture_vertex_data) (GskGpuFrame *self,
@@ -49,6 +51,7 @@ struct _GskGpuFrameClass
void (* submit) (GskGpuFrame *self,
GskRenderPassType pass_type,
GskGpuBuffer *vertex_buffer,
GskGpuBuffer *globals_buffer,
GskGpuOp *op);
};
@@ -92,6 +95,8 @@ void gsk_gpu_frame_write_texture_vertex_data (GskGpuF
GskGpuImage **images,
GskGpuSampler *samplers,
gsize n_images);
gsize gsk_gpu_frame_add_globals (GskGpuFrame *self,
const GskGpuGlobalsInstance *globals);
GskGpuBuffer * gsk_gpu_frame_write_storage_buffer (GskGpuFrame *self,
const guchar *data,
gsize size,

View File

@@ -2,7 +2,7 @@
#include "gskgpuglobalsopprivate.h"
#include "gskglframeprivate.h"
#include "gskglbufferprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuprintprivate.h"
#include "gskroundedrectprivate.h"
@@ -17,6 +17,7 @@ struct _GskGpuGlobalsOp
{
GskGpuOp op;
gsize id;
GskGpuGlobalsInstance instance;
};
@@ -67,13 +68,10 @@ gsk_gpu_globals_op_gl_command (GskGpuOp *op,
{
GskGpuGlobalsOp *self = (GskGpuGlobalsOp *) op;
gsk_gl_frame_bind_globals (GSK_GL_FRAME (frame));
/* FIXME: Does it matter if we glBufferData() or glSubBufferData() here? */
glBufferSubData (GL_UNIFORM_BUFFER,
0,
sizeof (self->instance),
&self->instance);
gsk_gl_buffer_bind_range (GSK_GL_BUFFER (state->globals),
0,
self->id * sizeof (GskGpuGlobalsInstance),
sizeof (GskGpuGlobalsInstance));
return op->next;
}
@@ -102,4 +100,5 @@ gsk_gpu_globals_op (GskGpuFrame *frame,
graphene_matrix_to_float (mvp, self->instance.mvp);
gsk_rounded_rect_to_float (clip, graphene_point_zero (), self->instance.clip);
graphene_vec2_to_float (scale, self->instance.scale);
self->id = gsk_gpu_frame_add_globals (frame, &self->instance);
}

View File

@@ -7,15 +7,17 @@
G_BEGIN_DECLS
typedef struct _GskGpuGlobalsInstance GskGpuGlobalsInstance;
struct _GskGpuGlobalsInstance
{
float mvp[16];
float clip[12];
float scale[2];
float padding[2];
};
/* GPUs often want 32bit alignment */
G_STATIC_ASSERT (sizeof (GskGpuGlobalsInstance) % 32 == 0);
void gsk_gpu_globals_op (GskGpuFrame *frame,
const graphene_vec2_t *scale,
const graphene_matrix_t *mvp,

View File

@@ -29,6 +29,7 @@ struct _GskGLCommandState
GskGpuColorStates color_states;
guint32 variation;
} current_program;
GskGpuBuffer *globals;
GskGpuImage *current_images[2];
GskGpuSampler current_samplers[2];
};

View File

@@ -11,6 +11,7 @@ typedef struct _GskGpuClip GskGpuClip;
typedef guint32 GskGpuColorStates;
typedef struct _GskGpuDevice GskGpuDevice;
typedef struct _GskGpuFrame GskGpuFrame;
typedef struct _GskGpuGlobalsInstance GskGpuGlobalsInstance;
typedef struct _GskGpuImage GskGpuImage;
typedef struct _GskGpuOp GskGpuOp;
typedef struct _GskGpuOpClass GskGpuOpClass;

View File

@@ -229,6 +229,13 @@ 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_globals_buffer (GskGpuFrame *frame,
gsize size)
{
return NULL;
}
static GskGpuBuffer *
gsk_vulkan_frame_create_storage_buffer (GskGpuFrame *frame,
gsize size)
@@ -249,6 +256,7 @@ static void
gsk_vulkan_frame_submit (GskGpuFrame *frame,
GskRenderPassType pass_type,
GskGpuBuffer *vertex_buffer,
GskGpuBuffer *globals_buffer,
GskGpuOp *op)
{
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
@@ -351,6 +359,7 @@ gsk_vulkan_frame_class_init (GskVulkanFrameClass *klass)
gpu_frame_class->begin = gsk_vulkan_frame_begin;
gpu_frame_class->upload_texture = gsk_vulkan_frame_upload_texture;
gpu_frame_class->create_vertex_buffer = gsk_vulkan_frame_create_vertex_buffer;
gpu_frame_class->create_globals_buffer = gsk_vulkan_frame_create_globals_buffer;
gpu_frame_class->create_storage_buffer = gsk_vulkan_frame_create_storage_buffer;
gpu_frame_class->write_texture_vertex_data = gsk_vulkan_frame_write_texture_vertex_data;
gpu_frame_class->submit = gsk_vulkan_frame_submit;