[gtk+/wip/otte/shader: 70/156] gsksl: Add support for parsing blocks



commit b01177a1cf10e04411d63fb811ca33b7d1c72b5c
Author: Benjamin Otte <otte redhat com>
Date:   Sun Oct 1 23:49:10 2017 +0200

    gsksl: Add support for parsing blocks

 gsk/gskslpointertype.c        |    9 -
 gsk/gskslpointertypeprivate.h |    3 -
 gsk/gsksltype.c               |  330 ++++++++++++++++++++++++++++++++++++++++-
 gsk/gsksltypeprivate.h        |    2 +
 gsk/gskslvariable.c           |   26 +++-
 gsk/gskspvwriterprivate.h     |   31 ++++-
 6 files changed, 384 insertions(+), 17 deletions(-)
---
diff --git a/gsk/gskslpointertype.c b/gsk/gskslpointertype.c
index e96c88a..380d4a8 100644
--- a/gsk/gskslpointertype.c
+++ b/gsk/gskslpointertype.c
@@ -76,15 +76,6 @@ gsk_sl_pointer_type_unref (GskSlPointerType *type)
   g_slice_free (GskSlPointerType, type);
 }
 
-void
-gsk_sl_pointer_type_print (const GskSlPointerType *type,
-                           GskSlPrinter           *printer)
-{
-  if (gsk_sl_qualifier_print (&type->qualifier, printer))
-    gsk_sl_printer_append (printer, " ");
-  gsk_sl_printer_append (printer, gsk_sl_type_get_name (type->type));
-}
-
 GskSlType *
 gsk_sl_pointer_type_get_type (const GskSlPointerType *type)
 {
diff --git a/gsk/gskslpointertypeprivate.h b/gsk/gskslpointertypeprivate.h
index 444089f..97042a9 100644
--- a/gsk/gskslpointertypeprivate.h
+++ b/gsk/gskslpointertypeprivate.h
@@ -32,9 +32,6 @@ GskSlPointerType *      gsk_sl_pointer_type_new                         (GskSlTy
 GskSlPointerType *      gsk_sl_pointer_type_ref                         (GskSlPointerType           *type);
 void                    gsk_sl_pointer_type_unref                       (GskSlPointerType           *type);
 
-void                    gsk_sl_pointer_type_print                       (const GskSlPointerType     *type,
-                                                                         GskSlPrinter               
*printer);
-
 GskSlType *             gsk_sl_pointer_type_get_type                    (const GskSlPointerType     *type);
 const GskSlQualifier *  gsk_sl_pointer_type_get_qualifier               (const GskSlPointerType     *type);
 
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index 1cfee8f..5496059 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -1210,6 +1210,201 @@ static const GskSlTypeClass GSK_SL_TYPE_STRUCT = {
   gsk_sl_type_struct_write_value_spv
 };
 
+/* BLOCK */
+
+typedef struct _GskSlTypeBlock GskSlTypeBlock;
+
+struct _GskSlTypeBlock {
+  GskSlType parent;
+
+  char *name;
+  gsize size;
+
+  GskSlTypeMember *members;
+  guint n_members;
+};
+
+static void
+gsk_sl_type_block_free (GskSlType *type)
+{
+  GskSlTypeBlock *block = (GskSlTypeBlock *) type;
+  guint i;
+
+  for (i = 0; i < block->n_members; i++)
+    {
+      gsk_sl_type_unref (block->members[i].type);
+      g_free (block->members[i].name);
+    }
+
+  g_free (block->members);
+  g_free (block->name);
+
+  g_slice_free (GskSlTypeBlock, block);
+}
+
+static const char *
+gsk_sl_type_block_get_name (const GskSlType *type)
+{
+  GskSlTypeBlock *block = (GskSlTypeBlock *) type;
+
+  return block->name;
+}
+
+static GskSlScalarType
+gsk_sl_type_block_get_scalar_type (const GskSlType *type)
+{
+  return GSK_SL_VOID;
+}
+
+static GskSlType *
+gsk_sl_type_block_get_index_type (const GskSlType *type)
+{
+  return NULL;
+}
+
+static gsize
+gsk_sl_type_block_get_index_stride (const GskSlType *type)
+{
+  return 0;
+}
+
+static guint
+gsk_sl_type_block_get_length (const GskSlType *type)
+{
+  return 0;
+}
+
+static gsize
+gsk_sl_type_block_get_size (const GskSlType *type)
+{
+  const GskSlTypeBlock *block = (const GskSlTypeBlock *) type;
+
+  return block->size;
+}
+
+static guint
+gsk_sl_type_block_get_n_members (const GskSlType *type)
+{
+  const GskSlTypeBlock *block = (const GskSlTypeBlock *) type;
+
+  return block->n_members;
+}
+
+static const GskSlTypeMember *
+gsk_sl_type_block_get_member (const GskSlType *type,
+                              guint            n)
+{
+  const GskSlTypeBlock *block = (const GskSlTypeBlock *) type;
+
+  return &block->members[n];
+}
+
+static gboolean
+gsk_sl_type_block_can_convert (const GskSlType *target,
+                               const GskSlType *source)
+{
+  return gsk_sl_type_equal (target, source);
+}
+
+static guint32
+gsk_sl_type_block_write_spv (GskSlType    *type,
+                             GskSpvWriter *writer)
+{
+  GskSlTypeBlock *block = (GskSlTypeBlock *) type;
+  guint32 ids[block->n_members + 1];
+  guint i;
+
+  ids[0] = gsk_spv_writer_next_id (writer);
+
+  for (i = 0; i < block->n_members; i++)
+    {
+      ids[i + 1] = gsk_spv_writer_get_id_for_type (writer, block->members[i].type);
+    }
+
+  gsk_spv_writer_add (writer,
+                      GSK_SPV_WRITER_SECTION_DEBUG,
+                      3, GSK_SPV_OP_DECORATE,
+                      (guint32[2]) { ids[0],
+                                     GSK_SPV_DECORATION_BLOCK });
+  
+  gsk_spv_writer_add (writer,
+                      GSK_SPV_WRITER_SECTION_DECLARE,
+                      2 + block->n_members, GSK_SPV_OP_TYPE_STRUCT,
+                      ids);
+  
+  return ids[0];
+}
+
+static void
+gsk_sl_type_block_print_value (const GskSlType *type,
+                               GskSlPrinter    *printer,
+                               gconstpointer    value)
+{
+  const GskSlTypeBlock *block = (const GskSlTypeBlock *) type;
+  guint i;
+
+  gsk_sl_printer_append (printer, block->name);
+  gsk_sl_printer_append (printer, "(");
+
+  for (i = 0; i < block->n_members; i++)
+    {
+      if (i > 0)
+        gsk_sl_printer_append (printer, ", ");
+      gsk_sl_type_print_value (block->members[i].type,
+                               printer,
+                               (guchar *) value + block->members[i].offset);
+    }
+
+  gsk_sl_printer_append (printer, ")");
+}
+
+static guint32
+gsk_sl_type_block_write_value_spv (GskSlType     *type,
+                                   GskSpvWriter  *writer,
+                                   gconstpointer  value)
+{
+  GskSlTypeBlock *block = (GskSlTypeBlock *) type;
+  guint32 ids[block->n_members + 2];
+  GskSlValue *v;
+  guint i;
+
+  ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
+  for (i = 0; i < block->n_members; i++)
+    {
+      v = gsk_sl_value_new_for_data (block->members[i].type,
+                                     (guchar *) value + block->members[i].offset,
+                                     NULL, NULL);
+      ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v);
+      gsk_sl_value_free (v);
+    }
+
+  ids[1] = gsk_spv_writer_next_id (writer);
+
+  gsk_spv_writer_add (writer,
+                      GSK_SPV_WRITER_SECTION_DECLARE,
+                      3 + block->n_members,
+                      GSK_SPV_OP_CONSTANT_COMPOSITE,
+                      ids);
+  
+  return ids[1];
+}
+
+static const GskSlTypeClass GSK_SL_TYPE_BLOCK = {
+  gsk_sl_type_block_free,
+  gsk_sl_type_block_get_name,
+  gsk_sl_type_block_get_scalar_type,
+  gsk_sl_type_block_get_index_type,
+  gsk_sl_type_block_get_index_stride,
+  gsk_sl_type_block_get_length,
+  gsk_sl_type_block_get_size,
+  gsk_sl_type_block_get_n_members,
+  gsk_sl_type_block_get_member,
+  gsk_sl_type_block_can_convert,
+  gsk_sl_type_block_write_spv,
+  gsk_sl_type_block_print_value,
+  gsk_sl_type_block_write_value_spv
+};
+
 /* API */
 
 static GskSlType *
@@ -1311,6 +1506,85 @@ out:
   return type;
 }
 
+static GskSlType *
+gsk_sl_type_parse_block (GskSlScope        *scope,
+                         GskSlPreprocessor *preproc)
+{
+  GskSlType *type;
+  const GskSlToken *token;
+  GskSlTypeBuilder *builder;
+
+  if (!gsk_sl_scope_is_global (scope))
+    {
+      gsk_sl_preprocessor_error (preproc, SYNTAX, "Blocks are only allowed in global scope.");
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
+    }
+
+  token = gsk_sl_preprocessor_get (preproc);
+  if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+    {    
+      builder = gsk_sl_type_builder_new_block (token->str);
+      gsk_sl_preprocessor_consume (preproc, NULL);
+    }
+  else
+    {
+      gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected block name.");
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
+    }
+
+  token = gsk_sl_preprocessor_get (preproc);
+  if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
+    {
+      gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected opening \"{\" after block declaration.");
+      goto out;
+    }
+  gsk_sl_preprocessor_consume (preproc, NULL);
+
+  for (token = gsk_sl_preprocessor_get (preproc);
+       !gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE) && !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
+       token = gsk_sl_preprocessor_get (preproc))
+    {
+      type = gsk_sl_type_new_parse (scope, preproc);
+
+      while (TRUE)
+        {
+          token = gsk_sl_preprocessor_get (preproc);
+          if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+            {
+              gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected identifier for type name.");
+              break;
+            }
+          if (gsk_sl_type_builder_has_member (builder, token->str))
+            gsk_sl_preprocessor_error (preproc, DECLARATION, "struct already has a member named \"%s\".", 
token->str);
+          else
+            gsk_sl_type_builder_add_member (builder, type, token->str);
+          gsk_sl_preprocessor_consume (preproc, NULL);
+
+          token = gsk_sl_preprocessor_get (preproc);
+          if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
+            break;
+
+          gsk_sl_preprocessor_consume (preproc, NULL);
+        }
+      gsk_sl_type_unref (type);
+
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
+        gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected semicolon after block member declaration.");
+      else
+        gsk_sl_preprocessor_consume (preproc, NULL);
+    }
+
+  if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE))
+    {
+      gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected closing \"}\" after block declaration.");
+      gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_BRACE);
+    }
+  gsk_sl_preprocessor_consume (preproc, NULL);
+  
+out:
+  return gsk_sl_type_builder_free (builder);
+}
+
 GskSlType *
 gsk_sl_type_get_builtin (GskSlBuiltinType builtin)
 {
@@ -1545,8 +1819,9 @@ gsk_sl_type_new_parse (GskSlScope        *scope,
             type = gsk_sl_type_ref (type);
             break;
           }
+  
+        return gsk_sl_type_parse_block (scope, preproc);
       }
-      /* fall through */
     default:
       gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected type specifier");
       return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
@@ -1736,6 +2011,12 @@ gsk_sl_type_is_struct (const GskSlType *type)
   return type->class == &GSK_SL_TYPE_STRUCT;
 }
 
+gboolean
+gsk_sl_type_is_block (const GskSlType *type)
+{
+  return type->class == &GSK_SL_TYPE_BLOCK;
+}
+
 GskSlScalarType
 gsk_sl_type_get_scalar_type (const GskSlType *type)
 {
@@ -1923,6 +2204,7 @@ struct _GskSlTypeBuilder {
   char *name;
   gsize size;
   GArray *members;
+  guint is_block :1;
 };
 
 GskSlTypeBuilder *
@@ -1938,6 +2220,22 @@ gsk_sl_type_builder_new_struct (const char *name)
   return builder;
 }
 
+GskSlTypeBuilder *
+gsk_sl_type_builder_new_block (const char *name)
+{
+  GskSlTypeBuilder *builder;
+
+  g_assert (name != NULL);
+
+  builder = g_slice_new0 (GskSlTypeBuilder);
+
+  builder->name = g_strdup (name);
+  builder->members = g_array_new (FALSE, FALSE, sizeof (GskSlTypeMember));
+  builder->is_block = TRUE;
+
+  return builder;
+}
+
 static char *
 gsk_sl_type_builder_generate_name (GskSlTypeBuilder *builder)
 {
@@ -1966,8 +2264,8 @@ gsk_sl_type_builder_generate_name (GskSlTypeBuilder *builder)
   return g_string_free (string, FALSE);
 }
 
-GskSlType *
-gsk_sl_type_builder_free (GskSlTypeBuilder *builder)
+static GskSlType *
+gsk_sl_type_builder_free_to_struct (GskSlTypeBuilder *builder)
 {
   GskSlTypeStruct *result;
 
@@ -1986,6 +2284,32 @@ gsk_sl_type_builder_free (GskSlTypeBuilder *builder)
   return &result->parent;
 }
 
+static GskSlType *
+gsk_sl_type_builder_free_to_block (GskSlTypeBuilder *builder)
+{
+  GskSlTypeBlock *result;
+
+  result = gsk_sl_type_new (GskSlTypeBlock, &GSK_SL_TYPE_BLOCK);
+
+  result->name = builder->name;
+  result->size = builder->size;
+  result->n_members = builder->members->len;
+  result->members = (GskSlTypeMember *) g_array_free (builder->members, FALSE);
+
+  g_slice_free (GskSlTypeBuilder, builder);
+
+  return &result->parent;
+}
+
+GskSlType *
+gsk_sl_type_builder_free (GskSlTypeBuilder *builder)
+{
+  if (builder->is_block)
+    return gsk_sl_type_builder_free_to_block (builder);
+  else
+    return gsk_sl_type_builder_free_to_struct (builder);
+}
+
 void
 gsk_sl_type_builder_add_member (GskSlTypeBuilder *builder,
                                 GskSlType        *type,
diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h
index 6e4f1f7..dcf1019 100644
--- a/gsk/gsksltypeprivate.h
+++ b/gsk/gsksltypeprivate.h
@@ -46,6 +46,7 @@ gboolean                gsk_sl_type_is_scalar                   (const GskSlType
 gboolean                gsk_sl_type_is_vector                   (const GskSlType     *type);
 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);
 
 const char *            gsk_sl_type_get_name                    (const GskSlType     *type);
 GskSlScalarType         gsk_sl_type_get_scalar_type             (const GskSlType     *type);
@@ -89,6 +90,7 @@ void                    gsk_sl_scalar_type_convert_value        (GskSlScalarType
                                                                  gconstpointer        source_value);
 
 GskSlTypeBuilder *      gsk_sl_type_builder_new_struct          (const char          *name);
+GskSlTypeBuilder *      gsk_sl_type_builder_new_block           (const char          *name);
 GskSlType *             gsk_sl_type_builder_free                (GskSlTypeBuilder    *builder);
 void                    gsk_sl_type_builder_add_member          (GskSlTypeBuilder    *builder,
                                                                  GskSlType           *type,
diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c
index fa7ca24..439aa80 100644
--- a/gsk/gskslvariable.c
+++ b/gsk/gskslvariable.c
@@ -85,7 +85,31 @@ void
 gsk_sl_variable_print (const GskSlVariable *variable,
                        GskSlPrinter        *printer)
 {
-  gsk_sl_pointer_type_print (variable->type, printer);
+  GskSlType *type;
+
+  if (gsk_sl_qualifier_print (gsk_sl_pointer_type_get_qualifier (variable->type), printer))
+    gsk_sl_printer_append (printer, " ");
+  type = gsk_sl_pointer_type_get_type (variable->type);
+  gsk_sl_printer_append (printer, gsk_sl_type_get_name (type));
+  if (gsk_sl_type_is_block (type))
+    {
+      guint i, n;
+
+      gsk_sl_printer_append (printer, " {");
+      gsk_sl_printer_push_indentation (printer);
+      n = gsk_sl_type_get_n_members (type);
+      for (i = 0; i < n; i++)
+        {
+          gsk_sl_printer_newline (printer);
+          gsk_sl_printer_append (printer, gsk_sl_type_get_name (gsk_sl_type_get_member_type (type, i)));
+          gsk_sl_printer_append (printer, " ");
+          gsk_sl_printer_append (printer, gsk_sl_type_get_member_name (type, i));
+          gsk_sl_printer_append (printer, ";");
+        }
+      gsk_sl_printer_pop_indentation (printer);
+      gsk_sl_printer_newline (printer);
+      gsk_sl_printer_append (printer, "}");
+    }
   if (variable->name)
     {
       gsk_sl_printer_append (printer, " ");
diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h
index 81b2af1..9a9aceb 100644
--- a/gsk/gskspvwriterprivate.h
+++ b/gsk/gskspvwriterprivate.h
@@ -95,6 +95,11 @@ typedef enum {
   GSK_SPV_OP_ARRAY_LENGTH = 68,
   GSK_SPV_OP_GENERIC_PTR_MEM_SEMANTICS = 69,
   GSK_SPV_OP_IN_BOUNDS_PTR_ACCESS_CHAIN = 70,
+  GSK_SPV_OP_DECORATE = 71,
+  GSK_SPV_OP_MEMBER_DECORATE = 72,
+  GSK_SPV_OP_DECORATION_GROUP = 73,
+  GSK_SPV_OP_GROUP_DECORATE = 74,
+  GSK_SPV_OP_GROUP_MEMBER_DECORATE = 75,
   GSK_SPV_OP_VECTOR_EXTRACT_DYNAMIC = 77,
   GSK_SPV_OP_VECTOR_INSERT_DYNAMIC = 78,
   GSK_SPV_OP_VECTOR_SHUFFLE = 79,
@@ -161,7 +166,8 @@ typedef enum {
   GSK_SPV_OP_LIFETIME_STOP = 257,
   GSK_SPV_OP_SIZE_OF = 321,
   GSK_SPV_OP_TYPE_PIPE_STORAGE = 322,
-  GSK_SPV_OP_TYPE_NAMED_BARRIER = 327
+  GSK_SPV_OP_TYPE_NAMED_BARRIER = 327,
+  GSK_SPV_OP_DECORATE_ID = 332
 } GskSpvOpcode;
 
 typedef enum {
@@ -212,6 +218,29 @@ typedef enum {
 } GskSpvStorageClass;
 
 typedef enum {
+  GSK_SPV_DECORATION_RELAXED_PRECISION = 0,
+  GSK_SPV_DECORATION_SPEC_ID = 1,
+  GSK_SPV_DECORATION_BLOCK = 2,
+  GSK_SPV_DECORATION_BUFFER_BLOCK = 3,
+  GSK_SPV_DECORATION_ROW_MAJOR = 4,
+  GSK_SPV_DECORATION_COLUMN_MAJOR = 5,
+  GSK_SPV_DECORATION_ARRAY_STRIDE = 6,
+  GSK_SPV_DECORATION_MATRIX_STRIDE = 7,
+  GSK_SPV_DECORATION_GLSL_SHARED = 8,
+  GSK_SPV_DECORATION_GLSL_PACKED = 9,
+  GSK_SPV_DECORATION_C_PACKED = 10,
+  GSK_SPV_DECORATION_BUILTIN = 11,
+  GSK_SPV_DECORATION_NO_PERSPECTIVE = 13,
+  GSK_SPV_DECORATION_FLAT = 14,
+  GSK_SPV_DECORATION_PATCH = 15,
+  GSK_SPV_DECORATION_CENTROID = 16,
+  GSK_SPV_DECORATION_SAMPLE = 17,
+  GSK_SPV_DECORATION_INVARIANT = 18,
+  GSK_SPV_DECORATION_RESTRICT = 19,
+  GSK_SPV_DECORATION_ALIASED = 20
+} GskSpvDecoration;
+
+typedef enum {
   GSK_SPV_WRITER_SECTION_HEADER,
   GSK_SPV_WRITER_SECTION_DEBUG,
   GSK_SPV_WRITER_SECTION_DECLARE,


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