diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2018-03-30 02:21:48 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2018-03-30 02:24:53 +0100 |
commit | 4a2e73a07c71f48290b1f6c1ec04349403c06143 (patch) | |
tree | 594ad58dd34997d7ba7502466b2ab0a9ffd8b03b | |
parent | f8e19243551a2260fcbccd1eea575afae67b9228 (diff) | |
download | gtk+-4a2e73a07c71f48290b1f6c1ec04349403c06143.tar.gz |
Move GL shader compilation to a separate object
We want to cache the compiled and linked programs, so the first step is
to create an object in charge of compiling and linking GLSL programs.
We only create one per GL context, for the time being, but in the
following commits we're going to store it per display connection, and
introduce the cache.
-rw-r--r-- | gsk/gl/gskglrenderer.c | 1 | ||||
-rw-r--r-- | gsk/gl/gskglshadercache.c | 133 | ||||
-rw-r--r-- | gsk/gl/gskglshadercacheprivate.h | 23 | ||||
-rw-r--r-- | gsk/gl/gskshaderbuilder.c | 107 | ||||
-rw-r--r-- | gsk/gl/gskshaderbuilderprivate.h | 1 | ||||
-rw-r--r-- | gsk/meson.build | 15 |
6 files changed, 190 insertions, 90 deletions
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 182004518c..a3ec8e5fd0 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -1790,6 +1790,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, prog->index = i; prog->id = gsk_shader_builder_create_program (builder, + self->gl_context, program_definitions[i].vs, program_definitions[i].fs, &shader_error); diff --git a/gsk/gl/gskglshadercache.c b/gsk/gl/gskglshadercache.c new file mode 100644 index 0000000000..8f708ddf48 --- /dev/null +++ b/gsk/gl/gskglshadercache.c @@ -0,0 +1,133 @@ +#include "config.h" + +#include "gskglshadercacheprivate.h" + +#include "gskdebugprivate.h" + +#include <epoxy/gl.h> + +struct _GskGLShaderCache +{ + GObject parent_instance; +}; + +G_DEFINE_TYPE (GskGLShaderCache, gsk_gl_shader_cache, G_TYPE_OBJECT) + +static void +gsk_gl_shader_cache_class_init (GskGLShaderCacheClass *klass) +{ +} + +static void +gsk_gl_shader_cache_init (GskGLShaderCache *self) +{ +} + +GskGLShaderCache * +gsk_gl_shader_cache_new (void) +{ + return g_object_new (GSK_TYPE_GL_SHADER_CACHE, NULL); +} + +int +gsk_gl_shader_cache_compile_shader (GskGLShaderCache *cache, + int shader_type, + const char *source, + GError **error) +{ + int shader_id = glCreateShader (shader_type); + glShaderSource (shader_id, 1, (const GLchar **) &source, NULL); + glCompileShader (shader_id); + +#ifdef G_ENABLE_DEBUG + if (GSK_DEBUG_CHECK (SHADERS)) + { + g_print ("*** Compiling %s shader ***\n" + "%s\n", + shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", + source); + } +#endif + + int status = GL_FALSE; + glGetShaderiv (shader_id, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + int log_len = 0; + glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &log_len); + + char *buffer = g_malloc0 (log_len + 1); + glGetShaderInfoLog (shader_id, log_len, NULL, buffer); + + g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED, + "Compilation failure in %s shader:\n%s", + shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", + buffer); + + g_free (buffer); + + glDeleteShader (shader_id); + shader_id = -1; + } + + return shader_id; +} + +int +gsk_gl_shader_cache_link_program (GskGLShaderCache *cache, + int vertex_shader, + int fragment_shader, + GError **error) +{ + int program_id = glCreateProgram (); + +#ifdef G_ENABLE_DEBUG + if (GSK_DEBUG_CHECK (SHADERS)) + { + g_print ("*** Linking %d, %d shaders ***\n", + vertex_shader, + fragment_shader); + } +#endif + + glAttachShader (program_id, vertex_shader); + glAttachShader (program_id, fragment_shader); + glLinkProgram (program_id); + + int status = GL_FALSE; + glGetProgramiv (program_id, GL_LINK_STATUS, &status); + if (status == GL_FALSE) + { + int log_len = 0; + glGetProgramiv (program_id, GL_INFO_LOG_LENGTH, &log_len); + + char *buffer = g_malloc0 (log_len + 1); + glGetProgramInfoLog (program_id, log_len, NULL, buffer); + + g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED, + "Linking failure in shader:\n%s", buffer); + + g_free (buffer); + + glDeleteProgram (program_id); + program_id = -1; + } + + if (vertex_shader > 0) + { + if (program_id > 0) + glDetachShader (program_id, vertex_shader); + + glDeleteShader (vertex_shader); + } + + if (fragment_shader > 0) + { + if (program_id > 0) + glDetachShader (program_id, fragment_shader); + + glDeleteShader (fragment_shader); + } + + return program_id; +} diff --git a/gsk/gl/gskglshadercacheprivate.h b/gsk/gl/gskglshadercacheprivate.h new file mode 100644 index 0000000000..8ae4f95976 --- /dev/null +++ b/gsk/gl/gskglshadercacheprivate.h @@ -0,0 +1,23 @@ +#pragma once + +#include <gdk/gdk.h> +#include <graphene.h> + +G_BEGIN_DECLS + +#define GSK_TYPE_GL_SHADER_CACHE (gsk_gl_shader_cache_get_type ()) + +G_DECLARE_FINAL_TYPE (GskGLShaderCache, gsk_gl_shader_cache, GSK, GL_SHADER_CACHE, GObject) + +GskGLShaderCache * gsk_gl_shader_cache_new (void); + +int gsk_gl_shader_cache_compile_shader (GskGLShaderCache *cache, + int shader_type, + const char *code, + GError **error); +int gsk_gl_shader_cache_link_program (GskGLShaderCache *cache, + int vertex_shader, + int fragment_shader, + GError **error); + +G_END_DECLS diff --git a/gsk/gl/gskshaderbuilder.c b/gsk/gl/gskshaderbuilder.c index 4866fc2fe4..f6d95f23b2 100644 --- a/gsk/gl/gskshaderbuilder.c +++ b/gsk/gl/gskshaderbuilder.c @@ -3,6 +3,7 @@ #include "gskshaderbuilderprivate.h" #include "gskdebugprivate.h" +#include "gskglshadercacheprivate.h" #include <gdk/gdk.h> #include <epoxy/gl.h> @@ -18,8 +19,6 @@ struct _GskShaderBuilder int version; GPtrArray *defines; - GPtrArray *uniforms; - GPtrArray *attributes; }; G_DEFINE_TYPE (GskShaderBuilder, gsk_shader_builder, G_TYPE_OBJECT) @@ -137,6 +136,7 @@ lookup_shader_code (GString *code, static int gsk_shader_builder_compile_shader (GskShaderBuilder *builder, + GskGLShaderCache *cache, int shader_type, const char *shader_preamble, const char *shader_source, @@ -145,7 +145,6 @@ gsk_shader_builder_compile_shader (GskShaderBuilder *builder, GString *code; char *source; int shader_id; - int status; int i; code = g_string_new (NULL); @@ -188,70 +187,48 @@ gsk_shader_builder_compile_shader (GskShaderBuilder *builder, source = g_string_free (code, FALSE); - shader_id = glCreateShader (shader_type); - glShaderSource (shader_id, 1, (const GLchar **) &source, NULL); - glCompileShader (shader_id); - -#ifdef G_ENABLE_DEBUG - if (GSK_DEBUG_CHECK (SHADERS)) - { - g_print ("*** Compiling %s shader from '%s' + '%s' ***\n" - "%s\n", - shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", - shader_preamble, shader_source, - source); - } -#endif + shader_id = gsk_gl_shader_cache_compile_shader (cache, + shader_type, source, + error); g_free (source); - glGetShaderiv (shader_id, GL_COMPILE_STATUS, &status); - if (status == GL_FALSE) - { - int log_len; - char *buffer; - - glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &log_len); - - buffer = g_malloc0 (log_len + 1); - glGetShaderInfoLog (shader_id, log_len, NULL, buffer); - - g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED, - "Compilation failure in %s shader:\n%s", - shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", - buffer); - g_free (buffer); - - glDeleteShader (shader_id); - - return -1; - } - return shader_id; } int gsk_shader_builder_create_program (GskShaderBuilder *builder, + GdkGLContext *gl_context, const char *vertex_shader, const char *fragment_shader, GError **error) { 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_shader != NULL, -1); g_return_val_if_fail (fragment_shader != NULL, -1); - vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER, + GskGLShaderCache *cache = g_object_get_data (G_OBJECT (gl_context), "-gsk-gl-shader-cache"); + if (cache == NULL) + { + cache = gsk_gl_shader_cache_new (); + g_object_set_data_full (G_OBJECT (gl_context), + "-gsk-gl-shader-cache", + cache, + (GDestroyNotify) g_object_unref); + } + + vertex_id = gsk_shader_builder_compile_shader (builder, cache, + 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, + fragment_id = gsk_shader_builder_compile_shader (builder, cache, + GL_FRAGMENT_SHADER, builder->fragment_preamble, fragment_shader, error); @@ -261,44 +238,8 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder, return -1; } - program_id = glCreateProgram (); - glAttachShader (program_id, vertex_id); - glAttachShader (program_id, fragment_id); - glLinkProgram (program_id); - - glGetProgramiv (program_id, GL_LINK_STATUS, &status); - if (status == GL_FALSE) - { - char *buffer = NULL; - int log_len = 0; - - glGetProgramiv (program_id, GL_INFO_LOG_LENGTH, &log_len); - - buffer = g_malloc0 (log_len + 1); - glGetProgramInfoLog (program_id, log_len, NULL, buffer); - - g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED, - "Linking failure in shader:\n%s", buffer); - g_free (buffer); - - glDeleteProgram (program_id); - program_id = -1; - - goto out; - } - -out: - 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; + return gsk_gl_shader_cache_link_program (cache, + vertex_id, + fragment_id, + error); } diff --git a/gsk/gl/gskshaderbuilderprivate.h b/gsk/gl/gskshaderbuilderprivate.h index 73f44736fa..d995acf814 100644 --- a/gsk/gl/gskshaderbuilderprivate.h +++ b/gsk/gl/gskshaderbuilderprivate.h @@ -26,6 +26,7 @@ void gsk_shader_builder_add_define (GskShad const char *define_value); int gsk_shader_builder_create_program (GskShaderBuilder *builder, + GdkGLContext *gl_context, const char *vertex_shader, const char *fragment_shader, GError **error); diff --git a/gsk/meson.build b/gsk/meson.build index 0c8b6400ec..c32ad1f8be 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -25,7 +25,7 @@ gsk_public_sources = files([ 'gskrenderer.c', 'gskrendernode.c', 'gskrendernodeimpl.c', - 'gskroundedrect.c' + 'gskroundedrect.c', ]) gsk_private_sources = files([ @@ -34,13 +34,14 @@ gsk_private_sources = files([ 'gskdebug.c', 'gskprivate.c', 'gskprofiler.c', - 'gl/gskshaderbuilder.c', - 'gl/gskglprofiler.c', - 'gl/gskglrenderer.c', + 'gl/gskgldriver.c', 'gl/gskglglyphcache.c', 'gl/gskglimage.c', - 'gl/gskgldriver.c', - 'gl/gskglrenderops.c' + 'gl/gskglprofiler.c', + 'gl/gskglrenderer.c', + 'gl/gskglrenderops.c', + 'gl/gskglshadercache.c', + 'gl/gskshaderbuilder.c', ]) gsk_public_headers = files([ @@ -49,7 +50,7 @@ gsk_public_headers = files([ 'gskrendernode.h', 'gskroundedrect.h', 'gsktypes.h', - 'gsk-autocleanup.h' + 'gsk-autocleanup.h', ]) install_headers(gsk_public_headers, 'gsk.h', subdir: 'gtk-4.0/gsk') |