summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2017-10-17 03:22:43 +0200
committerBenjamin Otte <otte@redhat.com>2017-10-30 02:58:03 +0100
commit5472458e6b14c9bf06ee42e4a2deccc2f2c840f8 (patch)
treef0bc9d16775b1f582861a9a50c5bb6f0d6269de9
parent8431b63b5d0fde9a66110579a4d70bb811342d53 (diff)
downloadgtk+-5472458e6b14c9bf06ee42e4a2deccc2f2c840f8.tar.gz
gsksl: Check qualifier/type combinations are valid
So far, this is only implemented for in variables.
-rw-r--r--gsk/gsksldeclaration.c2
-rw-r--r--gsk/gskslpreprocessorprivate.h2
-rw-r--r--gsk/gskslqualifier.c61
-rw-r--r--gsk/gskslqualifierprivate.h3
-rw-r--r--gsk/gsksltype.c6
-rw-r--r--gsk/gsksltypeprivate.h1
-rw-r--r--testsuite/gsksl/errors/no-bool-in-variables.frag6
-rw-r--r--testsuite/gsksl/errors/no-sampler-in-variables.frag6
-rw-r--r--testsuite/gsksl/errors/no-struct-in-variables-in-vertex-shader.vert6
9 files changed, 93 insertions, 0 deletions
diff --git a/gsk/gsksldeclaration.c b/gsk/gsksldeclaration.c
index 68948647f7..ca2edeae11 100644
--- a/gsk/gsksldeclaration.c
+++ b/gsk/gsksldeclaration.c
@@ -226,6 +226,8 @@ gsk_sl_declaration_parse_variable (GskSlScope *scope,
GskSlExpression *initial = NULL;
const GskSlToken *token;
+ gsk_sl_qualifier_check_type (qualifier, preproc, type);
+
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_EQUAL))
{
diff --git a/gsk/gskslpreprocessorprivate.h b/gsk/gskslpreprocessorprivate.h
index 29def725c8..f8d13010dd 100644
--- a/gsk/gskslpreprocessorprivate.h
+++ b/gsk/gskslpreprocessorprivate.h
@@ -20,6 +20,7 @@
#define __GSK_SL_PREPROCESSOR_PRIVATE_H__
#include "gskslcompilerprivate.h"
+#include "gskslenvironmentprivate.h"
#include "gsksltypesprivate.h"
#include "gsksltokenizerprivate.h"
@@ -38,6 +39,7 @@ const GskSlToken * gsk_sl_preprocessor_get (GskSlPreprocess
const GskCodeLocation * gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc);
void gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
gpointer consumer);
+#define gsk_sl_preprocessor_is_stage(preproc,stage) (gsk_sl_environment_get_stage (gsk_sl_preprocessor_get_environment (preproc)) == (stage))
void gsk_sl_preprocessor_sync (GskSlPreprocessor *preproc,
GskSlTokenType token);
diff --git a/gsk/gskslqualifier.c b/gsk/gskslqualifier.c
index 049242acf4..7d7bc25a38 100644
--- a/gsk/gskslqualifier.c
+++ b/gsk/gskslqualifier.c
@@ -577,6 +577,67 @@ gsk_sl_qualifier_get_storage_class (const GskSlQualifier *qualifier)
}
}
+#define ERROR(...) G_STMT_START{\
+ gsk_sl_preprocessor_error (preproc, DECLARATION, __VA_ARGS__); \
+ result = FALSE; \
+}G_STMT_END
+
+static gboolean
+gsk_sl_qualifier_check_type_for_input (const GskSlQualifier *qualifier,
+ GskSlPreprocessor *preproc,
+ GskSlType *type)
+{
+ gboolean result = TRUE;
+ gsize i;
+
+ if (gsk_sl_type_is_struct (type) && gsk_sl_preprocessor_is_stage (preproc, GSK_SL_SHADER_VERTEX))
+ ERROR ("In variables in vertex shaders must not contain structs");
+ if (gsk_sl_type_is_opaque (type))
+ ERROR ("In variables must not contain opaque types");
+ if (gsk_sl_type_get_scalar_type (type) == GSK_SL_BOOL)
+ ERROR ("In variables must not contain boolean types");
+
+ for (i = 0; i < gsk_sl_type_get_n_members (type); i++)
+ {
+ result &= gsk_sl_qualifier_check_type_for_input (qualifier,
+ preproc,
+ gsk_sl_type_get_member_type (type, i));
+ }
+
+ return result;
+}
+
+gboolean
+gsk_sl_qualifier_check_type (const GskSlQualifier *qualifier,
+ GskSlPreprocessor *preproc,
+ GskSlType *type)
+{
+ switch (qualifier->storage)
+ {
+ case GSK_SL_STORAGE_DEFAULT:
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+
+ case GSK_SL_STORAGE_GLOBAL:
+ case GSK_SL_STORAGE_GLOBAL_CONST:
+ return TRUE;
+
+ case GSK_SL_STORAGE_GLOBAL_IN:
+ return gsk_sl_qualifier_check_type_for_input (qualifier, preproc, type);
+
+ case GSK_SL_STORAGE_GLOBAL_OUT:
+ case GSK_SL_STORAGE_GLOBAL_UNIFORM:
+ case GSK_SL_STORAGE_LOCAL:
+ case GSK_SL_STORAGE_LOCAL_CONST:
+ case GSK_SL_STORAGE_PARAMETER_IN:
+ case GSK_SL_STORAGE_PARAMETER_OUT:
+ case GSK_SL_STORAGE_PARAMETER_INOUT:
+ case GSK_SL_STORAGE_PARAMETER_CONST:
+ return TRUE;
+ }
+}
+
static void
gsk_sl_qualifier_write_inout_decorations (const GskSlQualifier *qualifier,
GskSpvWriter *writer,
diff --git a/gsk/gskslqualifierprivate.h b/gsk/gskslqualifierprivate.h
index 12e9e413cf..3eceb712ce 100644
--- a/gsk/gskslqualifierprivate.h
+++ b/gsk/gskslqualifierprivate.h
@@ -66,6 +66,9 @@ gboolean gsk_sl_qualifier_is_constant (const G
GskSlQualifierLocation gsk_sl_qualifier_get_location (const GskSlQualifier *qualifier);
GskSpvStorageClass gsk_sl_qualifier_get_storage_class (const GskSlQualifier *qualifier);
+gboolean gsk_sl_qualifier_check_type (const GskSlQualifier *qualifier,
+ GskSlPreprocessor *preproc,
+ GskSlType *type);
void gsk_sl_qualifier_write_spv_decorations (const GskSlQualifier *qualifier,
GskSpvWriter *writer,
guint32 value_id);
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index e513c05f85..c4050de4d1 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -2068,6 +2068,12 @@ gsk_sl_type_is_block (const GskSlType *type)
return type->class == &GSK_SL_TYPE_BLOCK;
}
+gboolean
+gsk_sl_type_is_opaque (const GskSlType *type)
+{
+ return FALSE;
+}
+
GskSlScalarType
gsk_sl_type_get_scalar_type (const GskSlType *type)
{
diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h
index 5c5d765eb4..55b6956d5d 100644
--- a/gsk/gsksltypeprivate.h
+++ b/gsk/gsksltypeprivate.h
@@ -50,6 +50,7 @@ gboolean gsk_sl_type_is_vector (const GskSlType
gboolean gsk_sl_type_is_matrix (const GskSlType *type);
gboolean gsk_sl_type_is_struct (const GskSlType *type);
gboolean gsk_sl_type_is_block (const GskSlType *type);
+gboolean gsk_sl_type_is_opaque (const GskSlType *type);
const char * gsk_sl_type_get_name (const GskSlType *type);
GskSlScalarType gsk_sl_type_get_scalar_type (const GskSlType *type);
diff --git a/testsuite/gsksl/errors/no-bool-in-variables.frag b/testsuite/gsksl/errors/no-bool-in-variables.frag
new file mode 100644
index 0000000000..47e1be8242
--- /dev/null
+++ b/testsuite/gsksl/errors/no-bool-in-variables.frag
@@ -0,0 +1,6 @@
+in bool b;
+
+void
+main ()
+{
+}
diff --git a/testsuite/gsksl/errors/no-sampler-in-variables.frag b/testsuite/gsksl/errors/no-sampler-in-variables.frag
new file mode 100644
index 0000000000..61539380b2
--- /dev/null
+++ b/testsuite/gsksl/errors/no-sampler-in-variables.frag
@@ -0,0 +1,6 @@
+in sampler2D t;
+
+void
+main ()
+{
+}
diff --git a/testsuite/gsksl/errors/no-struct-in-variables-in-vertex-shader.vert b/testsuite/gsksl/errors/no-struct-in-variables-in-vertex-shader.vert
new file mode 100644
index 0000000000..b535e1bee5
--- /dev/null
+++ b/testsuite/gsksl/errors/no-struct-in-variables-in-vertex-shader.vert
@@ -0,0 +1,6 @@
+in struct {int x; int y; } s;
+
+void
+main ()
+{
+}