[gtk+/wip/otte/shader: 86/226] gskslexpression: Parse swizzles



commit 13dd620828a531ffed584c738fceffa8fc8e92f3
Author: Benjamin Otte <otte redhat com>
Date:   Wed Sep 27 03:14:53 2017 +0200

    gskslexpression: Parse swizzles

 gsk/gskslexpression.c     |  288 ++++++++++++++++++++++++++++++++++++++++++++-
 gsk/gskspvwriterprivate.h |   24 ++++
 2 files changed, 311 insertions(+), 1 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 18a89cb..6506f16 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -784,6 +784,177 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = {
   gsk_sl_expression_function_call_write_spv
 };
 
+/* SWIZZLE */
+
+typedef enum {
+  GSK_SL_SWIZZLE_POINT,
+  GSK_SL_SWIZZLE_COLOR,
+  GSK_SL_SWIZZLE_TEXCOORD
+} GskSlSwizzleName;
+
+static const char *swizzle_options[] = { "xyzw", "rgba", "stpq" };
+
+typedef struct _GskSlExpressionSwizzle GskSlExpressionSwizzle;
+
+struct _GskSlExpressionSwizzle {
+  GskSlExpression parent;
+
+  GskSlExpression *expr;
+  GskSlSwizzleName name;
+  guint length;
+  guint indexes[4];
+};
+
+static void
+gsk_sl_expression_swizzle_free (GskSlExpression *expression)
+{
+  GskSlExpressionSwizzle *swizzle = (GskSlExpressionSwizzle *) expression;
+
+  gsk_sl_expression_unref (swizzle->expr);
+
+  g_slice_free (GskSlExpressionSwizzle, swizzle);
+}
+
+static void
+gsk_sl_expression_swizzle_print (const GskSlExpression *expression,
+                                 GString               *string)
+{
+  const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+  guint i;
+
+  gsk_sl_expression_print (swizzle->expr, string);
+  g_string_append (string, ".");
+  for (i = 0; i < swizzle->length; i++)
+    {
+      g_string_append_c (string, swizzle_options[swizzle->name][swizzle->indexes[i]]);
+    }
+}
+
+static GskSlType *
+gsk_sl_expression_swizzle_get_return_type (const GskSlExpression *expression)
+{
+  const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+  GskSlType *type;
+
+  type = gsk_sl_expression_get_return_type (swizzle->expr);
+
+  if (swizzle->length == 1)
+    return gsk_sl_type_get_scalar (gsk_sl_type_get_scalar_type (type));
+  else
+    return gsk_sl_type_get_vector (gsk_sl_type_get_scalar_type (type), swizzle->length);
+}
+
+static GskSlValue *
+gsk_sl_expression_swizzle_get_constant (const GskSlExpression *expression)
+{
+  const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+  GskSlValue *result, *value;
+  guchar *sdata, *ddata;
+  gsize sstride, dstride;
+  GskSlScalarType scalar_type;
+  guint i;
+
+  value = gsk_sl_expression_get_constant (swizzle->expr);
+  if (value == NULL)
+    return NULL;
+
+  scalar_type = gsk_sl_type_get_scalar_type (gsk_sl_value_get_type (value));
+  sdata = gsk_sl_value_get_data (value);
+  sstride = gsk_sl_type_get_index_stride (gsk_sl_value_get_type (value));
+  result = gsk_sl_value_new (gsk_sl_expression_get_return_type (expression));
+  ddata = gsk_sl_value_get_data (result);
+  dstride = gsk_sl_type_get_index_stride (gsk_sl_value_get_type (result));
+
+  for (i = 0; i < swizzle->length; i++)
+    {
+      gsk_sl_scalar_type_convert_value (scalar_type,
+                                        ddata + dstride * i,
+                                        scalar_type,
+                                        sdata + sstride * swizzle->indexes[i]);
+    }
+
+  gsk_sl_value_free (value);
+
+  return result;
+}
+
+static guint32
+gsk_sl_expression_swizzle_write_spv (const GskSlExpression *expression,
+                                     GskSpvWriter          *writer)
+{
+  const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+  GskSlType *type;
+  guint32 expr_id, type_id, result_id;
+
+  type = gsk_sl_expression_get_return_type (swizzle->expr);
+  expr_id = gsk_sl_expression_write_spv (swizzle->expr, writer);
+
+  if (gsk_sl_type_is_scalar (type))
+    {
+      if (swizzle->length == 1)
+        return expr_id;
+
+      type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_expression_get_return_type (expression));
+      result_id = gsk_spv_writer_next_id (writer);
+
+      gsk_spv_writer_add (writer,
+                          GSK_SPV_WRITER_SECTION_CODE,
+                          3 + swizzle->length, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
+                          (guint32[6]) { type_id,
+                                         result_id,
+                                         expr_id,
+                                         expr_id,
+                                         expr_id,
+                                         expr_id });
+
+      return result_id;
+    }
+  else if (gsk_sl_type_is_vector (type))
+    {
+      type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_expression_get_return_type (expression));
+      result_id = gsk_spv_writer_next_id (writer);
+
+      if (swizzle->length == 1)
+        {
+          gsk_spv_writer_add (writer,
+                              GSK_SPV_WRITER_SECTION_CODE,
+                              4, GSK_SPV_OP_COMPOSITE_EXTRACT,
+                              (guint32[6]) { type_id,
+                                             result_id,
+                                             swizzle->indexes[0] });
+        }
+      else
+        {
+          gsk_spv_writer_add (writer,
+                              GSK_SPV_WRITER_SECTION_CODE,
+                              5 + swizzle->length, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
+                              (guint32[8]) { type_id,
+                                             result_id,
+                                             expr_id,
+                                             expr_id,
+                                             swizzle->indexes[0],
+                                             swizzle->indexes[1],
+                                             swizzle->indexes[2],
+                                             swizzle->indexes[3] });
+        }
+
+      return result_id;
+    }
+  else
+    {
+      g_assert_not_reached ();
+      return 0;
+    }
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_SWIZZLE = {
+  gsk_sl_expression_swizzle_free,
+  gsk_sl_expression_swizzle_print,
+  gsk_sl_expression_swizzle_get_return_type,
+  gsk_sl_expression_swizzle_get_constant,
+  gsk_sl_expression_swizzle_write_spv
+};
+
 /* CONSTANT */
 
 typedef struct _GskSlExpressionConstant GskSlExpressionConstant;
@@ -1048,10 +1219,125 @@ gsk_sl_expression_parse_primary (GskSlScope        *scope,
 }
 
 static GskSlExpression *
+gsk_sl_expression_parse_field_selection (GskSlScope        *scope,
+                                         GskSlPreprocessor *stream,
+                                         GskSlExpression   *expr,
+                                         const char        *name,
+                                         gboolean          *success)
+{
+  GskSlType *type;
+
+  if (g_str_equal (name, "length"))
+    {
+       gsk_sl_preprocessor_error (stream, ".length() is not implemented yet.");
+       *success = FALSE;
+       return expr;
+    }
+
+  type = gsk_sl_expression_get_return_type (expr);
+
+  if (gsk_sl_type_is_scalar (type) || gsk_sl_type_is_vector (type))
+    {
+      GskSlExpressionSwizzle *swizzle;
+      guint type_length = MAX (1, gsk_sl_type_get_length (type));
+      
+      swizzle = gsk_sl_expression_new (GskSlExpressionSwizzle, &GSK_SL_EXPRESSION_SWIZZLE);
+
+      for (swizzle->name = 0; swizzle->name < G_N_ELEMENTS(swizzle_options); swizzle->name++)
+        {
+          const char *found = strchr (swizzle_options[swizzle->name], name[0]);
+          if (found)
+            break;
+        }
+      if (swizzle->name == G_N_ELEMENTS(swizzle_options))
+        {
+          gsk_sl_preprocessor_error (stream, "Type %s has no member named \"%s\".", gsk_sl_type_get_name 
(type), name);
+          gsk_sl_expression_unref ((GskSlExpression *) swizzle);
+          *success = FALSE;
+          return expr;
+        }
+      swizzle->expr = expr;
+
+      for (swizzle->length = 0; swizzle->length < 4 && name[swizzle->length]; swizzle->length++)
+        {
+          const char *found = strchr (swizzle_options[swizzle->name], name[swizzle->length]);
+          if (found == NULL)
+            {
+              gsk_sl_preprocessor_error (stream, "Character '%c' is not valid for swizzle. Must be one of 
\"%s\".",
+                                                 name[swizzle->length], swizzle_options[swizzle->name]);
+              *success = FALSE;
+              return (GskSlExpression *) swizzle;
+            }
+          swizzle->indexes[swizzle->length] = found - swizzle_options[swizzle->name];
+          if (swizzle->indexes[swizzle->length] >= type_length)
+            {
+              gsk_sl_preprocessor_error (stream, "Swizzle index '%c' not allowed for type %s",
+                                                 name[swizzle->length], gsk_sl_type_get_name (type));
+              *success = FALSE;
+              return (GskSlExpression *) swizzle;
+            }
+        }
+      if (name[swizzle->length])
+        {
+          gsk_sl_preprocessor_error (stream, "Too many swizzle options. A maximum of 4 characters are 
allowed.");
+          *success = FALSE;
+          return (GskSlExpression *) swizzle;
+        }
+  
+      return (GskSlExpression *) swizzle;
+    }
+  else
+    {
+      gsk_sl_preprocessor_error (stream, "Cannot select fields of type %s.", gsk_sl_type_get_name (type));
+      *success = FALSE;
+      return expr;
+    }
+}
+
+static GskSlExpression *
 gsk_sl_expression_parse_postfix (GskSlScope        *scope,
                                  GskSlPreprocessor *stream)
 {
-  return gsk_sl_expression_parse_primary (scope, stream);
+  GskSlExpression *expr;
+  const GskSlToken *token;
+  gboolean success = TRUE;
+  
+  expr = gsk_sl_expression_parse_primary (scope, stream);
+
+  while (TRUE)
+    {
+      token = gsk_sl_preprocessor_get (stream);
+      if (gsk_sl_token_is (token, GSK_SL_TOKEN_DOT))
+        {
+          gsk_sl_preprocessor_consume (stream, NULL);
+          token = gsk_sl_preprocessor_get (stream);
+          if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+            {
+              char *field = g_strdup (token->str);
+              gsk_sl_preprocessor_consume (stream, NULL);
+              expr = gsk_sl_expression_parse_field_selection (scope, stream, expr, field, &success);
+              g_free (field);
+            }
+          else
+            {
+              gsk_sl_preprocessor_error (stream, "Expected an identifier to select a field.");
+              success = FALSE;
+              continue;
+            }
+        }
+      else 
+        {
+          break;
+        }
+    }
+
+  if (!success)
+    {
+      gsk_sl_expression_unref (expr);
+      return NULL;
+    }
+
+  return expr;
 }
 
 static GskSlExpression *
diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h
index 321c138..c0f3d5c 100644
--- a/gsk/gskspvwriterprivate.h
+++ b/gsk/gskspvwriterprivate.h
@@ -95,6 +95,30 @@ 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_VECTOR_EXTRACT_DYNAMIC = 77,
+  GSK_SPV_OP_VECTOR_INSERT_DYNAMIC = 78,
+  GSK_SPV_OP_VECTOR_SHUFFLE = 79,
+  GSK_SPV_OP_COMPOSITE_CONSTRUCT = 80,
+  GSK_SPV_OP_COMPOSITE_EXTRACT = 81,
+  GSK_SPV_OP_COMPOSITE_INSERT = 82,
+  GSK_SPV_OP_COPY_OBJECT = 83,
+  GSK_SPV_OP_TRANSPOSE = 84,
+  GSK_SPV_OP_CONVERT_F_TO_U = 109,
+  GSK_SPV_OP_CONVERT_F_TO_S = 110,
+  GSK_SPV_OP_CONVERT_S_TO_F = 111,
+  GSK_SPV_OP_CONVERT_U_TO_F = 112,
+  GSK_SPV_OP_U_CONVERT = 113,
+  GSK_SPV_OP_S_CONVERT = 114,
+  GSK_SPV_OP_F_CONVERT = 115,
+  GSK_SPV_OP_QUANTIZE_TO_F16 = 116,
+  GSK_SPV_OP_CONVERT_PTR_TO_U = 117,
+  GSK_SPV_OP_SAT_CONVERT_S_TO_U = 118,
+  GSK_SPV_OP_SAT_CONVERT_U_TO_S = 119,
+  GSK_SPV_OP_CONVERT_U_TO_PTR = 120,
+  GSK_SPV_OP_PTR_CAST_TO_GENERIC = 121,
+  GSK_SPV_OP_GENERIC_CAST_TO_PTR = 122,
+  GSK_SPV_OP_GENERIC_CAST_TO_PTR_EXPLICIT = 123,
+  GSK_SPV_OP_BITCAST = 124,
   GSK_SPV_OP_PHI = 245,
   GSK_SPV_OP_LOOP_MERGE = 246,
   GSK_SPV_OP_SELECTION_MERGE = 247,


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