[gtk+/wip/otte/shader: 53/150] gskslexpression: Implement negation



commit e6cb2345580ec83ad907648e2dfb509c3033174e
Author: Benjamin Otte <otte redhat com>
Date:   Fri Sep 29 02:45:11 2017 +0200

    gskslexpression: Implement negation
    
    This includes adding gsk_sl_value_componentwise() which is not something
    I particularly like, but it does its job - and will be useful for the
    other operations.

 gsk/gskslexpression.c     |  181 ++++++++++++++++++++++++++++++++++++++++++++-
 gsk/gskslvalue.c          |   19 +++++
 gsk/gskslvalueprivate.h   |    3 +
 gsk/gskspvwriterprivate.h |   27 +++++++
 4 files changed, 228 insertions(+), 2 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index ea99319..9c9de36 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -1055,6 +1055,142 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_SWIZZLE = {
   gsk_sl_expression_swizzle_write_spv
 };
 
+/* NEGATION */
+
+typedef struct _GskSlExpressionNegation GskSlExpressionNegation;
+
+struct _GskSlExpressionNegation {
+  GskSlExpression parent;
+
+  GskSlExpression *expr;
+};
+
+static void
+gsk_sl_expression_negation_free (GskSlExpression *expression)
+{
+  GskSlExpressionNegation *negation = (GskSlExpressionNegation *) expression;
+
+  gsk_sl_expression_unref (negation->expr);
+
+  g_slice_free (GskSlExpressionNegation, negation);
+}
+
+static void
+gsk_sl_expression_negation_print (const GskSlExpression *expression,
+                                  GString               *string)
+{
+  const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
+
+  g_string_append (string, "-");
+  gsk_sl_expression_print (negation->expr, string);
+}
+
+static GskSlType *
+gsk_sl_expression_negation_get_return_type (const GskSlExpression *expression)
+{
+  const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
+
+  return gsk_sl_expression_get_return_type (negation->expr);
+}
+
+#define GSK_SL_OPERATION_FUNC(func,type,...) \
+static void \
+func (gpointer value, gpointer unused) \
+{ \
+  type x = *(type *) value; \
+  __VA_ARGS__ \
+  *(type *) value = x; \
+}
+GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_int, gint32, x = -x;)
+GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_uint, guint32, x = -x;)
+GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_float, float, x = -x;)
+GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_double, double, x = -x;)
+
+static GskSlValue *
+gsk_sl_expression_negation_get_constant (const GskSlExpression *expression)
+{
+  const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
+  GskSlValue *value;
+
+  value = gsk_sl_expression_get_constant (negation->expr);
+  if (value == NULL)
+    return NULL;
+
+  switch (gsk_sl_type_get_scalar_type (gsk_sl_value_get_type (value)))
+    {
+    case GSK_SL_INT:
+      gsk_sl_value_componentwise (value, gsk_sl_expression_negation_int, NULL);
+      break;
+    case GSK_SL_UINT:
+      gsk_sl_value_componentwise (value, gsk_sl_expression_negation_uint, NULL);
+      break;
+    case GSK_SL_FLOAT:
+      gsk_sl_value_componentwise (value, gsk_sl_expression_negation_float, NULL);
+      break;
+    case GSK_SL_DOUBLE:
+      gsk_sl_value_componentwise (value, gsk_sl_expression_negation_double, NULL);
+      break;
+    case GSK_SL_VOID:
+    case GSK_SL_BOOL:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return value;
+}
+
+static guint32
+gsk_sl_expression_negation_write_spv (const GskSlExpression *expression,
+                                      GskSpvWriter          *writer)
+{
+  const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
+  guint type_id, expr_id, result_id;
+  GskSlType *type;
+
+  type = gsk_sl_expression_get_return_type (negation->expr);
+  type_id = gsk_spv_writer_get_id_for_type (writer, type);
+  expr_id = gsk_sl_expression_write_spv (negation->expr, writer);
+  result_id = gsk_spv_writer_next_id (writer);
+
+  switch (gsk_sl_type_get_scalar_type (type))
+    {
+    case GSK_SL_INT:
+    case GSK_SL_UINT:
+      gsk_spv_writer_add (writer,
+                          GSK_SPV_WRITER_SECTION_CODE,
+                          4, GSK_SPV_OP_S_NEGATE,
+                          (guint32[3]) { type_id,
+                                         result_id,
+                                         expr_id });
+      break;
+    case GSK_SL_FLOAT:
+    case GSK_SL_DOUBLE:
+      gsk_spv_writer_add (writer,
+                          GSK_SPV_WRITER_SECTION_CODE,
+                          4, GSK_SPV_OP_F_NEGATE,
+                          (guint32[3]) { type_id,
+                                         result_id,
+                                         expr_id });
+      break;
+    case GSK_SL_VOID:
+    case GSK_SL_BOOL:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return result_id;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_NEGATION = {
+  gsk_sl_expression_negation_free,
+  gsk_sl_expression_negation_print,
+  gsk_sl_expression_negation_get_return_type,
+  gsk_sl_expression_negation_get_constant,
+  gsk_sl_expression_negation_write_spv
+};
+
 /* CONSTANT */
 
 typedef struct _GskSlExpressionConstant GskSlExpressionConstant;
@@ -1071,6 +1207,8 @@ gsk_sl_expression_constant_free (GskSlExpression *expression)
   GskSlExpressionConstant *constant = (GskSlExpressionConstant *) expression;
 
   gsk_sl_value_free (constant->value);
+
+  g_slice_free (GskSlExpressionConstant, constant);
 }
 
 static void
@@ -1496,9 +1634,48 @@ gsk_sl_expression_parse_postfix (GskSlScope        *scope,
 
 static GskSlExpression *
 gsk_sl_expression_parse_unary (GskSlScope        *scope,
-                               GskSlPreprocessor *stream)
+                               GskSlPreprocessor *preproc)
 {
-  return gsk_sl_expression_parse_postfix (scope, stream);
+  const GskSlToken *token;
+  GskSlType *type;
+
+  token = gsk_sl_preprocessor_get (preproc);
+
+  if (gsk_sl_token_is (token, GSK_SL_TOKEN_DASH))
+    {
+      GskSlExpressionNegation *negation = gsk_sl_expression_new (GskSlExpressionNegation, 
&GSK_SL_EXPRESSION_NEGATION); 
+      GskSlExpression *expr;
+
+      gsk_sl_preprocessor_consume (preproc, negation);
+      negation->expr = gsk_sl_expression_parse_unary (scope, preproc);
+      type = gsk_sl_expression_get_return_type (negation->expr);
+      if (!gsk_sl_type_is_scalar (type) && !gsk_sl_type_is_vector (type) && !gsk_sl_type_is_matrix (type))
+        {
+          gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+                                     "Negation only works on scalars, vectors and matrices, not on %s.",
+                                     gsk_sl_type_get_name (type));
+          expr = gsk_sl_expression_ref (negation->expr);
+          gsk_sl_expression_unref ((GskSlExpression *) negation);
+          return expr;
+        }
+      else if (gsk_sl_type_get_scalar_type (type) == GSK_SL_BOOL)
+        {
+          gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+                                     "Negation does not work on boolean types like %s.",
+                                     gsk_sl_type_get_name (type));
+          expr = gsk_sl_expression_ref (negation->expr);
+          gsk_sl_expression_unref ((GskSlExpression *) negation);
+          return expr;
+        }
+      else
+        {
+          return (GskSlExpression *) negation;
+        }
+    }
+  else
+    {
+      return gsk_sl_expression_parse_postfix (scope, preproc);
+    }
 }
 
 static GskSlExpression *
diff --git a/gsk/gskslvalue.c b/gsk/gskslvalue.c
index 6972ff7..304fafe 100644
--- a/gsk/gskslvalue.c
+++ b/gsk/gskslvalue.c
@@ -195,6 +195,25 @@ gsk_sl_value_free (GskSlValue *value)
 }
 
 void
+gsk_sl_value_componentwise (GskSlValue    *value,
+                            void (* func) (gpointer, gpointer),
+                            gpointer       user_data)
+{
+  gsize stride;
+  gsize i, n;
+
+  g_return_if_fail (gsk_sl_type_is_scalar (value->type) || gsk_sl_type_is_vector (value->type) || 
gsk_sl_type_is_matrix (value->type));
+
+  stride = gsk_sl_type_get_size (gsk_sl_type_get_scalar (gsk_sl_type_get_scalar_type (value->type)));
+  n = gsk_sl_type_get_size (value->type) / stride;
+
+  for (i = 0; i < n; i++)
+    {
+      func ((guchar *) value->data + stride * i, user_data);
+    }
+}
+
+void
 gsk_sl_value_print (const GskSlValue *value,
                     GString          *string)
 {
diff --git a/gsk/gskslvalueprivate.h b/gsk/gskslvalueprivate.h
index c4e7c59..3a314a6 100644
--- a/gsk/gskslvalueprivate.h
+++ b/gsk/gskslvalueprivate.h
@@ -35,6 +35,9 @@ GskSlValue *            gsk_sl_value_new_member                 (GskSlValue
 GskSlValue *            gsk_sl_value_copy                       (const GskSlValue    *source);
 void                    gsk_sl_value_free                       (GskSlValue          *value);
 
+void                    gsk_sl_value_componentwise              (GskSlValue          *value,
+                                                                 void (* func)       (gpointer, gpointer),
+                                                                 gpointer             user_data);
 void                    gsk_sl_value_print                      (const GskSlValue    *value,
                                                                  GString             *string);
 
diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h
index c0f3d5c..81b2af1 100644
--- a/gsk/gskspvwriterprivate.h
+++ b/gsk/gskspvwriterprivate.h
@@ -119,6 +119,33 @@ typedef enum {
   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_S_NEGATE = 126,
+  GSK_SPV_OP_F_NEGATE = 127,
+  GSK_SPV_OP_I_ADD = 128,
+  GSK_SPV_OP_F_ADD = 129,
+  GSK_SPV_OP_I_SUB = 130,
+  GSK_SPV_OP_F_SUB = 131,
+  GSK_SPV_OP_I_MUL = 132,
+  GSK_SPV_OP_F_MUL = 133,
+  GSK_SPV_OP_U_DIV = 134,
+  GSK_SPV_OP_S_DIV = 135,
+  GSK_SPV_OP_F_DIV = 136,
+  GSK_SPV_OP_U_MOD = 137,
+  GSK_SPV_OP_S_REM = 138,
+  GSK_SPV_OP_S_MOD = 139,
+  GSK_SPV_OP_F_REM = 140,
+  GSK_SPV_OP_F_MOD = 141,
+  GSK_SPV_OP_VECTOR_TIMES_SCALAR = 142,
+  GSK_SPV_OP_MATRIX_TIMES_SCALAR = 143,
+  GSK_SPV_OP_VECTOR_TIMES_MATRIX = 144,
+  GSK_SPV_OP_MATRIX_TIMES_VECTOR = 145,
+  GSK_SPV_OP_MATRIX_TIMES_MATRIX = 146,
+  GSK_SPV_OP_OUTER_PRODUCT = 147,
+  GSK_SPV_OP_DOT = 148,
+  GSK_SPV_OP_I_ADD_CARRY = 149,
+  GSK_SPV_OP_I_SUB_BORROW = 150,
+  GSK_SPV_OP_U_MUL_EXTENDED = 151,
+  GSK_SPV_OP_S_MUL_EXTENDED = 152,
   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]