[gtk+/wip/otte/shader: 6/26] gsksl: Parse interpolation qualifiers



commit d7ce3cdac79e172e4d56aef95caf2c37af2ac416
Author: Benjamin Otte <otte redhat com>
Date:   Tue Oct 17 03:42:53 2017 +0200

    gsksl: Parse interpolation qualifiers

 gsk/gskslqualifier.c                               |   75 +++++++++++++++++++-
 gsk/gskslqualifierprivate.h                        |    8 ++
 gsk/gskslstatement.c                               |    3 +
 .../errors/duplicate-interpolation-qualifier.frag  |    6 ++
 testsuite/gsksl/errors/int-qualifier.frag          |    6 ++
 5 files changed, 96 insertions(+), 2 deletions(-)
---
diff --git a/gsk/gskslqualifier.c b/gsk/gskslqualifier.c
index 7d7bc25..c859831 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 3eceb71..a21841b 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 c758df2..ca4708f 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 0000000..b942d2f
--- /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 0000000..cb56f2e
--- /dev/null
+++ b/testsuite/gsksl/errors/int-qualifier.frag
@@ -0,0 +1,6 @@
+in int i;
+
+void
+main ()
+{
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]