mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-12 20:00:09 +00:00
gpu: Add a GL optimization
Use glDrawArraysInstancedBaseInstance() to draw. (Yay for GL naming.) That allows setting up the offset in the vertex array without having to glVertexAttribPointer() everything again. However, this is only supported since GL 4.2 and not at all in stock GLES, so we need to have code that can work without it. Fortunately, it is mandatory in Vulkan, so every recent GPU supports it. And if that GPU has a proper driver, it will also expose the GL extension for it. (Hint: You can check https://opengles.gpuinfo.org/listextensions.php for how many proper drivers exist outside of Mesa.)
This commit is contained in:
parent
8271687ef6
commit
9045431bde
@ -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));
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
|
||||
{ "uber", GSK_GPU_OPTIMIZE_UBER, "Don't use the uber shader" },
|
||||
{ "clear", GSK_GPU_OPTIMIZE_CLEAR, "Use shaders instead of vkCmdClearAttachment()/glClear()" },
|
||||
{ "merge", GSK_GPU_OPTIMIZE_MERGE, "Use one vkCmdDraw()/glDrawArrays() per operation" },
|
||||
|
||||
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
|
||||
};
|
||||
|
||||
typedef struct _GskGpuRendererPrivate GskGpuRendererPrivate;
|
||||
@ -33,6 +35,7 @@ struct _GskGpuRendererPrivate
|
||||
{
|
||||
GskGpuDevice *device;
|
||||
GdkDrawContext *context;
|
||||
GskGpuOptimizations optimizations;
|
||||
|
||||
GskGpuFrame *frames[GSK_GPU_MAX_FRAMES];
|
||||
};
|
||||
@ -83,7 +86,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;
|
||||
}
|
||||
@ -119,6 +122,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)
|
||||
@ -130,13 +134,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;
|
||||
}
|
||||
|
||||
@ -287,6 +293,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 *
|
||||
|
@ -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);
|
||||
|
@ -106,12 +106,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;
|
||||
}
|
||||
|
@ -58,5 +58,7 @@ typedef enum {
|
||||
GSK_GPU_OPTIMIZE_UBER = 1 << 0,
|
||||
GSK_GPU_OPTIMIZE_CLEAR = 1 << 1,
|
||||
GSK_GPU_OPTIMIZE_MERGE = 1 << 2,
|
||||
/* These require hardware support */
|
||||
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 3,
|
||||
} GskGpuOptimizations;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user