diff --git a/gsk/gpu/gskglframe.c b/gsk/gpu/gskglframe.c index a5f2a84f6f..367e2e1ffa 100644 --- a/gsk/gpu/gskglframe.c +++ b/gsk/gpu/gskglframe.c @@ -4,6 +4,7 @@ #include "gskgpuglobalsopprivate.h" #include "gskgpuopprivate.h" +#include "gskgpushaderopprivate.h" #include "gskglbufferprivate.h" #include "gskgldeviceprivate.h" @@ -66,6 +67,13 @@ static GskGpuBuffer * gsk_gl_frame_create_vertex_buffer (GskGpuFrame *frame, gsize size) { + GskGLFrame *self = GSK_GL_FRAME (frame); + + /* We could also reassign them all to the new buffer here? + * Is that faster? + */ + g_hash_table_remove_all (self->vaos); + return gsk_gl_buffer_new (GL_ARRAY_BUFFER, size, GL_WRITE_ONLY); } @@ -166,11 +174,12 @@ gsk_gl_frame_use_program (GskGLFrame *self, vao = GPOINTER_TO_UINT (g_hash_table_lookup (self->vaos, op_class)); if (vao) { - glBindVertexArray(vao); + glBindVertexArray (vao); return; } - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + glGenVertexArrays (1, &vao); + glBindVertexArray (vao); + op_class->setup_vao (0); g_hash_table_insert (self->vaos, (gpointer) op_class, GUINT_TO_POINTER (vao)); } diff --git a/gsk/gpu/gskgpurenderer.c b/gsk/gpu/gskgpurenderer.c index ed7002e14a..8f41e435a4 100644 --- a/gsk/gpu/gskgpurenderer.c +++ b/gsk/gpu/gskgpurenderer.c @@ -24,6 +24,8 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = { { "uber", GSK_GPU_OPTIMIZE_UBER, "Don't use the uber shader" }, { "clear", GSK_GPU_OPTIMIZE_CLEAR, "Don't vkCmdClearAttachment()/glClear() instead of shaders" }, + + { "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" }, }; typedef struct _GskGpuRendererPrivate GskGpuRendererPrivate; @@ -32,6 +34,7 @@ struct _GskGpuRendererPrivate { GskGpuDevice *device; GdkDrawContext *context; + GskGpuOptimizations optimizations; GskGpuFrame *frames[GSK_GPU_MAX_FRAMES]; }; @@ -82,7 +85,7 @@ gsk_gpu_renderer_create_frame (GskGpuRenderer *self) result = g_object_new (klass->frame_type, NULL); - gsk_gpu_frame_setup (result, self, priv->device, klass->optimizations); + gsk_gpu_frame_setup (result, self, priv->device, priv->optimizations); return result; } @@ -118,6 +121,7 @@ gsk_gpu_renderer_realize (GskRenderer *renderer, { GskGpuRenderer *self = GSK_GPU_RENDERER (renderer); GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self); + GskGpuOptimizations context_optimizations; GdkDisplay *display; if (surface) @@ -129,13 +133,15 @@ gsk_gpu_renderer_realize (GskRenderer *renderer, if (priv->device == NULL) return FALSE; - priv->context = GSK_GPU_RENDERER_GET_CLASS (self)->create_context (self, display, surface, error); + priv->context = GSK_GPU_RENDERER_GET_CLASS (self)->create_context (self, display, surface, &context_optimizations, error); if (priv->context == NULL) { g_clear_object (&priv->device); return FALSE; } + priv->optimizations &= context_optimizations; + return TRUE; } @@ -286,6 +292,9 @@ gsk_gpu_renderer_class_init (GskGpuRendererClass *klass) static void gsk_gpu_renderer_init (GskGpuRenderer *self) { + GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self); + + priv->optimizations = GSK_GPU_RENDERER_GET_CLASS (self)->optimizations; } GdkDrawContext * diff --git a/gsk/gpu/gskgpurendererprivate.h b/gsk/gpu/gskgpurendererprivate.h index 8a408c6fac..8d2c73221a 100644 --- a/gsk/gpu/gskgpurendererprivate.h +++ b/gsk/gpu/gskgpurendererprivate.h @@ -23,13 +23,14 @@ struct _GskGpuRendererClass GskRendererClass parent_class; GType frame_type; - GskGpuOptimizations optimizations; + GskGpuOptimizations optimizations; /* subclasses cannot override this */ GskGpuDevice * (* get_device) (GdkDisplay *display, GError **error); GdkDrawContext * (* create_context) (GskGpuRenderer *self, GdkDisplay *display, GdkSurface *surface, + GskGpuOptimizations *supported, GError **error); void (* make_current) (GskGpuRenderer *self); diff --git a/gsk/gpu/gskgpushaderop.c b/gsk/gpu/gskgpushaderop.c index 7422ae36a7..f61ddd1edf 100644 --- a/gsk/gpu/gskgpushaderop.c +++ b/gsk/gpu/gskgpushaderop.c @@ -96,12 +96,23 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op, gsk_gl_device_get_sampler_id (device, images[i].sampler)); } - shader_op_class->setup_vao (self->vertex_offset); + if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE)) + { + glDrawArraysInstancedBaseInstance (GL_TRIANGLES, + 0, + 6 * instance_scale, + 1, + self->vertex_offset / shader_op_class->vertex_size); + } + else + { + shader_op_class->setup_vao (self->vertex_offset); - glDrawArraysInstanced (GL_TRIANGLES, - 0, - 6 * instance_scale, - 1); + glDrawArraysInstanced (GL_TRIANGLES, + 0, + 6 * instance_scale, + 1); + } return op->next; } diff --git a/gsk/gpu/gskgputypesprivate.h b/gsk/gpu/gskgputypesprivate.h index 0d83ed9bc4..d3e56d7650 100644 --- a/gsk/gpu/gskgputypesprivate.h +++ b/gsk/gpu/gskgputypesprivate.h @@ -57,5 +57,7 @@ typedef enum { typedef enum { GSK_GPU_OPTIMIZE_UBER = 1 << 0, GSK_GPU_OPTIMIZE_CLEAR = 1 << 1, + /* These require hardware support */ + GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 2, } GskGpuOptimizations; diff --git a/gsk/gpu/gsknglrenderer.c b/gsk/gpu/gsknglrenderer.c index 4319fc1061..a0b5478757 100644 --- a/gsk/gpu/gsknglrenderer.c +++ b/gsk/gpu/gsknglrenderer.c @@ -8,6 +8,8 @@ #include "gskglframeprivate.h" #include "gskglimageprivate.h" +#include "gdk/gdkglcontextprivate.h" + struct _GskNglRenderer { GskGpuRenderer parent_instance; @@ -23,10 +25,11 @@ struct _GskNglRendererClass G_DEFINE_TYPE (GskNglRenderer, gsk_ngl_renderer, GSK_TYPE_GPU_RENDERER) static GdkDrawContext * -gsk_ngl_renderer_create_context (GskGpuRenderer *renderer, - GdkDisplay *display, - GdkSurface *surface, - GError **error) +gsk_ngl_renderer_create_context (GskGpuRenderer *renderer, + GdkDisplay *display, + GdkSurface *surface, + GskGpuOptimizations *supported, + GError **error) { GdkGLContext *context; @@ -47,6 +50,14 @@ gsk_ngl_renderer_create_context (GskGpuRenderer *renderer, return NULL; } + gdk_gl_context_make_current (context); + + *supported = -1; + if (!gdk_gl_context_check_version (context, "4.2", "9.9") && + !epoxy_has_gl_extension ("GL_EXT_base_instance") && + !epoxy_has_gl_extension ("GL_ARB_base_instance")) + *supported &= ~GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE; + return GDK_DRAW_CONTEXT (context); } diff --git a/gsk/gpu/gskvulkanrenderer.c b/gsk/gpu/gskvulkanrenderer.c index afe33d2478..b3fdd1cb38 100644 --- a/gsk/gpu/gskvulkanrenderer.c +++ b/gsk/gpu/gskvulkanrenderer.c @@ -73,10 +73,11 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, } static GdkDrawContext * -gsk_vulkan_renderer_create_context (GskGpuRenderer *renderer, - GdkDisplay *display, - GdkSurface *surface, - GError **error) +gsk_vulkan_renderer_create_context (GskGpuRenderer *renderer, + GdkDisplay *display, + GdkSurface *surface, + GskGpuOptimizations *supported, + GError **error) { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); GdkVulkanContext *context; @@ -95,6 +96,8 @@ gsk_vulkan_renderer_create_context (GskGpuRenderer *renderer, self); gsk_vulkan_renderer_update_images_cb (context, self); + *supported = -1; + return GDK_DRAW_CONTEXT (context); }