[gtk+/wip/otte/shader: 62/101] gsksl: Add support for stages
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 62/101] gsksl: Add support for stages
- Date: Fri, 27 Oct 2017 12:27:23 +0000 (UTC)
commit 861768e75a0db35badf30c5a594d41d5451cec2a
Author: Benjamin Otte <otte redhat com>
Date: Tue Oct 17 03:04:26 2017 +0200
gsksl: Add support for stages
The stage is just passed to everywhere it's needed. The compiler does
not keep a stage property, instead it requires passing the stage as an
argument to every compilation.
As a side effect, environment treatment has changed:
Environments now allow creating "similar" (for lack of a better term)
environments with different version/profile.
We use this to pass the stage as part of the environment.
gsk/gskenums.h | 12 +++++++++
gsk/gskpixelshader.c | 2 +-
gsk/gskslcompiler.c | 25 ++++++++++++-------
gsk/gskslcompiler.h | 2 +
gsk/gskslenvironment.c | 23 ++++++++++++++++-
gsk/gskslenvironmentprivate.h | 8 +++++-
gsk/gskslpreprocessor.c | 37 ++++++++++------------------
gsk/gskslprogram.c | 4 ++-
gsk/gskspvwriter.c | 29 ++++++++++++++++++----
gsk/gskspvwriterprivate.h | 2 +-
gtk/glsl.c | 54 +++++++++++++++++++++++++++++++++++++++-
testsuite/gsksl/test-error.c | 24 +++++++++++++++++-
12 files changed, 175 insertions(+), 47 deletions(-)
---
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index ddca9b2..6d53824 100644
--- a/gsk/gskenums.h
+++ b/gsk/gskenums.h
@@ -192,4 +192,16 @@ typedef enum {
GSK_SL_PROFILE_ES,
} GskSlProfile;
+/**
+ * GskSlShaderStage:
+ * @GSK_SL_SHADER_VERTEX: The vertex shader stage
+ * @GSK_SL_SHADER_FRAGMENT: The fragment shader stage
+ *
+ * The shader stage associated with a GLSL program.
+ */
+typedef enum {
+ GSK_SL_SHADER_VERTEX,
+ GSK_SL_SHADER_FRAGMENT
+} GskSlShaderStage;
+
#endif /* __GSK_TYPES_H__ */
diff --git a/gsk/gskpixelshader.c b/gsk/gskpixelshader.c
index a0cadd5..4ec43cf 100644
--- a/gsk/gskpixelshader.c
+++ b/gsk/gskpixelshader.c
@@ -151,7 +151,7 @@ gsk_pixel_shader_new_for_data (GBytes *source,
g_return_val_if_fail (source != NULL, NULL);
compiler = gsk_sl_compiler_new ();
- program = gsk_sl_compiler_compile_bytes (compiler, source);
+ program = gsk_sl_compiler_compile_bytes (compiler, GSK_SL_SHADER_FRAGMENT, source);
g_object_unref (compiler);
if (program == NULL)
return NULL;
diff --git a/gsk/gskslcompiler.c b/gsk/gskslcompiler.c
index 8af9579..4d8de43 100644
--- a/gsk/gskslcompiler.c
+++ b/gsk/gskslcompiler.c
@@ -22,6 +22,7 @@
#include "gskcodesourceprivate.h"
#include "gsksldefineprivate.h"
+#include "gskslenvironmentprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprogramprivate.h"
#include "gsksltokenizerprivate.h"
@@ -231,15 +232,19 @@ gsk_sl_compiler_resolve_include (GskSlCompiler *compiler,
}
static GskSlProgram *
-gsk_sl_compiler_compile (GskSlCompiler *compiler,
- GskCodeSource *source)
+gsk_sl_compiler_compile (GskSlCompiler *compiler,
+ GskSlShaderStage stage,
+ GskCodeSource *source)
{
GskSlPreprocessor *preproc;
+ GskSlEnvironment *environment;
GskSlProgram *program;
program = g_object_new (GSK_TYPE_SL_PROGRAM, NULL);
- preproc = gsk_sl_preprocessor_new (compiler, NULL, source);
+ environment = gsk_sl_environment_new (stage, GSK_SL_PROFILE_CORE, 150);
+ preproc = gsk_sl_preprocessor_new (compiler, environment, source);
+ gsk_sl_environment_unref (environment);
gsk_sl_program_parse (program, preproc);
@@ -255,8 +260,9 @@ gsk_sl_compiler_compile (GskSlCompiler *compiler,
}
GskSlProgram *
-gsk_sl_compiler_compile_file (GskSlCompiler *compiler,
- GFile *file)
+gsk_sl_compiler_compile_file (GskSlCompiler *compiler,
+ GskSlShaderStage stage,
+ GFile *file)
{
GskSlProgram *program;
GskCodeSource *source;
@@ -266,7 +272,7 @@ gsk_sl_compiler_compile_file (GskSlCompiler *compiler,
source = gsk_code_source_new_for_file (file);
- program = gsk_sl_compiler_compile (compiler, source);
+ program = gsk_sl_compiler_compile (compiler, stage, source);
g_object_unref (source);
@@ -274,8 +280,9 @@ gsk_sl_compiler_compile_file (GskSlCompiler *compiler,
}
GskSlProgram *
-gsk_sl_compiler_compile_bytes (GskSlCompiler *compiler,
- GBytes *bytes)
+gsk_sl_compiler_compile_bytes (GskSlCompiler *compiler,
+ GskSlShaderStage stage,
+ GBytes *bytes)
{
GskSlProgram *program;
GskCodeSource *source;
@@ -285,7 +292,7 @@ gsk_sl_compiler_compile_bytes (GskSlCompiler *compiler,
source = gsk_code_source_new_for_bytes ("<program>", bytes);
- program = gsk_sl_compiler_compile (compiler, source);
+ program = gsk_sl_compiler_compile (compiler, stage, source);
g_object_unref (source);
diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h
index 6746e56..532f94d 100644
--- a/gsk/gskslcompiler.h
+++ b/gsk/gskslcompiler.h
@@ -74,9 +74,11 @@ void gsk_sl_compiler_remove_define (GskSlCompiler
GDK_AVAILABLE_IN_3_92
GskSlProgram * gsk_sl_compiler_compile_file (GskSlCompiler *compiler,
+ GskSlShaderStage stage,
GFile *file);
GDK_AVAILABLE_IN_3_92
GskSlProgram * gsk_sl_compiler_compile_bytes (GskSlCompiler *compiler,
+ GskSlShaderStage stage,
GBytes *bytes);
G_END_DECLS
diff --git a/gsk/gskslenvironment.c b/gsk/gskslenvironment.c
index f9c5ef2..6b5a0e3 100644
--- a/gsk/gskslenvironment.c
+++ b/gsk/gskslenvironment.c
@@ -29,19 +29,22 @@ struct _GskSlEnvironment
{
int ref_count;
+ GskSlShaderStage stage;
GskSlProfile profile;
guint version;
};
GskSlEnvironment *
-gsk_sl_environment_new (GskSlProfile profile,
- guint version)
+gsk_sl_environment_new (GskSlShaderStage stage,
+ GskSlProfile profile,
+ guint version)
{
GskSlEnvironment *environment;
environment = g_slice_new0 (GskSlEnvironment);
environment->ref_count = 1;
+ environment->stage = stage;
environment->profile = profile;
environment->version = version;
@@ -49,6 +52,17 @@ gsk_sl_environment_new (GskSlProfile profile,
}
GskSlEnvironment *
+gsk_sl_environment_new_similar (GskSlEnvironment *environment,
+ GskSlProfile profile,
+ guint version,
+ GError **error)
+{
+ return gsk_sl_environment_new (environment->stage,
+ profile == GSK_SL_PROFILE_NONE ? environment->profile : profile,
+ version);
+}
+
+GskSlEnvironment *
gsk_sl_environment_ref (GskSlEnvironment *environment)
{
g_return_val_if_fail (environment != NULL, NULL);
@@ -71,6 +85,11 @@ gsk_sl_environment_unref (GskSlEnvironment *environment)
g_slice_free (GskSlEnvironment, environment);
}
+GskSlShaderStage
+gsk_sl_environment_get_stage (GskSlEnvironment *environment)
+{
+ return environment->stage;
+}
GskSlProfile
gsk_sl_environment_get_profile (GskSlEnvironment *environment)
diff --git a/gsk/gskslenvironmentprivate.h b/gsk/gskslenvironmentprivate.h
index 5e73f1c..ea63a95 100644
--- a/gsk/gskslenvironmentprivate.h
+++ b/gsk/gskslenvironmentprivate.h
@@ -25,12 +25,18 @@
G_BEGIN_DECLS
-GskSlEnvironment * gsk_sl_environment_new (GskSlProfile profile,
+GskSlEnvironment * gsk_sl_environment_new (GskSlShaderStage stage,
+ GskSlProfile profile,
guint version);
+GskSlEnvironment * gsk_sl_environment_new_similar (GskSlEnvironment *environment,
+ GskSlProfile profile,
+ guint version,
+ GError **error);
GskSlEnvironment * gsk_sl_environment_ref (GskSlEnvironment *environment);
void gsk_sl_environment_unref (GskSlEnvironment *environment);
+GskSlShaderStage gsk_sl_environment_get_stage (GskSlEnvironment *environment);
GskSlProfile gsk_sl_environment_get_profile (GskSlEnvironment *environment);
guint gsk_sl_environment_get_version (GskSlEnvironment *environment);
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index e7e3de2..5487b50 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -164,7 +164,9 @@ gsk_sl_preprocessor_handle_version (GskSlPreprocessor *preproc,
const char *profile_name,
gboolean first_token_ever)
{
- G_GNUC_UNUSED GskSlProfile profile;
+ GskSlEnvironment *new_environment;
+ GskSlProfile profile;
+ GError *error = NULL;
if (version <= 0)
{
@@ -189,29 +191,18 @@ gsk_sl_preprocessor_handle_version (GskSlPreprocessor *preproc,
gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "#version directive must be first in
compilation.");
return;
}
- if (preproc->environment)
+
+ new_environment = gsk_sl_environment_new_similar (preproc->environment, profile, version, &error);
+ if (new_environment == NULL)
{
- if (gsk_sl_environment_get_profile (preproc->environment) == profile &&
- gsk_sl_environment_get_version (preproc->environment) == version)
- {
- gsk_sl_preprocessor_warn_full (preproc, VERSION, location,
- "#version directive should not be used, but it matches predefined
version.");
- return;
- }
- else
- {
- GskSlProfile env_profile = gsk_sl_environment_get_profile (preproc->environment);
- gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location,
- "#version directive not allowed. This compilation uses %u %s.",
- gsk_sl_environment_get_version (preproc->environment),
- env_profile == GSK_SL_PROFILE_ES ? "es" :
- env_profile == GSK_SL_PROFILE_COMPATIBILITY ? "compatibility" :
- "core");
- return;
- }
+ gsk_sl_preprocessor_emit_error (preproc, TRUE, location, error);
+ g_clear_error (&error);
+ }
+ else
+ {
+ gsk_sl_environment_unref (preproc->environment);
+ preproc->environment = new_environment;
}
-
- preproc->environment = gsk_sl_environment_new (profile, version);
}
static gboolean
@@ -737,8 +728,6 @@ gsk_sl_preprocessor_new (GskSlCompiler *compiler,
gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
gsk_sl_preprocessor_handle_token (preproc, &pp, TRUE, FALSE);
}
- if (preproc->environment == NULL)
- preproc->environment = gsk_sl_environment_new (GSK_SL_PROFILE_CORE, 150);
return preproc;
}
diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c
index e5a1066..8ca5d39 100644
--- a/gsk/gskslprogram.c
+++ b/gsk/gskslprogram.c
@@ -33,6 +33,7 @@
struct _GskSlProgram {
GObject parent_instance;
+ GskSlShaderStage stage;
GskSlScope *scope;
GSList *declarations;
};
@@ -70,6 +71,7 @@ gsk_sl_program_parse (GskSlProgram *program,
GskSlDeclaration *declaration;
const GskSlToken *token;
+ program->stage = gsk_sl_environment_get_stage (gsk_sl_preprocessor_get_environment (preproc));
program->scope = gsk_sl_environment_create_scope (gsk_sl_preprocessor_get_environment (preproc));
for (token = gsk_sl_preprocessor_get (preproc);
@@ -153,7 +155,7 @@ gsk_sl_program_to_spirv (GskSlProgram *program)
g_return_val_if_fail (GSK_IS_SL_PROGRAM (program), NULL);
- writer = gsk_spv_writer_new ();
+ writer = gsk_spv_writer_new (program->stage);
bytes = gsk_spv_writer_write (writer,
gsk_sl_program_get_entry_point (program),
diff --git a/gsk/gskspvwriter.c b/gsk/gskspvwriter.c
index 57e5b38..ce307bb 100644
--- a/gsk/gskspvwriter.c
+++ b/gsk/gskspvwriter.c
@@ -49,6 +49,8 @@ struct _GskSpvWriter
{
int ref_count;
+ GskSlShaderStage stage;
+
guint32 last_id;
guint extended_instructions_id;
GArray *code[GSK_SPV_WRITER_N_GLOBAL_SECTIONS];
@@ -122,13 +124,14 @@ pointer_type_free (gpointer data)
}
GskSpvWriter *
-gsk_spv_writer_new (void)
+gsk_spv_writer_new (GskSlShaderStage stage)
{
GskSpvWriter *writer;
guint i;
writer = g_slice_new0 (GskSpvWriter);
writer->ref_count = 1;
+ writer->stage = stage;
for (i = 0; i < GSK_SPV_WRITER_N_GLOBAL_SECTIONS; i++)
{
@@ -266,6 +269,21 @@ gsk_spv_writer_collect_entry_point_interfaces (GskSpvWriter *writer,
return (guint32 *) g_array_free (interfaces, FALSE);
}
+static GskSpvExecutionModel
+gsk_spv_writer_get_execution_model (GskSpvWriter *writer)
+{
+ switch (writer->stage)
+ {
+ case GSK_SL_SHADER_VERTEX:
+ return GSK_SPV_EXECUTION_MODEL_VERTEX;
+ case GSK_SL_SHADER_FRAGMENT:
+ return GSK_SPV_EXECUTION_MODEL_FRAGMENT;
+ default:
+ g_assert_not_reached ();
+ return GSK_SPV_EXECUTION_MODEL_FRAGMENT;
+ }
+}
+
static void
gsk_spv_writer_do_write (GskSpvWriter *writer,
GskSlFunction *entry_point,
@@ -295,16 +313,17 @@ gsk_spv_writer_do_write (GskSpvWriter *writer,
interfaces = gsk_spv_writer_collect_entry_point_interfaces (writer,
&n_interfaces);
gsk_spv_writer_entry_point (writer,
- GSK_SPV_EXECUTION_MODEL_FRAGMENT,
+ gsk_spv_writer_get_execution_model (writer),
entry_point_id,
"main",
interfaces,
n_interfaces);
g_free (interfaces);
- gsk_spv_writer_execution_mode (writer,
- entry_point_id,
- GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT);
+ if (writer->stage == GSK_SL_SHADER_FRAGMENT)
+ gsk_spv_writer_execution_mode (writer,
+ entry_point_id,
+ GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT);
}
static void
diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h
index f745362..74937df 100644
--- a/gsk/gskspvwriterprivate.h
+++ b/gsk/gskspvwriterprivate.h
@@ -47,7 +47,7 @@ typedef enum {
#define GSK_SPV_WRITER_N_GLOBAL_SECTIONS GSK_SPV_WRITER_SECTION_BLOCK_FIRST
#define GSK_SPV_WRITER_N_BLOCK_SECTIONS (GSK_SPV_WRITER_N_SECTIONS - GSK_SPV_WRITER_N_GLOBAL_SECTIONS)
-GskSpvWriter * gsk_spv_writer_new (void);
+GskSpvWriter * gsk_spv_writer_new (GskSlShaderStage stage);
GskSpvWriter * gsk_spv_writer_ref (GskSpvWriter *writer);
void gsk_spv_writer_unref (GskSpvWriter *writer);
diff --git a/gtk/glsl.c b/gtk/glsl.c
index 033be8a..d757ba7 100644
--- a/gtk/glsl.c
+++ b/gtk/glsl.c
@@ -41,7 +41,9 @@ compile (GskSlCompiler *compiler,
file = g_file_new_for_commandline_arg (filename);
- program = gsk_sl_compiler_compile_file (compiler, file);
+ program = gsk_sl_compiler_compile_file (compiler,
+ GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (compiler),
"shader-stage")),
+ file);
g_object_unref (file);
if (program == NULL)
return FALSE;
@@ -74,7 +76,9 @@ dump (GskSlCompiler *compiler,
file = g_file_new_for_commandline_arg (filename);
- program = gsk_sl_compiler_compile_file (compiler, file);
+ program = gsk_sl_compiler_compile_file (compiler,
+ GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (compiler),
"shader-stage")),
+ file);
g_object_unref (file);
if (program == NULL)
return FALSE;
@@ -141,6 +145,50 @@ undefine (const gchar *option_name,
return TRUE;
}
+static gboolean
+stage (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ static const struct {
+ const char *name;
+ GskSlShaderStage stage;
+ } stage_names[] = {
+ { "f", GSK_SL_SHADER_FRAGMENT },
+ { "frag", GSK_SL_SHADER_FRAGMENT },
+ { "fragment", GSK_SL_SHADER_FRAGMENT },
+ { "v", GSK_SL_SHADER_VERTEX },
+ { "vert", GSK_SL_SHADER_VERTEX },
+ { "vertex", GSK_SL_SHADER_VERTEX }
+ };
+ GskSlCompiler *compiler = data;
+ GString *str;
+ gsize i;
+
+ for (i = 0; i < G_N_ELEMENTS (stage_names); i++)
+ {
+ if (g_ascii_strcasecmp (stage_names[i].name, value) == 0)
+ {
+ g_object_set_data (G_OBJECT (compiler), "shader-stage", GUINT_TO_POINTER (stage_names[i].stage));
+ return TRUE;
+ }
+ }
+
+ str = g_string_new ("");
+ for (i = 0; i < G_N_ELEMENTS (stage_names); i++)
+ {
+ if (i > 0)
+ g_string_append (str, ", ");
+ g_string_append (str, stage_names[i].name);
+ }
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Unknown value given for shader stage. Valid options are: %s",
+ str->str);
+ g_string_free (str, TRUE);
+ return FALSE;
+}
+
int
main (int argc, char *argv[])
{
@@ -152,6 +200,7 @@ main (int argc, char *argv[])
{ "define", 'D', 0, G_OPTION_ARG_CALLBACK, define, "Add a preprocssor definition", "NAME[=VALUE]" },
{ "undef", 'U', 0, G_OPTION_ARG_CALLBACK, undefine, "Cancel previous preprocessor definition", "NAME" },
{ "print", 'p', 0, G_OPTION_ARG_NONE, &print, "Print instead of compiling", NULL },
+ { "stage", 's', 0, G_OPTION_ARG_CALLBACK, stage, "Set the shader stage", "STAGE" },
{ "output", 'o', 0, G_OPTION_ARG_FILENAME, &output_file, "Output filename", "FILE" },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, "List of input files", "FILE
[FILE...]" },
{ NULL, }
@@ -168,6 +217,7 @@ main (int argc, char *argv[])
gtk_init ();
compiler = gsk_sl_compiler_new ();
+ g_object_set_data (G_OBJECT (compiler), "shader-stage", GUINT_TO_POINTER (GSK_SL_SHADER_FRAGMENT));
ctx = g_option_context_new (NULL);
group = g_option_group_new (NULL, NULL, NULL, g_object_ref (compiler), g_object_unref);
g_option_group_add_entries (group, entries);
diff --git a/testsuite/gsksl/test-error.c b/testsuite/gsksl/test-error.c
index b957270..01b69e0 100644
--- a/testsuite/gsksl/test-error.c
+++ b/testsuite/gsksl/test-error.c
@@ -27,12 +27,34 @@
static GskSlCompiler *compiler;
+static GskSlShaderStage
+shader_stage_from_filename (GFile *file)
+{
+ GskSlShaderStage stage;
+ char *base;
+
+ base = g_file_get_basename (file);
+
+ if (g_str_has_suffix (base, ".vert"))
+ stage = GSK_SL_SHADER_VERTEX;
+ else if (g_str_has_suffix (base, ".frag"))
+ stage = GSK_SL_SHADER_FRAGMENT;
+ else
+ stage = GSK_SL_SHADER_FRAGMENT;
+
+ g_free (base);
+
+ return stage;
+}
+
static void
test_glsl_file (GFile *file)
{
GskSlProgram *program;
- program = gsk_sl_compiler_compile_file (compiler, file);
+ program = gsk_sl_compiler_compile_file (compiler,
+ shader_stage_from_filename (file),
+ file);
if (program != NULL)
{
g_object_unref (program);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]