diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index ee5e0ab6c8..a878236238 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -109,6 +109,7 @@ static const GdkDebugKey gdk_gl_feature_keys[] = { { "half-float", GDK_GL_FEATURE_VERTEX_HALF_FLOAT, "GL_OES_vertex_half_float" }, { "sync", GDK_GL_FEATURE_SYNC, "GL_ARB_sync" }, { "base-instance", GDK_GL_FEATURE_BASE_INSTANCE, "GL_ARB_base_instance" }, + { "buffer-storage", GDK_GL_FEATURE_BUFFER_STORAGE, "GL_EXT_buffer_storage" }, }; typedef struct _GdkGLContextPrivate GdkGLContextPrivate; @@ -1703,6 +1704,11 @@ gdk_gl_context_check_features (GdkGLContext *context) epoxy_has_gl_extension ("GL_ARB_base_instance")) features |= GDK_GL_FEATURE_BASE_INSTANCE; + if (gdk_gl_context_check_version (context, "4.4", "9.9") || + epoxy_has_gl_extension ("GL_EXT_buffer_storage") || + epoxy_has_gl_extension ("GL_ARB_buffer_storage")) + features |= GDK_GL_FEATURE_BUFFER_STORAGE; + return features; } diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h index 87636970c7..db9b6bb5b2 100644 --- a/gdk/gdkglcontextprivate.h +++ b/gdk/gdkglcontextprivate.h @@ -33,6 +33,7 @@ typedef enum { GDK_GL_FEATURE_VERTEX_HALF_FLOAT = 1 << 2, GDK_GL_FEATURE_SYNC = 1 << 3, GDK_GL_FEATURE_BASE_INSTANCE = 1 << 4, + GDK_GL_FEATURE_BUFFER_STORAGE = 1 << 5, } GdkGLFeatures; typedef enum { diff --git a/gsk/gpu/gskglbuffer.c b/gsk/gpu/gskglbuffer.c index d0456a9233..461590dd4c 100644 --- a/gsk/gpu/gskglbuffer.c +++ b/gsk/gpu/gskglbuffer.c @@ -1,30 +1,25 @@ #include "config.h" -#include - #include "gskglbufferprivate.h" +/* {{{ GskGLBuffer */ + struct _GskGLBuffer { GskGpuBuffer parent_instance; GLenum target; GLuint buffer_id; - GLenum access; guchar *data; }; G_DEFINE_TYPE (GskGLBuffer, gsk_gl_buffer, GSK_TYPE_GPU_BUFFER) -static guint profiler_buffer_uploads_id; -static gint64 profiler_buffer_uploads; - static void gsk_gl_buffer_finalize (GObject *object) { GskGLBuffer *self = GSK_GL_BUFFER (object); - g_free (self->data); glDeleteBuffers (1, &self->buffer_id); G_OBJECT_CLASS (gsk_gl_buffer_parent_class)->finalize (object); @@ -42,16 +37,6 @@ static void gsk_gl_buffer_unmap (GskGpuBuffer *buffer, gsize used) { - GskGLBuffer *self = GSK_GL_BUFFER (buffer); - - if (used == 0) - return; - - gsk_gl_buffer_bind (self); - - profiler_buffer_uploads += used; - glBufferSubData (self->target, 0, used, self->data); - gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads); } static void @@ -64,8 +49,6 @@ gsk_gl_buffer_class_init (GskGLBufferClass *klass) buffer_class->unmap = gsk_gl_buffer_unmap; gobject_class->finalize = gsk_gl_buffer_finalize; - - profiler_buffer_uploads_id = gdk_profiler_define_int_counter ("ngl-buffer-uploads", "Number of bytes uploaded to GPU"); } static void @@ -73,28 +56,6 @@ gsk_gl_buffer_init (GskGLBuffer *self) { } -GskGpuBuffer * -gsk_gl_buffer_new (GLenum target, - gsize size, - GLenum access) -{ - GskGLBuffer *self; - - self = g_object_new (GSK_TYPE_GL_BUFFER, NULL); - - gsk_gpu_buffer_setup (GSK_GPU_BUFFER (self), size); - - self->target = target; - self->access = access; - - glGenBuffers (1, &self->buffer_id); - glBindBuffer (target, self->buffer_id); - glBufferData (target, size, NULL, GL_STATIC_DRAW); - self->data = malloc (size); - - return GSK_GPU_BUFFER (self); -} - void gsk_gl_buffer_bind (GskGLBuffer *self) { @@ -108,3 +69,140 @@ gsk_gl_buffer_bind_base (GskGLBuffer *self, glBindBufferBase (self->target, index, self->buffer_id); } +static void +gsk_gl_buffer_setup (GskGLBuffer *self, + GLenum target, + gsize size) +{ + gsk_gpu_buffer_setup (GSK_GPU_BUFFER (self), size); + + self->target = target; + + glGenBuffers (1, &self->buffer_id); +} + +/* }}} */ +/* {{{ GskGLMappedBuffer */ + +struct _GskGLMappedBuffer +{ + GskGLBuffer parent_instance; +}; + +G_DEFINE_TYPE (GskGLMappedBuffer, gsk_gl_mapped_buffer, GSK_TYPE_GL_BUFFER) + +static void +gsk_gl_mapped_buffer_finalize (GObject *object) +{ + GskGLBuffer *self = GSK_GL_BUFFER (object); + + gsk_gl_buffer_bind (self); + glUnmapBuffer (self->target); + + G_OBJECT_CLASS (gsk_gl_mapped_buffer_parent_class)->finalize (object); +} + +static void +gsk_gl_mapped_buffer_class_init (GskGLMappedBufferClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gsk_gl_mapped_buffer_finalize; +} + +static void +gsk_gl_mapped_buffer_init (GskGLMappedBuffer *self) +{ +} + +GskGpuBuffer * +gsk_gl_mapped_buffer_new (GLenum target, + gsize size) +{ + GskGLBuffer *self; + + self = g_object_new (GSK_TYPE_GL_MAPPED_BUFFER, NULL); + + gsk_gl_buffer_setup (self, target, size); + gsk_gl_buffer_bind (self); + + glBufferStorage (target, + size, + NULL, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + self->data = glMapBufferRange (target, + 0, + size, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + + return GSK_GPU_BUFFER (self); +} + +/* }}} */ +/* {{{ GskGLCopiedBuffer */ + +struct _GskGLCopiedBuffer +{ + GskGLBuffer parent_instance; +}; + +G_DEFINE_TYPE (GskGLCopiedBuffer, gsk_gl_copied_buffer, GSK_TYPE_GL_BUFFER) + +static void +gsk_gl_copied_buffer_finalize (GObject *object) +{ + GskGLBuffer *self = GSK_GL_BUFFER (object); + + g_free (self->data); + + G_OBJECT_CLASS (gsk_gl_copied_buffer_parent_class)->finalize (object); +} + +static void +gsk_gl_copied_buffer_unmap (GskGpuBuffer *buffer, + gsize used) +{ + GskGLBuffer *self = GSK_GL_BUFFER (buffer); + + if (used == 0) + return; + + gsk_gl_buffer_bind (self); + + glBufferSubData (self->target, 0, used, self->data); +} + +static void +gsk_gl_copied_buffer_class_init (GskGLCopiedBufferClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GskGpuBufferClass *buffer_class = GSK_GPU_BUFFER_CLASS (klass); + + gobject_class->finalize = gsk_gl_copied_buffer_finalize; + + buffer_class->unmap = gsk_gl_copied_buffer_unmap; +} + +static void +gsk_gl_copied_buffer_init (GskGLCopiedBuffer *self) +{ +} + +GskGpuBuffer * +gsk_gl_copied_buffer_new (GLenum target, + gsize size) +{ + GskGLBuffer *self; + + self = g_object_new (GSK_TYPE_GL_COPIED_BUFFER, NULL); + + gsk_gl_buffer_setup (self, target, size); + gsk_gl_buffer_bind (self); + + glBufferData (target, size, NULL, GL_STATIC_DRAW); + self->data = malloc (size); + + return GSK_GPU_BUFFER (self); +} + +/* }}} */ diff --git a/gsk/gpu/gskglbufferprivate.h b/gsk/gpu/gskglbufferprivate.h index b0cbfa43f0..359cfa0615 100644 --- a/gsk/gpu/gskglbufferprivate.h +++ b/gsk/gpu/gskglbufferprivate.h @@ -7,12 +7,17 @@ G_BEGIN_DECLS #define GSK_TYPE_GL_BUFFER (gsk_gl_buffer_get_type ()) +#define GSK_TYPE_GL_MAPPED_BUFFER (gsk_gl_mapped_buffer_get_type ()) +#define GSK_TYPE_GL_COPIED_BUFFER (gsk_gl_copied_buffer_get_type ()) G_DECLARE_FINAL_TYPE (GskGLBuffer, gsk_gl_buffer, GSK, GL_BUFFER, GskGpuBuffer) +G_DECLARE_FINAL_TYPE (GskGLMappedBuffer, gsk_gl_mapped_buffer, GSK, GL_MAPPED_BUFFER, GskGLBuffer) +G_DECLARE_FINAL_TYPE (GskGLCopiedBuffer, gsk_gl_copied_buffer, GSK, GL_COPIED_BUFFER, GskGLBuffer) -GskGpuBuffer * gsk_gl_buffer_new (GLenum target, - gsize size, - GLenum access); +GskGpuBuffer * gsk_gl_mapped_buffer_new (GLenum target, + gsize size); +GskGpuBuffer * gsk_gl_copied_buffer_new (GLenum target, + gsize size); void gsk_gl_buffer_bind (GskGLBuffer *self); void gsk_gl_buffer_bind_base (GskGLBuffer *self, diff --git a/gsk/gpu/gskglframe.c b/gsk/gpu/gskglframe.c index c9997f28d9..d7033609d1 100644 --- a/gsk/gpu/gskglframe.c +++ b/gsk/gpu/gskglframe.c @@ -147,14 +147,22 @@ gsk_gl_frame_create_vertex_buffer (GskGpuFrame *frame, */ g_hash_table_remove_all (self->vaos); - return gsk_gl_buffer_new (GL_ARRAY_BUFFER, size, GL_WRITE_ONLY); + 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_ARRAY_BUFFER, size); + else + return gsk_gl_copied_buffer_new (GL_ARRAY_BUFFER, size); } static GskGpuBuffer * gsk_gl_frame_create_storage_buffer (GskGpuFrame *frame, gsize size) { - return gsk_gl_buffer_new (GL_UNIFORM_BUFFER, size, GL_WRITE_ONLY); + 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 void diff --git a/gsk/gpu/gskgpubuffer.c b/gsk/gpu/gskgpubuffer.c index de143ff5a4..c640fed235 100644 --- a/gsk/gpu/gskgpubuffer.c +++ b/gsk/gpu/gskgpubuffer.c @@ -2,6 +2,8 @@ #include "gskgpubufferprivate.h" +#include + typedef struct _GskGpuBufferPrivate GskGpuBufferPrivate; struct _GskGpuBufferPrivate @@ -11,9 +13,13 @@ struct _GskGpuBufferPrivate G_DEFINE_TYPE_WITH_PRIVATE (GskGpuBuffer, gsk_gpu_buffer, G_TYPE_OBJECT) +static guint profiler_buffer_uploads_id; +static gint64 profiler_buffer_uploads; + static void gsk_gpu_buffer_class_init (GskGpuBufferClass *klass) { + profiler_buffer_uploads_id = gdk_profiler_define_int_counter ("ngl-buffer-uploads", "Number of bytes uploaded to GPU"); } static void @@ -29,7 +35,7 @@ gsk_gpu_buffer_setup (GskGpuBuffer *self, priv->size = size; } - + gsize gsk_gpu_buffer_get_size (GskGpuBuffer *self) { @@ -49,5 +55,8 @@ gsk_gpu_buffer_unmap (GskGpuBuffer *self, gsize size) { GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self, size); + + profiler_buffer_uploads += size; + gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads); } diff --git a/gsk/gpu/gskvulkanbuffer.c b/gsk/gpu/gskvulkanbuffer.c index 93dbba0b0f..7a5e79c76b 100644 --- a/gsk/gpu/gskvulkanbuffer.c +++ b/gsk/gpu/gskvulkanbuffer.c @@ -97,7 +97,8 @@ gsk_vulkan_buffer_new_internal (GskVulkanDevice *device, self->allocator = gsk_vulkan_device_find_allocator (device, requirements.memoryTypeBits, GSK_VULKAN_MEMORY_MAPPABLE, - GSK_VULKAN_MEMORY_MAPPABLE); + GSK_VULKAN_MEMORY_MAPPABLE | + VK_MEMORY_PROPERTY_HOST_CACHED_BIT); gsk_vulkan_alloc (self->allocator, requirements.size, requirements.alignment,