[gtk+/wip/otte/shader: 46/156] gsksl: Add support for parsing members of struct variables



commit e32c74818a93f59744e04316c042d5a0a41ceeb1
Author: Benjamin Otte <otte redhat com>
Date:   Thu Sep 28 03:38:56 2017 +0200

    gsksl: Add support for parsing members of struct variables
    
    This includes adding the concept of members to GskSlType.

 gsk/gskslexpression.c   |  100 ++++++++++++++++++++++++
 gsk/gsksltype.c         |  198 +++++++++++++++++++++++++++++++++++++++--------
 gsk/gsksltypeprivate.h  |   12 +++
 gsk/gskslvalue.c        |   12 +++
 gsk/gskslvalueprivate.h |    2 +
 5 files changed, 293 insertions(+), 31 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index b8f23f0..9ea7cdb 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -794,6 +794,95 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = {
   gsk_sl_expression_function_call_write_spv
 };
 
+/* MEMBER */
+
+typedef struct _GskSlExpressionMember GskSlExpressionMember;
+
+struct _GskSlExpressionMember {
+  GskSlExpression parent;
+
+  GskSlExpression *expr;
+  guint id;
+};
+
+static void
+gsk_sl_expression_member_free (GskSlExpression *expression)
+{
+  GskSlExpressionMember *member = (GskSlExpressionMember *) expression;
+
+  gsk_sl_expression_unref (member->expr);
+
+  g_slice_free (GskSlExpressionMember, member);
+}
+
+static void
+gsk_sl_expression_member_print (const GskSlExpression *expression,
+                                GString               *string)
+{
+  const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
+
+  gsk_sl_expression_print (member->expr, string);
+  g_string_append (string, ".");
+  g_string_append (string, gsk_sl_type_get_member_name (gsk_sl_expression_get_return_type (member->expr), 
member->id));
+}
+
+static GskSlType *
+gsk_sl_expression_member_get_return_type (const GskSlExpression *expression)
+{
+  const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
+
+  return gsk_sl_type_get_member_type (gsk_sl_expression_get_return_type (member->expr), member->id);
+}
+
+static GskSlValue *
+gsk_sl_expression_member_get_constant (const GskSlExpression *expression)
+{
+  const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
+  GskSlValue *result, *value;
+
+  value = gsk_sl_expression_get_constant (member->expr);
+  if (value == NULL)
+    return NULL;
+
+  result = gsk_sl_value_new_member (value, member->id);
+
+  gsk_sl_value_free (value);
+
+  return result;
+}
+
+static guint32
+gsk_sl_expression_member_write_spv (const GskSlExpression *expression,
+                                    GskSpvWriter          *writer)
+{
+  const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
+  GskSlType *type;
+  guint32 expr_id, type_id, result_id;
+
+  type = gsk_sl_expression_get_return_type (member->expr);
+  type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_member_type (type, member->id));
+  expr_id = gsk_sl_expression_write_spv (member->expr, writer);
+  result_id = gsk_spv_writer_next_id (writer);
+
+  gsk_spv_writer_add (writer,
+                      GSK_SPV_WRITER_SECTION_CODE,
+                      5, GSK_SPV_OP_ACCESS_CHAIN,
+                      (guint32[4]) { type_id,
+                                     result_id,
+                                     expr_id,
+                                     member->id });
+
+  return result_id;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_MEMBER = {
+  gsk_sl_expression_member_free,
+  gsk_sl_expression_member_print,
+  gsk_sl_expression_member_get_return_type,
+  gsk_sl_expression_member_get_constant,
+  gsk_sl_expression_member_write_spv
+};
+
 /* SWIZZLE */
 
 typedef enum {
@@ -1268,6 +1357,7 @@ gsk_sl_expression_parse_field_selection (GskSlScope        *scope,
                                          const char        *name)
 {
   GskSlType *type;
+  guint n;
 
   if (g_str_equal (name, "length"))
     {
@@ -1327,6 +1417,16 @@ gsk_sl_expression_parse_field_selection (GskSlScope        *scope,
   
       return (GskSlExpression *) swizzle;
     }
+  else if (gsk_sl_type_find_member (type, name, &n, NULL, NULL))
+    {
+      GskSlExpressionMember *member;
+      
+      member = gsk_sl_expression_new (GskSlExpressionMember, &GSK_SL_EXPRESSION_MEMBER);
+      member->expr = expr;
+      member->id = n;
+  
+      return (GskSlExpression *) member;
+    }
   else
     {
       gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Type %s has no fields to select.", 
gsk_sl_type_get_name (type));
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index 1f1d7b0..18c30ba 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -31,8 +31,16 @@
 
 #define N_SCALAR_TYPES 6
 
+typedef struct _GskSlTypeMember GskSlTypeMember;
 typedef struct _GskSlTypeClass GskSlTypeClass;
 
+struct _GskSlTypeMember {
+  GskSlType *type;
+  char *name;
+  gsize offset;
+};
+
+
 struct _GskSlType
 {
   const GskSlTypeClass *class;
@@ -42,13 +50,15 @@ struct _GskSlType
 
 struct _GskSlTypeClass {
   void                  (* free)                                (GskSlType           *type);
-
   const char *          (* get_name)                            (const GskSlType     *type);
   GskSlScalarType       (* get_scalar_type)                     (const GskSlType     *type);
   GskSlType *           (* get_index_type)                      (const GskSlType     *type);
   gsize                 (* get_index_stride)                    (const GskSlType     *type);
   guint                 (* get_length)                          (const GskSlType     *type);
   gsize                 (* get_size)                            (const GskSlType     *type);
+  guint                 (* get_n_members)                       (const GskSlType     *type);
+  const GskSlTypeMember * (* get_member)                        (const GskSlType     *type,
+                                                                 guint                i);
   gboolean              (* can_convert)                         (const GskSlType     *target,
                                                                  const GskSlType     *source);
   guint32               (* write_spv)                           (GskSlType           *type,
@@ -387,6 +397,19 @@ gsk_sl_type_scalar_get_size (const GskSlType *type)
   return scalar_infos[scalar->scalar].size;
 }
 
+static guint
+gsk_sl_type_scalar_get_n_members (const GskSlType *type)
+{
+  return 0;
+}
+
+static const GskSlTypeMember *
+gsk_sl_type_scalar_get_member (const GskSlType *type,
+                               guint            n)
+{
+  return NULL;
+}
+
 static gboolean
 gsk_sl_type_scalar_can_convert (const GskSlType *target,
                                 const GskSlType *source)
@@ -499,6 +522,8 @@ static const GskSlTypeClass GSK_SL_TYPE_SCALAR = {
   gsk_sl_type_scalar_get_index_stride,
   gsk_sl_type_scalar_get_length,
   gsk_sl_type_scalar_get_size,
+  gsk_sl_type_scalar_get_n_members,
+  gsk_sl_type_scalar_get_member,
   gsk_sl_type_scalar_can_convert,
   gsk_sl_type_scalar_write_spv,
   gsk_sl_type_scalar_print_value,
@@ -571,6 +596,19 @@ gsk_sl_type_vector_get_size (const GskSlType *type)
   return vector->length * scalar_infos[vector->scalar].size;
 }
 
+static guint
+gsk_sl_type_vector_get_n_members (const GskSlType *type)
+{
+  return 0;
+}
+
+static const GskSlTypeMember *
+gsk_sl_type_vector_get_member (const GskSlType *type,
+                               guint            n)
+{
+  return NULL;
+}
+
 static gboolean
 gsk_sl_type_vector_can_convert (const GskSlType *target,
                                 const GskSlType *source)
@@ -672,6 +710,8 @@ static const GskSlTypeClass GSK_SL_TYPE_VECTOR = {
   gsk_sl_type_vector_get_index_stride,
   gsk_sl_type_vector_get_length,
   gsk_sl_type_vector_get_size,
+  gsk_sl_type_vector_get_n_members,
+  gsk_sl_type_vector_get_member,
   gsk_sl_type_vector_can_convert,
   gsk_sl_type_vector_write_spv,
   gsk_sl_type_vector_print_value,
@@ -745,6 +785,19 @@ gsk_sl_type_matrix_get_size (const GskSlType *type)
   return matrix->columns * matrix->rows * scalar_infos[matrix->scalar].size;
 }
 
+static guint
+gsk_sl_type_matrix_get_n_members (const GskSlType *type)
+{
+  return 0;
+}
+
+static const GskSlTypeMember *
+gsk_sl_type_matrix_get_member (const GskSlType *type,
+                               guint            n)
+{
+  return NULL;
+}
+
 static gboolean
 gsk_sl_type_matrix_can_convert (const GskSlType *target,
                                 const GskSlType *source)
@@ -847,6 +900,8 @@ static const GskSlTypeClass GSK_SL_TYPE_MATRIX = {
   gsk_sl_type_matrix_get_index_stride,
   gsk_sl_type_matrix_get_length,
   gsk_sl_type_matrix_get_size,
+  gsk_sl_type_matrix_get_n_members,
+  gsk_sl_type_matrix_get_member,
   gsk_sl_type_matrix_can_convert,
   gsk_sl_type_matrix_write_spv,
   gsk_sl_type_matrix_print_value,
@@ -855,15 +910,8 @@ static const GskSlTypeClass GSK_SL_TYPE_MATRIX = {
 
 /* STRUCT */
 
-typedef struct _GskSlTypeMember GskSlTypeMember;
 typedef struct _GskSlTypeStruct GskSlTypeStruct;
 
-struct _GskSlTypeMember {
-  GskSlType *type;
-  char *name;
-  gsize offset;
-};
-
 struct _GskSlTypeStruct {
   GskSlType parent;
 
@@ -893,55 +941,72 @@ gsk_sl_type_struct_free (GskSlType *type)
 }
 
 static const char *
-gsk_sl_type_struct_get_name (GskSlType *type)
+gsk_sl_type_struct_get_name (const GskSlType *type)
 {
-  GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
+  const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
 
   return struc->name;
 }
 
 static GskSlScalarType
-gsk_sl_type_struct_get_scalar_type (GskSlType *type)
+gsk_sl_type_struct_get_scalar_type (const GskSlType *type)
 {
   return GSK_SL_VOID;
 }
 
 static GskSlType *
-gsk_sl_type_struct_get_index_type (GskSlType *type)
+gsk_sl_type_struct_get_index_type (const GskSlType *type)
 {
   return NULL;
 }
 
 static gsize
-gsk_sl_type_struct_get_index_stride (GskSlType *type)
+gsk_sl_type_struct_get_index_stride (const GskSlType *type)
 {
   return 0;
 }
 
 static guint
-gsk_sl_type_struct_get_length (GskSlType *type)
+gsk_sl_type_struct_get_length (const GskSlType *type)
 {
   return 0;
 }
 
 static gsize
-gsk_sl_type_struct_get_size (GskSlType *type)
+gsk_sl_type_struct_get_size (const GskSlType *type)
 {
-  GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
+  const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
 
   return struc->size;
 }
 
+static guint
+gsk_sl_type_struct_get_n_members (const GskSlType *type)
+{
+  const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
+
+  return struc->n_members;
+}
+
+static const GskSlTypeMember *
+gsk_sl_type_struct_get_member (const GskSlType *type,
+                               guint            n)
+{
+  const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
+
+  return &struc->members[n];
+}
+
 static gboolean
-gsk_sl_type_struct_can_convert (GskSlType *target,
-                                GskSlType *source)
+gsk_sl_type_struct_can_convert (const GskSlType *target,
+                                const GskSlType *source)
 {
   return gsk_sl_type_equal (target, source);
 }
 
 static guint32
-gsk_sl_type_struct_write_spv (const GskSlType *type,
-                              GskSpvWriter    *writer)
+gsk_sl_type_struct_write_spv (GskSlType    *type,
+                              GskSpvWriter *writer)
 {
   GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
   guint32 ids[struc->n_members + 1];
@@ -965,9 +1030,9 @@ gsk_sl_type_struct_write_spv (const GskSlType *type,
 static void
 gsk_sl_type_struct_print_value (const GskSlType *type,
                                 GString         *string,
-                                gpointer         value)
+                                gconstpointer    value)
 {
-  GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
+  const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
   guint i;
 
   g_string_append (string, struc->name);
@@ -986,20 +1051,15 @@ gsk_sl_type_struct_print_value (const GskSlType *type,
 }
 
 static guint32
-gsk_sl_type_struct_write_value_spv (GskSlType    *type,
-                                    GskSpvWriter *writer,
-                                    gpointer      value)
+gsk_sl_type_struct_write_value_spv (GskSlType     *type,
+                                    GskSpvWriter  *writer,
+                                    gconstpointer  value)
 {
   GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
   guint32 ids[struc->n_members + 2];
-  GskSlType *vector_type;
   GskSlValue *v;
-  guchar *data;
   guint i;
 
-  data = value;
-  vector_type = gsk_sl_type_get_index_type (type);
-
   ids[0] = gsk_spv_writer_get_id_for_type (writer, type);
   for (i = 0; i < struc->n_members; i++)
     {
@@ -1008,7 +1068,6 @@ gsk_sl_type_struct_write_value_spv (GskSlType    *type,
                                      NULL, NULL);
       ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v);
       gsk_sl_value_free (v);
-      data += gsk_sl_type_get_size (vector_type);
     }
 
   ids[1] = gsk_spv_writer_next_id (writer);
@@ -1030,6 +1089,8 @@ static const GskSlTypeClass GSK_SL_TYPE_STRUCT = {
   gsk_sl_type_struct_get_index_stride,
   gsk_sl_type_struct_get_length,
   gsk_sl_type_struct_get_size,
+  gsk_sl_type_struct_get_n_members,
+  gsk_sl_type_struct_get_member,
   gsk_sl_type_struct_can_convert,
   gsk_sl_type_struct_write_spv,
   gsk_sl_type_struct_print_value,
@@ -1482,6 +1543,81 @@ gsk_sl_type_get_size (const GskSlType *type)
   return type->class->get_size (type);
 }
 
+guint
+gsk_sl_type_get_n_members (const GskSlType *type)
+{
+  return type->class->get_n_members (type);
+}
+
+static const GskSlTypeMember *
+gsk_sl_type_get_member (const GskSlType *type,
+                        guint            n)
+{
+  return type->class->get_member (type, n);
+}
+
+GskSlType *
+gsk_sl_type_get_member_type (const GskSlType *type,
+                             guint            n)
+{
+  const GskSlTypeMember *member;
+
+  member = gsk_sl_type_get_member (type, n);
+
+  return member->type;
+}
+
+const char *
+gsk_sl_type_get_member_name (const GskSlType *type,
+                             guint            n)
+{
+  const GskSlTypeMember *member;
+
+  member = gsk_sl_type_get_member (type, n);
+
+  return member->name;
+}
+
+gsize
+gsk_sl_type_get_member_offset (const GskSlType *type,
+                               guint            n)
+{
+  const GskSlTypeMember *member;
+
+  member = gsk_sl_type_get_member (type, n);
+
+  return member->offset;
+}
+
+gboolean
+gsk_sl_type_find_member (const GskSlType *type,
+                         const char      *name,
+                         guint           *out_index,
+                         GskSlType      **out_type,
+                         gsize           *out_offset)
+{
+  const GskSlTypeMember *member;
+  guint i, n;
+  
+  n = gsk_sl_type_get_n_members (type);
+  for (i = 0; i < n; i++)
+    {
+      member = gsk_sl_type_get_member (type, i);
+      if (g_str_equal (member->name, name))
+        {
+          if (out_index)
+            *out_index = i;
+          if (out_type)
+            *out_type = member->type;
+          if (out_offset)
+            *out_offset = member->offset;
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 gboolean
 gsk_sl_scalar_type_can_convert (GskSlScalarType target,
                                 GskSlScalarType source)
diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h
index c07d8d6..592d524 100644
--- a/gsk/gsksltypeprivate.h
+++ b/gsk/gsksltypeprivate.h
@@ -59,6 +59,18 @@ GskSlType *             gsk_sl_type_get_index_type              (const GskSlType
 gsize                   gsk_sl_type_get_index_stride            (const GskSlType     *type);
 guint                   gsk_sl_type_get_length                  (const GskSlType     *type);
 gsize                   gsk_sl_type_get_size                    (const GskSlType     *type);
+guint                   gsk_sl_type_get_n_members               (const GskSlType     *type);
+GskSlType *             gsk_sl_type_get_member_type             (const GskSlType     *type,
+                                                                 guint                n);
+const char *            gsk_sl_type_get_member_name             (const GskSlType     *type,
+                                                                 guint                n);
+gsize                   gsk_sl_type_get_member_offset           (const GskSlType     *type,
+                                                                 guint                n);
+gboolean                gsk_sl_type_find_member                 (const GskSlType     *type,
+                                                                 const char          *name,
+                                                                 guint               *out_index,
+                                                                 GskSlType          **out_type,
+                                                                 gsize               *out_offset);
 gboolean                gsk_sl_scalar_type_can_convert          (GskSlScalarType      target,
                                                                  GskSlScalarType      source);
 gboolean                gsk_sl_type_can_convert                 (const GskSlType     *target,
diff --git a/gsk/gskslvalue.c b/gsk/gskslvalue.c
index 4049730..6972ff7 100644
--- a/gsk/gskslvalue.c
+++ b/gsk/gskslvalue.c
@@ -159,6 +159,18 @@ gsk_sl_value_new_convert (GskSlValue *source,
 }
 
 GskSlValue *
+gsk_sl_value_new_member (GskSlValue *value,
+                         guint       n)
+{
+  gpointer data;
+
+  data = g_memdup ((guchar *) value->data + gsk_sl_type_get_member_offset (value->type, n),
+                   gsk_sl_type_get_size (gsk_sl_type_get_member_type (value->type, n)));
+
+  return gsk_sl_value_new_for_data (value->type, data, g_free, data);
+}
+
+GskSlValue *
 gsk_sl_value_copy (const GskSlValue *source)
 {
   gpointer data;
diff --git a/gsk/gskslvalueprivate.h b/gsk/gskslvalueprivate.h
index afd81b5..c4e7c59 100644
--- a/gsk/gskslvalueprivate.h
+++ b/gsk/gskslvalueprivate.h
@@ -30,6 +30,8 @@ GskSlValue *            gsk_sl_value_new_for_data               (GskSlType
                                                                  gpointer             user_data);
 GskSlValue *            gsk_sl_value_new_convert                (GskSlValue          *source,
                                                                  GskSlType           *new_type);
+GskSlValue *            gsk_sl_value_new_member                 (GskSlValue          *value,
+                                                                 guint                n);
 GskSlValue *            gsk_sl_value_copy                       (const GskSlValue    *source);
 void                    gsk_sl_value_free                       (GskSlValue          *value);
 


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