summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2018-03-30 02:21:48 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2018-03-30 02:24:53 +0100
commit4a2e73a07c71f48290b1f6c1ec04349403c06143 (patch)
tree594ad58dd34997d7ba7502466b2ab0a9ffd8b03b
parentf8e19243551a2260fcbccd1eea575afae67b9228 (diff)
downloadgtk+-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.c1
-rw-r--r--gsk/gl/gskglshadercache.c133
-rw-r--r--gsk/gl/gskglshadercacheprivate.h23
-rw-r--r--gsk/gl/gskshaderbuilder.c107
-rw-r--r--gsk/gl/gskshaderbuilderprivate.h1
-rw-r--r--gsk/meson.build15
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')