[gtk+/wip/otte/shader: 117/151] gskslexpression: Add a logical or expression



commit dd36ec9cad20d2594ae4b226895b1ee4bc3d45a8
Author: Benjamin Otte <otte redhat com>
Date:   Thu Oct 12 01:43:22 2017 +0200

    gskslexpression: Add a logical or expression
    
    Logical or is not a binary expression in that the right side of the
    expression is only executed if the left side returns false while all
    binary operations always execute both sides.

 gsk/gskslexpression.c |  133 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 126 insertions(+), 7 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index f40b27d..3a4f0f6 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -286,6 +286,127 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_BINARY = {
   gsk_sl_expression_default_get_spv_access_chain
 };
 
+/* LOGICAL_OR */
+
+typedef struct _GskSlExpressionLogicalOr GskSlExpressionLogicalOr;
+
+struct _GskSlExpressionLogicalOr {
+  GskSlExpression parent;
+
+  GskSlExpression *left;
+  GskSlExpression *right;
+};
+
+static void
+gsk_sl_expression_logical_or_free (GskSlExpression *expression)
+{
+  GskSlExpressionLogicalOr *logical_or = (GskSlExpressionLogicalOr *) expression;
+
+  gsk_sl_expression_unref (logical_or->left);
+  gsk_sl_expression_unref (logical_or->right);
+
+  g_slice_free (GskSlExpressionLogicalOr, logical_or);
+}
+
+static void
+gsk_sl_expression_logical_or_print (const GskSlExpression *expression,
+                                    GskSlPrinter          *printer)
+{
+  GskSlExpressionLogicalOr *logical_or = (GskSlExpressionLogicalOr *) expression;
+
+  gsk_sl_expression_print (logical_or->left, printer);
+  gsk_sl_printer_append (printer, " || ");
+  gsk_sl_expression_print (logical_or->right, printer);
+}
+
+static GskSlType *
+gsk_sl_expression_logical_or_get_return_type (const GskSlExpression *expression)
+{
+  return gsk_sl_type_get_scalar (GSK_SL_BOOL);
+}
+
+static GskSlValue *
+gsk_sl_expression_logical_or_get_constant (const GskSlExpression *expression)
+{
+  const GskSlExpressionLogicalOr *logical_or = (const GskSlExpressionLogicalOr *) expression;
+  GskSlValue *lvalue, *rvalue;
+
+  lvalue = gsk_sl_expression_get_constant (logical_or->left);
+  if (lvalue == NULL)
+    return NULL;
+  rvalue = gsk_sl_expression_get_constant (logical_or->right);
+  if (rvalue == NULL)
+    {
+      gsk_sl_value_free (lvalue);
+      return NULL;
+    }
+
+  if (*(guint32 *) gsk_sl_value_get_data (lvalue))
+    {
+      gsk_sl_value_free (rvalue);
+      return lvalue;
+    }
+  else
+    {
+      gsk_sl_value_free (lvalue);
+      return rvalue;
+    }
+}
+
+static guint32
+gsk_sl_expression_logical_or_write_spv (const GskSlExpression *expression,
+                                        GskSpvWriter          *writer)
+{
+  const GskSlExpressionLogicalOr *logical_or = (const GskSlExpressionLogicalOr *) expression;
+  GskSpvCodeBlock *current_block, *after_block, *or_block;
+  guint32 current_id, condition_id, after_id, or_id, left_id, right_id, result_id;
+
+  left_id = gsk_sl_expression_write_spv (logical_or->left, writer);
+
+  current_block = gsk_spv_writer_pop_code_block (writer);
+  current_id = gsk_spv_code_block_get_label (current_block);
+  gsk_spv_writer_push_code_block (writer, current_block);
+
+  or_id = gsk_spv_writer_push_new_code_block (writer);
+  or_block = gsk_spv_writer_pop_code_block (writer);
+
+  after_id = gsk_spv_writer_push_new_code_block (writer);
+  after_block = gsk_spv_writer_pop_code_block (writer);
+
+  /* mirror glslang */
+  condition_id = gsk_spv_writer_logical_not (writer, gsk_sl_type_get_scalar (GSK_SL_BOOL), left_id);
+  gsk_spv_writer_selection_merge (writer, after_id, 0);
+  gsk_spv_writer_branch_conditional (writer, condition_id, or_id, after_id, NULL, 0);
+
+  gsk_spv_writer_push_code_block (writer, or_block);
+  right_id = gsk_sl_expression_write_spv (logical_or->right, writer);
+  gsk_spv_writer_branch (writer, after_id);
+  gsk_spv_writer_commit_code_block (writer);
+
+  gsk_spv_writer_push_code_block (writer, after_block);
+  gsk_spv_writer_commit_code_block (writer);
+
+  result_id = gsk_spv_writer_phi (writer, 
+                                  gsk_sl_type_get_scalar (GSK_SL_BOOL),
+                                  (guint32 **) (guint32[4][2]) {
+                                      { left_id, current_id },
+                                      { right_id, or_id }
+                                  },
+                                  2);
+
+  return result_id;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_LOGICAL_OR = {
+  gsk_sl_expression_logical_or_free,
+  gsk_sl_expression_logical_or_print,
+  gsk_sl_expression_default_is_assignable,
+  gsk_sl_expression_logical_or_get_return_type,
+  gsk_sl_expression_logical_or_get_constant,
+  gsk_sl_expression_logical_or_write_spv,
+  gsk_sl_expression_default_get_spv_access_chain
+};
+
 /* REFERENCE */
 
 typedef struct _GskSlExpressionReference GskSlExpressionReference;
@@ -2475,13 +2596,11 @@ gsk_sl_expression_parse_logical_or (GskSlScope        *scope,
                                               gsk_sl_expression_get_return_type (right));
       if (result_type)
         {
-          GskSlExpressionBinary *binary_expr;
-          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
-          binary_expr->binary = binary;
-          binary_expr->type = gsk_sl_type_ref (result_type);
-          binary_expr->left = expression;
-          binary_expr->right = right;
-          expression = (GskSlExpression *) binary_expr;
+          GskSlExpressionLogicalOr *logical_expr;
+          logical_expr = gsk_sl_expression_new (GskSlExpressionLogicalOr, &GSK_SL_EXPRESSION_LOGICAL_OR);
+          logical_expr->left = expression;
+          logical_expr->right = right;
+          expression = (GskSlExpression *) logical_expr;
         }
       else
         {


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