From 41fd67263f17887d9cf89550dc21032104697fbe Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 17 Oct 2017 03:42:53 +0200 Subject: [PATCH] gsksl: Parse interpolation qualifiers --- gsk/gskslqualifier.c | 75 ++++++++++++++++++- gsk/gskslqualifierprivate.h | 8 ++ gsk/gskslstatement.c | 3 + .../duplicate-interpolation-qualifier.frag | 6 ++ testsuite/gsksl/errors/int-qualifier.frag | 6 ++ 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 testsuite/gsksl/errors/duplicate-interpolation-qualifier.frag create mode 100644 testsuite/gsksl/errors/int-qualifier.frag diff --git a/gsk/gskslqualifier.c b/gsk/gskslqualifier.c index 7d7bc25a38..c859831649 100644 --- a/gsk/gskslqualifier.c +++ b/gsk/gskslqualifier.c @@ -169,6 +169,24 @@ gsk_sl_storage_get_name (GskSlStorage storage) } } +static const char * +gsk_sl_interpolation_get_name (GskSlInterpolation interp) +{ + switch (interp) + { + default: + g_assert_not_reached (); + case GSK_SL_INTERPOLATE_DEFAULT: + return ""; + case GSK_SL_INTERPOLATE_SMOOTH: + return "smooth"; + case GSK_SL_INTERPOLATE_FLAT: + return "flat"; + case GSK_SL_INTERPOLATE_NO_PERSPECTIVE: + return "noperspective"; + } +} + static gboolean gsk_sl_storage_allows_const (GskSlStorage storage) { @@ -283,6 +301,36 @@ gsk_sl_qualifier_parse (GskSlQualifier *qualifier, gsk_sl_preprocessor_consume (preproc, NULL); break; + case GSK_SL_TOKEN_SMOOTH: + if (qualifier->interpolation != GSK_SL_INTERPOLATE_DEFAULT) + gsk_sl_preprocessor_error (preproc, SYNTAX, + "Duplicate interpolation qualifiers: \"%s\" and \"smooth\".", + gsk_sl_interpolation_get_name (qualifier->interpolation)); + else + qualifier->interpolation = GSK_SL_INTERPOLATE_SMOOTH; + gsk_sl_preprocessor_consume (preproc, NULL); + break; + + case GSK_SL_TOKEN_FLAT: + if (qualifier->interpolation != GSK_SL_INTERPOLATE_DEFAULT) + gsk_sl_preprocessor_error (preproc, SYNTAX, + "Duplicate interpolation qualifiers: \"%s\" and \"flat\".", + gsk_sl_interpolation_get_name (qualifier->interpolation)); + else + qualifier->interpolation = GSK_SL_INTERPOLATE_FLAT; + gsk_sl_preprocessor_consume (preproc, NULL); + break; + + case GSK_SL_TOKEN_NOPERSPECTIVE: + if (qualifier->interpolation != GSK_SL_INTERPOLATE_DEFAULT) + gsk_sl_preprocessor_error (preproc, SYNTAX, + "Duplicate interpolation qualifiers: \"%s\" and \"noperspective\".", + gsk_sl_interpolation_get_name (qualifier->interpolation)); + else + qualifier->interpolation = GSK_SL_INTERPOLATE_NO_PERSPECTIVE; + gsk_sl_preprocessor_consume (preproc, NULL); + break; + case GSK_SL_TOKEN_INVARIANT: if (qualifier->invariant) gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"invariant\" qualifier."); @@ -480,6 +528,7 @@ gsk_sl_qualifier_print (const GskSlQualifier *qualifier, need_space = TRUE; } + need_space = append_with_space (printer, gsk_sl_interpolation_get_name (qualifier->interpolation), need_space); need_space = append_with_space (printer, gsk_sl_storage_get_name (qualifier->storage), need_space); return need_space; @@ -590,12 +639,18 @@ gsk_sl_qualifier_check_type_for_input (const GskSlQualifier *qualifier, gboolean result = TRUE; gsize i; - if (gsk_sl_type_is_struct (type) && gsk_sl_preprocessor_is_stage (preproc, GSK_SL_SHADER_VERTEX)) + 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)) + if (gsk_sl_type_is_opaque (type) && + gsk_sl_preprocessor_is_stage (preproc, GSK_SL_SHADER_VERTEX)) 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"); + if (gsk_sl_type_get_scalar_type (type) != GSK_SL_FLOAT && + gsk_sl_preprocessor_is_stage (preproc, GSK_SL_SHADER_FRAGMENT) && + qualifier->interpolation != GSK_SL_INTERPOLATE_FLAT) + ERROR ("Non-float in variables in fragment shader must be qualified as \"flat\"."); for (i = 0; i < gsk_sl_type_get_n_members (type); i++) { @@ -643,6 +698,22 @@ gsk_sl_qualifier_write_inout_decorations (const GskSlQualifier *qualifier, GskSpvWriter *writer, guint32 value_id) { + switch (qualifier->interpolation) + { + case GSK_SL_INTERPOLATE_FLAT: + gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_FLAT, NULL, 0); + break; + + case GSK_SL_INTERPOLATE_NO_PERSPECTIVE: + gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_NO_PERSPECTIVE, NULL, 0); + break; + + case GSK_SL_INTERPOLATE_DEFAULT: + case GSK_SL_INTERPOLATE_SMOOTH: + default: + break; + } + if (qualifier->layout.set >= 0) gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_LOCATION, (guint32[1]) { qualifier->layout.set }, 1); if (qualifier->layout.binding >= 0) diff --git a/gsk/gskslqualifierprivate.h b/gsk/gskslqualifierprivate.h index 3eceb712ce..a21841b858 100644 --- a/gsk/gskslqualifierprivate.h +++ b/gsk/gskslqualifierprivate.h @@ -33,9 +33,17 @@ typedef enum { GSK_SL_QUALIFIER_LOCAL } GskSlQualifierLocation; +typedef enum { + GSK_SL_INTERPOLATE_DEFAULT, + GSK_SL_INTERPOLATE_SMOOTH, + GSK_SL_INTERPOLATE_FLAT, + GSK_SL_INTERPOLATE_NO_PERSPECTIVE +} GskSlInterpolation; + struct _GskSlQualifier { GskSlStorage storage; + GskSlInterpolation interpolation; struct { gint set; diff --git a/gsk/gskslstatement.c b/gsk/gskslstatement.c index c758df22d7..ca4708ff88 100644 --- a/gsk/gskslstatement.c +++ b/gsk/gskslstatement.c @@ -704,6 +704,9 @@ gsk_sl_statement_parse (GskSlScope *scope, case GSK_SL_TOKEN_RESTRICT: case GSK_SL_TOKEN_READONLY: case GSK_SL_TOKEN_WRITEONLY: + case GSK_SL_TOKEN_SMOOTH: + case GSK_SL_TOKEN_FLAT: + case GSK_SL_TOKEN_NOPERSPECTIVE: case GSK_SL_TOKEN_VOID: case GSK_SL_TOKEN_FLOAT: case GSK_SL_TOKEN_DOUBLE: diff --git a/testsuite/gsksl/errors/duplicate-interpolation-qualifier.frag b/testsuite/gsksl/errors/duplicate-interpolation-qualifier.frag new file mode 100644 index 0000000000..b942d2fcaf --- /dev/null +++ b/testsuite/gsksl/errors/duplicate-interpolation-qualifier.frag @@ -0,0 +1,6 @@ +in flat noperspective int i; + +void +main () +{ +} diff --git a/testsuite/gsksl/errors/int-qualifier.frag b/testsuite/gsksl/errors/int-qualifier.frag new file mode 100644 index 0000000000..cb56f2e6dc --- /dev/null +++ b/testsuite/gsksl/errors/int-qualifier.frag @@ -0,0 +1,6 @@ +in int i; + +void +main () +{ +}