[gtk+/wip/ebassi/gsk-renderer: 61/79] gsk: Consolidate program creation and storage
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/ebassi/gsk-renderer: 61/79] gsk: Consolidate program creation and storage
- Date: Wed, 20 Jul 2016 17:06:17 +0000 (UTC)
commit 3b85e0ed416a733f7c43856e75b8a940a517cf78
Author: Emmanuele Bassi <ebassi gnome org>
Date: Mon Jul 4 13:46:22 2016 +0100
gsk: Consolidate program creation and storage
We should use ShaderBuilder to create and store programs for the GL
renderer. This allows us to simplify the creation of programs (by moving
the compilation phase into the ShaderBuilder::create_program() method),
and move towards the ability to create multiple programs and just keep a
reference to the program id.
gsk/gskglrenderer.c | 87 +++++++---------------
gsk/gskshaderbuilder.c | 164 ++++++++++++++++++++++++++++++-----------
gsk/gskshaderbuilderprivate.h | 16 ++--
3 files changed, 155 insertions(+), 112 deletions(-)
---
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index 3f2a213..91589bc 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -87,7 +87,9 @@ struct _GskGLRenderer
GQuark uniforms[N_UNIFORMS];
GQuark attributes[N_ATTRIBUTES];
- GskShaderBuilder *blend_program;
+ GskShaderBuilder *shader_builder;
+
+ int blend_program_id;
guint vao_id;
@@ -295,9 +297,6 @@ static gboolean
gsk_gl_renderer_create_programs (GskGLRenderer *self)
{
GskShaderBuilder *builder;
- const char *vertex_preamble;
- const char *fragment_preamble;
- int vertex_id = -1, fragment_id = -1;
GError *error = NULL;
gboolean res = FALSE;
@@ -317,26 +316,23 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self)
if (gdk_gl_context_get_use_es (self->context))
{
gsk_shader_builder_set_version (builder, SHADER_VERSION_GLES);
+ gsk_shader_builder_set_vertex_preamble (builder, "es2_common.vs.glsl");
+ gsk_shader_builder_set_fragment_preamble (builder, "es2_common.fs.glsl");
gsk_shader_builder_add_define (builder, "GSK_GLES", "1");
-
- vertex_preamble = "gles_common.vs.glsl";
- fragment_preamble = "gles_common.fs.glsl";
}
else if (gdk_gl_context_is_legacy (self->context))
{
gsk_shader_builder_set_version (builder, SHADER_VERSION_GL_LEGACY);
+ gsk_shader_builder_set_vertex_preamble (builder, "gl_common.vs.glsl");
+ gsk_shader_builder_set_fragment_preamble (builder, "gl_common.fs.glsl");
gsk_shader_builder_add_define (builder, "GSK_LEGACY", "1");
-
- vertex_preamble = "gl_common.vs.glsl";
- fragment_preamble = "gl_common.fs.glsl";
}
else
{
gsk_shader_builder_set_version (builder, SHADER_VERSION_GL3);
+ gsk_shader_builder_set_vertex_preamble (builder, "gl3_common.vs.glsl");
+ gsk_shader_builder_set_fragment_preamble (builder, "gl3_common.fs.glsl");
gsk_shader_builder_add_define (builder, "GSK_GL3", "1");
-
- vertex_preamble = "gl3_common.vs.glsl";
- fragment_preamble = "gl3_common.fs.glsl";
}
#ifdef G_ENABLE_DEBUG
@@ -344,62 +340,28 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self)
gsk_shader_builder_add_define (builder, "GSK_DEBUG", "1");
#endif
- vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
- vertex_preamble,
- "blend.vs.glsl",
- &error);
- if (error != NULL)
- {
- g_critical ("Unable to compile vertex shader: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
- fragment_preamble,
- "blend.fs.glsl",
- &error);
- if (error != NULL)
- {
- g_critical ("Unable to compile fragment shader: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- gsk_shader_builder_create_program (builder, vertex_id, fragment_id, &error);
+ self->blend_program_id =
+ gsk_shader_builder_create_program (builder, "blend.vs.glsl", "blend.fs.glsl", &error);
if (error != NULL)
{
g_critical ("Unable to create program: %s", error->message);
g_error_free (error);
+ g_object_unref (builder);
goto out;
}
- self->blend_program = g_object_ref (builder);
+ self->shader_builder = builder;
res = TRUE;
out:
- g_object_unref (builder);
-
- if (vertex_id > 0)
- glDeleteShader (vertex_id);
- if (fragment_id > 0)
- glDeleteShader (fragment_id);
-
return res;
}
static void
gsk_gl_renderer_destroy_programs (GskGLRenderer *self)
{
- if (self->blend_program != NULL)
- {
- int program_id = gsk_shader_builder_get_program (self->blend_program);
-
- glDeleteProgram (program_id);
-
- g_clear_object (&self->blend_program);
- }
+ g_clear_object (&self->shader_builder);
}
static gboolean
@@ -440,10 +402,11 @@ gsk_gl_renderer_realize (GskRenderer *renderer)
gdk_gl_context_make_current (self->context);
GSK_NOTE (OPENGL, g_print ("Creating buffers and programs\n"));
- gsk_gl_renderer_create_buffers (self);
if (!gsk_gl_renderer_create_programs (self))
return FALSE;
+ gsk_gl_renderer_create_buffers (self);
+
return TRUE;
}
@@ -722,6 +685,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
graphene_rect_t bounds;
GskRenderNode *child;
RenderItem item;
+ int program_id;
if (gsk_render_node_is_hidden (node))
{
@@ -767,23 +731,24 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
item.render_data.vao_id = self->vao_id;
item.render_data.buffer_id = 0;
- item.render_data.program_id = gsk_shader_builder_get_program (self->blend_program);
+ program_id = self->blend_program_id;
+ item.render_data.program_id = program_id;
item.render_data.map_location =
- gsk_shader_builder_get_uniform_location (self->blend_program, self->uniforms[MAP]);
+ gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[MAP]);
item.render_data.parentMap_location =
- gsk_shader_builder_get_uniform_location (self->blend_program, self->uniforms[PARENT_MAP]);
+ gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[PARENT_MAP]);
item.render_data.mvp_location =
- gsk_shader_builder_get_uniform_location (self->blend_program, self->uniforms[MVP]);
+ gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[MVP]);
item.render_data.alpha_location =
- gsk_shader_builder_get_uniform_location (self->blend_program, self->uniforms[ALPHA]);
+ gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[ALPHA]);
item.render_data.blendMode_location =
- gsk_shader_builder_get_uniform_location (self->blend_program, self->uniforms[BLEND_MODE]);
+ gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[BLEND_MODE]);
item.render_data.position_location =
- gsk_shader_builder_get_attribute_location (self->blend_program, self->attributes[POSITION]);
+ gsk_shader_builder_get_attribute_location (self->shader_builder, program_id, self->attributes[POSITION]);
item.render_data.uv_location =
- gsk_shader_builder_get_attribute_location (self->blend_program, self->attributes[UV]);
+ gsk_shader_builder_get_attribute_location (self->shader_builder, program_id, self->attributes[UV]);
if (parent != NULL)
item.parent_data = &(parent->render_data);
diff --git a/gsk/gskshaderbuilder.c b/gsk/gskshaderbuilder.c
index b17c41a..8e37294 100644
--- a/gsk/gskshaderbuilder.c
+++ b/gsk/gskshaderbuilder.c
@@ -7,27 +7,59 @@
#include <gdk/gdk.h>
#include <epoxy/gl.h>
+typedef struct {
+ int program_id;
+
+ GHashTable *uniform_locations;
+ GHashTable *attribute_locations;
+} ShaderProgram;
+
struct _GskShaderBuilder
{
GObject parent_instance;
char *resource_base_path;
+ char *vertex_preamble;
+ char *fragment_preamble;
int version;
- int program_id;
-
GPtrArray *defines;
GPtrArray *uniforms;
GPtrArray *attributes;
- GHashTable *uniform_locations;
- GHashTable *attribute_locations;
+ GHashTable *programs;
};
G_DEFINE_TYPE (GskShaderBuilder, gsk_shader_builder, G_TYPE_OBJECT)
static void
+shader_program_free (gpointer data)
+{
+ ShaderProgram *p = data;
+
+ g_clear_pointer (&p->uniform_locations, g_hash_table_unref);
+ g_clear_pointer (&p->attribute_locations, g_hash_table_unref);
+
+ glDeleteProgram (p->program_id);
+
+ g_slice_free (ShaderProgram, data);
+}
+
+static ShaderProgram *
+shader_program_new (int program_id)
+{
+ ShaderProgram *p = g_slice_new (ShaderProgram);
+
+ p->program_id = program_id;
+
+ p->uniform_locations = g_hash_table_new (g_direct_hash, g_direct_equal);
+ p->attribute_locations = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ return p;
+}
+
+static void
gsk_shader_builder_finalize (GObject *gobject)
{
GskShaderBuilder *self = GSK_SHADER_BUILDER (gobject);
@@ -38,8 +70,7 @@ gsk_shader_builder_finalize (GObject *gobject)
g_clear_pointer (&self->uniforms, g_ptr_array_unref);
g_clear_pointer (&self->attributes, g_ptr_array_unref);
- g_clear_pointer (&self->uniform_locations, g_hash_table_unref);
- g_clear_pointer (&self->attribute_locations, g_hash_table_unref);
+ g_clear_pointer (&self->programs, g_hash_table_unref);
G_OBJECT_CLASS (gsk_shader_builder_parent_class)->finalize (gobject);
}
@@ -57,8 +88,9 @@ gsk_shader_builder_init (GskShaderBuilder *self)
self->uniforms = g_ptr_array_new_with_free_func (g_free);
self->attributes = g_ptr_array_new_with_free_func (g_free);
- self->uniform_locations = g_hash_table_new (g_direct_hash, g_direct_equal);
- self->attribute_locations = g_hash_table_new (g_direct_hash, g_direct_equal);
+ self->programs = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL,
+ shader_program_free);
}
GskShaderBuilder *
@@ -78,6 +110,26 @@ gsk_shader_builder_set_resource_base_path (GskShaderBuilder *builder,
}
void
+gsk_shader_builder_set_vertex_preamble (GskShaderBuilder *builder,
+ const char *vertex_preamble)
+{
+ g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
+
+ g_free (builder->vertex_preamble);
+ builder->vertex_preamble = g_strdup (vertex_preamble);
+}
+
+void
+gsk_shader_builder_set_fragment_preamble (GskShaderBuilder *builder,
+ const char *fragment_preamble)
+{
+ g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
+
+ g_free (builder->fragment_preamble);
+ builder->fragment_preamble = g_strdup (fragment_preamble);
+}
+
+void
gsk_shader_builder_set_version (GskShaderBuilder *builder,
int version)
{
@@ -150,7 +202,7 @@ lookup_shader_code (GString *code,
return TRUE;
}
-int
+static int
gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
int shader_type,
const char *shader_preamble,
@@ -163,9 +215,6 @@ gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
int status;
int i;
- g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
- g_return_val_if_fail (shader_source != NULL, -1);
-
code = g_string_new (NULL);
if (builder->version > 0)
@@ -249,16 +298,16 @@ gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
static void
gsk_shader_builder_cache_uniforms (GskShaderBuilder *builder,
- int program_id)
+ ShaderProgram *program)
{
int i;
for (i = 0; i < builder->uniforms->len; i++)
{
const char *uniform = g_ptr_array_index (builder->uniforms, i);
- int loc = glGetUniformLocation (program_id, uniform);
+ int loc = glGetUniformLocation (program->program_id, uniform);
- g_hash_table_insert (builder->uniform_locations,
+ g_hash_table_insert (program->uniform_locations,
GINT_TO_POINTER (g_quark_from_string (uniform)),
GINT_TO_POINTER (loc));
}
@@ -266,16 +315,16 @@ gsk_shader_builder_cache_uniforms (GskShaderBuilder *builder,
static void
gsk_shader_builder_cache_attributes (GskShaderBuilder *builder,
- int program_id)
+ ShaderProgram *program)
{
int i;
for (i = 0; i < builder->attributes->len; i++)
{
const char *attribute = g_ptr_array_index (builder->attributes, i);
- int loc = glGetAttribLocation (program_id, attribute);
+ int loc = glGetAttribLocation (program->program_id, attribute);
- g_hash_table_insert (builder->attribute_locations,
+ g_hash_table_insert (program->attribute_locations,
GINT_TO_POINTER (g_quark_from_string (attribute)),
GINT_TO_POINTER (loc));
}
@@ -283,16 +332,35 @@ gsk_shader_builder_cache_attributes (GskShaderBuilder *builder,
int
gsk_shader_builder_create_program (GskShaderBuilder *builder,
- int vertex_id,
- int fragment_id,
+ const char *vertex_shader,
+ const char *fragment_shader,
GError **error)
{
+ ShaderProgram *program;
+ int vertex_id, fragment_id;
int program_id;
int status;
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
- g_return_val_if_fail (vertex_id > 0, -1);
- g_return_val_if_fail (fragment_id > 0, -1);
+ g_return_val_if_fail (vertex_shader != NULL, -1);
+ g_return_val_if_fail (fragment_shader != NULL, -1);
+
+ vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
+ builder->vertex_preamble,
+ vertex_shader,
+ error);
+ if (vertex_id < 0)
+ return -1;
+
+ fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
+ builder->fragment_preamble,
+ fragment_shader,
+ error);
+ if (fragment_id < 0)
+ {
+ glDeleteShader (vertex_id);
+ return -1;
+ }
program_id = glCreateProgram ();
glAttachShader (program_id, vertex_id);
@@ -320,10 +388,11 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
goto out;
}
- gsk_shader_builder_cache_uniforms (builder, program_id);
- gsk_shader_builder_cache_attributes (builder, program_id);
+ program = shader_program_new (program_id);
+ gsk_shader_builder_cache_uniforms (builder, program);
+ gsk_shader_builder_cache_attributes (builder, program);
- builder->program_id = program_id;
+ g_hash_table_insert (builder->programs, GINT_TO_POINTER (program_id), program);
#ifdef G_ENABLE_DEBUG
if (GSK_DEBUG_CHECK (OPENGL))
@@ -331,7 +400,7 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
GHashTableIter iter;
gpointer name_p, location_p;
- g_hash_table_iter_init (&iter, builder->uniform_locations);
+ g_hash_table_iter_init (&iter, program->uniform_locations);
while (g_hash_table_iter_next (&iter, &name_p, &location_p))
{
g_print ("Uniform '%s' - location: %d\n",
@@ -339,7 +408,7 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
GPOINTER_TO_INT (location_p));
}
- g_hash_table_iter_init (&iter, builder->attribute_locations);
+ g_hash_table_iter_init (&iter, program->attribute_locations);
while (g_hash_table_iter_next (&iter, &name_p, &location_p))
{
g_print ("Attribute '%s' - location: %d\n",
@@ -350,27 +419,40 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
#endif
out:
- glDetachShader (program_id, vertex_id);
- glDetachShader (program_id, fragment_id);
+ if (vertex_id > 0)
+ {
+ glDetachShader (program_id, vertex_id);
+ glDeleteShader (vertex_id);
+ }
+
+ if (fragment_id > 0)
+ {
+ glDetachShader (program_id, fragment_id);
+ glDeleteShader (fragment_id);
+ }
return program_id;
}
int
gsk_shader_builder_get_uniform_location (GskShaderBuilder *builder,
+ int program_id,
GQuark uniform_quark)
{
+ ShaderProgram *p = NULL;
gpointer loc_p = NULL;
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
+ g_return_val_if_fail (program_id >= 0, -1);
- if (builder->program_id < 0)
+ if (builder->uniforms->len == 0)
return -1;
- if (builder->uniforms->len == 0)
+ p = g_hash_table_lookup (builder->programs, GINT_TO_POINTER (program_id));
+ if (p == NULL)
return -1;
- if (g_hash_table_lookup_extended (builder->uniform_locations, GINT_TO_POINTER (uniform_quark), NULL,
&loc_p))
+ if (g_hash_table_lookup_extended (p->uniform_locations, GINT_TO_POINTER (uniform_quark), NULL, &loc_p))
return GPOINTER_TO_INT (loc_p);
return -1;
@@ -378,28 +460,24 @@ gsk_shader_builder_get_uniform_location (GskShaderBuilder *builder,
int
gsk_shader_builder_get_attribute_location (GskShaderBuilder *builder,
+ int program_id,
GQuark attribute_quark)
{
+ ShaderProgram *p = NULL;
gpointer loc_p = NULL;
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
+ g_return_val_if_fail (program_id >= 0, -1);
- if (builder->program_id < 0)
+ if (builder->attributes->len == 0)
return -1;
- if (builder->attributes->len == 0)
+ p = g_hash_table_lookup (builder->programs, GINT_TO_POINTER (program_id));
+ if (p == NULL)
return -1;
- if (g_hash_table_lookup_extended (builder->attribute_locations, GINT_TO_POINTER (attribute_quark), NULL,
&loc_p))
+ if (g_hash_table_lookup_extended (p->attribute_locations, GINT_TO_POINTER (attribute_quark), NULL, &loc_p))
return GPOINTER_TO_INT (loc_p);
return -1;
}
-
-int
-gsk_shader_builder_get_program (GskShaderBuilder *builder)
-{
- g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
-
- return builder->program_id;
-}
diff --git a/gsk/gskshaderbuilderprivate.h b/gsk/gskshaderbuilderprivate.h
index ce069ed..144b2b0 100644
--- a/gsk/gskshaderbuilderprivate.h
+++ b/gsk/gskshaderbuilderprivate.h
@@ -16,6 +16,10 @@ void gsk_shader_builder_set_version (GskShad
int version);
void gsk_shader_builder_set_resource_base_path (GskShaderBuilder *builder,
const char *base_path);
+void gsk_shader_builder_set_vertex_preamble (GskShaderBuilder *builder,
+ const char *shader_preamble);
+void gsk_shader_builder_set_fragment_preamble (GskShaderBuilder *builder,
+ const char *shader_preamble);
GQuark gsk_shader_builder_add_uniform (GskShaderBuilder *builder,
const char *uniform_name);
@@ -25,20 +29,16 @@ void gsk_shader_builder_add_define (GskShad
const char *define_name,
const char *define_value);
-int gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
- int shader_type,
- const char *shader_preamble,
- const char *shader_source,
- GError **error);
int gsk_shader_builder_create_program (GskShaderBuilder *builder,
- int vertex_id,
- int fragment_id,
+ const char *vertex_shader,
+ const char *fragment_shader,
GError **error);
-int gsk_shader_builder_get_program (GskShaderBuilder *builder);
int gsk_shader_builder_get_uniform_location (GskShaderBuilder *builder,
+ int program_id,
GQuark uniform_quark);
int gsk_shader_builder_get_attribute_location (GskShaderBuilder *builder,
+ int program_id,
GQuark attribute_quark);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]