[gtk/wip/chergert/glproto: 191/493] add shader loading (and unloading) to driver
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/glproto: 191/493] add shader loading (and unloading) to driver
- Date: Fri, 19 Feb 2021 02:25:09 +0000 (UTC)
commit e9c92379b48d7a7247688d47b5a300aa26bbca9d
Author: Christian Hergert <chergert redhat com>
Date: Wed Jan 13 22:01:12 2021 -0800
add shader loading (and unloading) to driver
gsk/next/gskgldriver.c | 142 ++++++++++++++++++++++++++++++++++++++++-
gsk/next/gskgldriverprivate.h | 16 ++++-
gsk/next/gskglprogramprivate.h | 26 +++++---
3 files changed, 172 insertions(+), 12 deletions(-)
---
diff --git a/gsk/next/gskgldriver.c b/gsk/next/gskgldriver.c
index 9175ca3346..fc68c253ed 100644
--- a/gsk/next/gskgldriver.c
+++ b/gsk/next/gskgldriver.c
@@ -24,9 +24,10 @@
#include "config.h"
#include <gdk/gdkglcontextprivate.h>
-#include <gdk/gdktextureprivate.h>
#include <gdk/gdkgltextureprivate.h>
+#include <gdk/gdktextureprivate.h>
#include <gsk/gskdebugprivate.h>
+#include <gsk/gskglshaderprivate.h>
#include <gsk/gskrendererprivate.h>
#include "gskglcommandqueueprivate.h"
@@ -131,6 +132,18 @@ gsk_next_driver_collect_unused_textures (GskNextDriver *self,
return old_size - g_hash_table_size (self->textures);
}
+static void
+gsk_next_driver_shader_weak_cb (gpointer data,
+ GObject *where_object_was)
+{
+ GskNextDriver *self = data;
+
+ g_assert (GSK_IS_NEXT_DRIVER (self));
+
+ if (self->shader_cache)
+ g_hash_table_remove (self->shader_cache, where_object_was);
+}
+
static void
gsk_next_driver_dispose (GObject *object)
{
@@ -152,6 +165,24 @@ gsk_next_driver_dispose (GObject *object)
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_DEFINE_PROGRAM
+ if (self->shader_cache != NULL)
+ {
+ GHashTableIter iter;
+ gpointer k, v;
+
+ g_hash_table_iter_init (&iter, self->shader_cache);
+ while (g_hash_table_iter_next (&iter, &k, &v))
+ {
+ GskGLShader *shader = k;
+ g_object_weak_unref (G_OBJECT (shader),
+ gsk_next_driver_shader_weak_cb,
+ self);
+ g_hash_table_iter_remove (&iter);
+ }
+
+ g_clear_pointer (&self->shader_cache, g_hash_table_unref);
+ }
+
if (self->command_queue != NULL)
{
gsk_gl_command_queue_make_current (self->command_queue);
@@ -172,6 +203,7 @@ gsk_next_driver_dispose (GObject *object)
g_clear_pointer (&self->key_to_texture_id, g_hash_table_unref);
g_clear_pointer (&self->texture_id_to_key, g_hash_table_unref);
g_clear_pointer (&self->render_targets, g_ptr_array_unref);
+ g_clear_pointer (&self->shader_cache, g_hash_table_unref);
G_OBJECT_CLASS (gsk_next_driver_parent_class)->dispose (object);
}
@@ -194,6 +226,10 @@ gsk_next_driver_init (GskNextDriver *self)
texture_key_equal,
g_free,
NULL);
+ self->shader_cache = g_hash_table_new_full (NULL,
+ NULL,
+ g_object_unref,
+ g_object_unref);
gsk_gl_texture_pool_init (&self->texture_pool);
self->render_targets = g_ptr_array_new ();
}
@@ -648,7 +684,7 @@ gsk_next_driver_acquire_texture (GskNextDriver *self,
}
/**
- * gsk_gl_driver_release_texture:
+ * gsk_next_driver_release_texture:
* @self: a #GskNextDriver
* @texture: a #GskGLTexture
*
@@ -789,3 +825,105 @@ gsk_next_driver_release_render_target (GskNextDriver *self,
return texture_id;
}
+
+/**
+ * gsk_next_driver_lookup_shader:
+ * @self: a #GskNextDriver
+ * @shader: the shader to lookup or load
+ * @error: a location for a #GError, or %NULL
+ *
+ * Attepts to load @shader from the shader cache.
+ *
+ * If it has not been loaded, then it will compile the shader on demand.
+ *
+ * Returns: (transfer none): a #GskGLShader if successful; otherwise
+ * %NULL and @error is set.
+ */
+GskGLProgram *
+gsk_next_driver_lookup_shader (GskNextDriver *self,
+ GskGLShader *shader,
+ GError **error)
+{
+ GskGLProgram *program;
+
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (shader != NULL, NULL);
+
+ program = g_hash_table_lookup (self->shader_cache, shader);
+
+ if (program == NULL)
+ {
+ const GskGLUniform *uniforms;
+ GskGLCompiler *compiler;
+ GBytes *suffix;
+ int n_required_textures;
+ int n_uniforms;
+
+ uniforms = gsk_gl_shader_get_uniforms (shader, &n_uniforms);
+ if (n_uniforms > G_N_ELEMENTS (program->args_locations))
+ {
+ g_set_error (error,
+ GDK_GL_ERROR,
+ GDK_GL_ERROR_UNSUPPORTED_FORMAT,
+ "GLShaderNode supports max %d custom uniforms",
+ (int)G_N_ELEMENTS (program->args_locations));
+ return NULL;
+ }
+
+ n_required_textures = gsk_gl_shader_get_n_textures (shader);
+ if (n_required_textures > G_N_ELEMENTS (program->texture_locations))
+ {
+ g_set_error (error,
+ GDK_GL_ERROR,
+ GDK_GL_ERROR_UNSUPPORTED_FORMAT,
+ "GLShaderNode supports max %d texture sources",
+ (int)(G_N_ELEMENTS (program->texture_locations)));
+ return NULL;
+ }
+
+ compiler = gsk_gl_compiler_new (self->command_queue, FALSE);
+ suffix = gsk_gl_shader_get_source (shader);
+
+ gsk_gl_compiler_set_preamble_from_resource (compiler,
+ GSK_GL_COMPILER_ALL,
+ "/org/gtk/libgsk/glsl/preamble.glsl");
+ gsk_gl_compiler_set_preamble_from_resource (compiler,
+ GSK_GL_COMPILER_VERTEX,
+ "/org/gtk/libgsk/glsl/preamble.vs.glsl");
+ gsk_gl_compiler_set_preamble_from_resource (compiler,
+ GSK_GL_COMPILER_FRAGMENT,
+ "/org/gtk/libgsk/glsl/preamble.fs.glsl");
+ gsk_gl_compiler_set_suffix (compiler, GSK_GL_COMPILER_FRAGMENT, suffix);
+
+ if ((program = gsk_gl_compiler_compile (compiler, NULL, NULL)))
+ {
+ gsk_gl_program_add_uniform (program, "u_size", UNIFORM_CUSTOM_SIZE);
+ gsk_gl_program_add_uniform (program, "u_texture1", UNIFORM_CUSTOM_TEXTURE1);
+ gsk_gl_program_add_uniform (program, "u_texture2", UNIFORM_CUSTOM_TEXTURE2);
+ gsk_gl_program_add_uniform (program, "u_texture3", UNIFORM_CUSTOM_TEXTURE3);
+ gsk_gl_program_add_uniform (program, "u_texture4", UNIFORM_CUSTOM_TEXTURE4);
+ for (guint i = 0; i < n_uniforms; i++)
+ gsk_gl_program_add_uniform (program, uniforms[i].name, UNIFORM_CUSTOM_LAST+i);
+
+ program->size_location = gsk_gl_program_get_uniform_location (program, UNIFORM_CUSTOM_SIZE);
+ program->texture_locations[0] = gsk_gl_program_get_uniform_location (program,
UNIFORM_CUSTOM_TEXTURE1);
+ program->texture_locations[1] = gsk_gl_program_get_uniform_location (program,
UNIFORM_CUSTOM_TEXTURE2);
+ program->texture_locations[2] = gsk_gl_program_get_uniform_location (program,
UNIFORM_CUSTOM_TEXTURE3);
+ program->texture_locations[3] = gsk_gl_program_get_uniform_location (program,
UNIFORM_CUSTOM_TEXTURE4);
+ for (guint i = 0; i < n_uniforms; i++)
+ program->args_locations[i] = gsk_gl_program_get_uniform_location (program,
UNIFORM_CUSTOM_LAST+i);
+ for (guint i = n_uniforms; i < G_N_ELEMENTS (program->args_locations); i++)
+ program->args_locations[i] = -1;
+
+ g_hash_table_insert (self->shader_cache, shader, program);
+
+ g_object_weak_ref (G_OBJECT (shader),
+ gsk_next_driver_shader_weak_cb,
+ self);
+ }
+
+ g_object_unref (compiler);
+ }
+
+ return g_steal_pointer (&program);
+}
diff --git a/gsk/next/gskgldriverprivate.h b/gsk/next/gskgldriverprivate.h
index 79980f77cd..6e843e0a93 100644
--- a/gsk/next/gskgldriverprivate.h
+++ b/gsk/next/gskgldriverprivate.h
@@ -38,6 +38,16 @@ enum {
UNIFORM_SHARED_LAST
};
+enum {
+ UNIFORM_CUSTOM_SIZE = UNIFORM_SHARED_LAST,
+ UNIFORM_CUSTOM_TEXTURE1,
+ UNIFORM_CUSTOM_TEXTURE2,
+ UNIFORM_CUSTOM_TEXTURE3,
+ UNIFORM_CUSTOM_TEXTURE4,
+
+ UNIFORM_CUSTOM_LAST
+};
+
typedef struct {
gpointer pointer;
float scale_x;
@@ -82,10 +92,11 @@ struct _GskNextDriver
GskGLShadowLibrary *shadows;
GHashTable *textures;
-
GHashTable *key_to_texture_id;
GHashTable *texture_id_to_key;
+ GHashTable *shader_cache;
+
GArray *autorelease_framebuffers;
GPtrArray *render_targets;
@@ -139,6 +150,9 @@ GskGLTexture *gsk_next_driver_acquire_texture (GskNextDriver *self
int mag_filter);
void gsk_next_driver_release_texture (GskNextDriver *self,
GskGLTexture *texture);
+GskGLProgram *gsk_next_driver_lookup_shader (GskNextDriver *self,
+ GskGLShader *shader,
+ GError **error);
G_END_DECLS
diff --git a/gsk/next/gskglprogramprivate.h b/gsk/next/gskglprogramprivate.h
index 4cf22e3056..1149002bfc 100644
--- a/gsk/next/gskglprogramprivate.h
+++ b/gsk/next/gskglprogramprivate.h
@@ -33,16 +33,24 @@ G_DECLARE_FINAL_TYPE (GskGLProgram, gsk_gl_program, GSK, GL_PROGRAM, GObject)
struct _GskGLProgram
{
- GObject parent_instance;
- int id;
- char *name;
- GArray *uniform_locations;
+ GObject parent_instance;
+
+ int id;
+ char *name;
+ GArray *uniform_locations;
GskGLCommandQueue *command_queue;
- int projection_location;
- int modelview_location;
- int viewport_location;
- int clip_rect_location;
- int alpha_location;
+
+ /* Cached shared locations */
+ int projection_location;
+ int modelview_location;
+ int viewport_location;
+ int clip_rect_location;
+ int alpha_location;
+
+ /* For custom programs */
+ int texture_locations[4];
+ int args_locations[8];
+ int size_location;
};
GskGLProgram *gsk_gl_program_new (GskGLCommandQueue *command_queue,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]