On 03/26/2012 12:42 PM, Eric Anholt wrote:
The C++ constructors with placement new, while functional, are
extremely verbose, leading to generation of simple GLSL IR expressions
like (a * b + c * d) expanding to many lines of code and using lots of
temporary variables.  By creating a new ir_builder.h that puts simple
generators in our namespace and taking advantage of ralloc_parent(),
we can generate much more compact code, at a minor runtime cost.
---
  src/glsl/Makefile.sources            |    1 +
  src/glsl/ir_builder.cpp              |   69 ++++++++++++++++++
  src/glsl/ir_builder.h                |   36 ++++++++++
  src/mesa/main/ff_fragment_shader.cpp |  128 ++++++++++++----------------------
  4 files changed, 152 insertions(+), 82 deletions(-)
  create mode 100644 src/glsl/ir_builder.cpp
  create mode 100644 src/glsl/ir_builder.h

diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
index 06728da..4e3b074 100644
--- a/src/glsl/Makefile.sources
+++ b/src/glsl/Makefile.sources
@@ -26,6 +26,7 @@ LIBGLSL_CXX_FILES := \
        glsl_symbol_table.cpp \
        hir_field_selection.cpp \
        ir_basic_block.cpp \
+       ir_builder.cpp \
        ir_clone.cpp \
        ir_constant_expression.cpp \
        ir.cpp \
diff --git a/src/glsl/ir_builder.cpp b/src/glsl/ir_builder.cpp
new file mode 100644
index 0000000..039ee1b
--- /dev/null
+++ b/src/glsl/ir_builder.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "ir_builder.h"
+
+using namespace ir_builder;
+
+namespace ir_builder {
+
+ir_expression *
+expr(ir_expression_operation op,
+     ir_instruction *a, ir_instruction *b)
+{
+   void *mem_ctx = ralloc_parent(a);
+
+   return new(mem_ctx) ir_expression(op, a->as_rvalue(), b->as_rvalue());
+}

x.X

Please use ir_rvalue everywhere rather than ir_instruction. ir_rvalue is the base class for all expression trees/values, while ir_instruction is the base class for statements.

This also would make passing a non-rvalue a compile time error (no matching signature) rather than a run-time crash.

Otherwise, this patch looks pretty awesome.  I am a fan. :)

+
+ir_expression *add(ir_instruction *a, ir_instruction *b)
+{
+   return expr(ir_binop_add, a, b);
+}
+
+ir_expression *sub(ir_instruction *a, ir_instruction *b)
+{
+   return expr(ir_binop_sub, a, b);
+}
+
+ir_expression *mul(ir_instruction *a, ir_instruction *b)
+{
+   return expr(ir_binop_mul, a, b);
+}
+
+ir_expression *dot(ir_instruction *a, ir_instruction *b)
+{
+   return expr(ir_binop_dot, a, b);
+}
+
+ir_expression *
+saturate(ir_instruction *a)
+{
+   void *mem_ctx = ralloc_parent(a);
+
+   return expr(ir_binop_max,
+              expr(ir_binop_min, a, new(mem_ctx) ir_constant(1.0f)),
+              new(mem_ctx) ir_constant(0.0f));
+}
+
+} /* namespace ir_builder */
diff --git a/src/glsl/ir_builder.h b/src/glsl/ir_builder.h
new file mode 100644
index 0000000..5a26bb6
--- /dev/null
+++ b/src/glsl/ir_builder.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "ir.h"
+
+namespace ir_builder {
+
+ir_expression *expr(ir_expression_operation op,
+                   ir_instruction *a, ir_instruction *b);
+ir_expression *add(ir_instruction *a, ir_instruction *b);
+ir_expression *sub(ir_instruction *a, ir_instruction *b);
+ir_expression *mul(ir_instruction *a, ir_instruction *b);
+ir_expression *dot(ir_instruction *a, ir_instruction *b);
+ir_expression *saturate(ir_instruction *a);
+
+} /* namespace ir_builder */
diff --git a/src/mesa/main/ff_fragment_shader.cpp 
b/src/mesa/main/ff_fragment_shader.cpp
index 7b83043..cfee334 100644
--- a/src/mesa/main/ff_fragment_shader.cpp
+++ b/src/mesa/main/ff_fragment_shader.cpp
@@ -45,12 +45,15 @@ extern "C" {
  #include "main/uniforms.h"
  #include "../glsl/glsl_types.h"
  #include "../glsl/ir.h"
+#include "../glsl/ir_builder.h"
  #include "../glsl/glsl_symbol_table.h"
  #include "../glsl/glsl_parser_extras.h"
  #include "../glsl/ir_optimization.h"
  #include "../glsl/ir_print_visitor.h"
  #include "../program/ir_to_mesa.h"

+using namespace ir_builder;
+
  /*
   * Note on texture units:
   *
@@ -621,9 +624,7 @@ emit_combine_source(struct texenv_fragment_program *p,

     switch (operand) {
     case OPR_ONE_MINUS_SRC_COLOR:
-      return new(p->mem_ctx) ir_expression(ir_binop_sub,
-                                          new(p->mem_ctx) ir_constant(1.0f),
-                                          src);
+      return sub(new(p->mem_ctx) ir_constant(1.0f), src);

     case OPR_SRC_ALPHA:
        return src->type->is_scalar()
@@ -633,9 +634,7 @@ emit_combine_source(struct texenv_fragment_program *p,
        ir_rvalue *const scalar = (src->type->is_scalar())
         ? src : (ir_rvalue *) new(p->mem_ctx) ir_swizzle(src, 3, 3, 3, 3, 1);

-      return new(p->mem_ctx) ir_expression(ir_binop_sub,
-                                          new(p->mem_ctx) ir_constant(1.0f),
-                                          scalar);
+      return sub(new(p->mem_ctx) ir_constant(1.0f), scalar);
     }

     case OPR_ZERO:
@@ -720,73 +719,54 @@ emit_combine(struct texenv_fragment_program *p,
        return src[0];

     case MODE_MODULATE:
-      return new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[1]);
+      return mul(src[0], src[1]);

     case MODE_ADD:
-      return new(p->mem_ctx) ir_expression(ir_binop_add, src[0], src[1]);
+      return add(src[0], src[1]);

     case MODE_ADD_SIGNED:
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, src[0], src[1]);
-      return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0,
-                                          new(p->mem_ctx) ir_constant(-0.5f));
+      return add(add(src[0], src[1]), new(p->mem_ctx) ir_constant(-0.5f));

     case MODE_INTERPOLATE:
        /* Arg0 * (Arg2) + Arg1 * (1-Arg2) */
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]);
-
-      tmp1 = new(p->mem_ctx) ir_expression(ir_binop_sub,
-                                          new(p->mem_ctx) ir_constant(1.0f),
-                                          src[2]->clone(p->mem_ctx, NULL));
-      tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[1], tmp1);
-
-      return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, tmp1);
+      tmp0 = mul(src[0], src[2]);
+      tmp1 = mul(src[1], sub(new(p->mem_ctx) ir_constant(1.0f),
+                            src[2]->clone(p->mem_ctx, NULL)));
+      return add(tmp0, tmp1);

     case MODE_SUBTRACT:
-      return new(p->mem_ctx) ir_expression(ir_binop_sub, src[0], src[1]);
+      return sub(src[0], src[1]);

     case MODE_DOT3_RGBA:
     case MODE_DOT3_RGBA_EXT:
     case MODE_DOT3_RGB_EXT:
     case MODE_DOT3_RGB: {
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0],
-                                          new(p->mem_ctx) ir_constant(2.0f));
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0,
-                                          new(p->mem_ctx) ir_constant(-1.0f));
+      tmp0 = mul(src[0], new(p->mem_ctx) ir_constant(2.0f));
+      tmp0 = add(tmp0, new(p->mem_ctx) ir_constant(-1.0f));
        tmp0 = new(p->mem_ctx) ir_swizzle(smear(p, tmp0), 0, 1, 2, 3, 3);

-      tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[1],
-                                          new(p->mem_ctx) ir_constant(2.0f));
-      tmp1 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp1,
-                                          new(p->mem_ctx) ir_constant(-1.0f));
+      tmp1 = mul(src[1], new(p->mem_ctx) ir_constant(2.0f));
+      tmp1 = add(tmp1, new(p->mem_ctx) ir_constant(-1.0f));
        tmp1 = new(p->mem_ctx) ir_swizzle(smear(p, tmp1), 0, 1, 2, 3, 3);

-      return new(p->mem_ctx) ir_expression(ir_binop_dot, tmp0, tmp1);
+      return dot(tmp0, tmp1);
     }
     case MODE_MODULATE_ADD_ATI:
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]);
-      return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, src[1]);
+      return add(mul(src[0], src[2]), src[1]);

     case MODE_MODULATE_SIGNED_ADD_ATI:
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]);
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, src[1]);
-      return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0,
-                                          new(p->mem_ctx) ir_constant(-0.5f));
+      return add(add(mul(src[0], src[2]), src[1]),
+                new(p->mem_ctx) ir_constant(-0.5f));

     case MODE_MODULATE_SUBTRACT_ATI:
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]);
-      return new(p->mem_ctx) ir_expression(ir_binop_sub, tmp0, src[1]);
+      return sub(mul(src[0], src[2]), src[1]);

     case MODE_ADD_PRODUCTS:
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[1]);
-      tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[2], src[3]);
-      return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, tmp1);
+      return add(mul(src[0], src[1]), mul(src[2], src[3]));

     case MODE_ADD_PRODUCTS_SIGNED:
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[1]);
-      tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[2], src[3]);
-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, tmp1);
-      return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0,
-                                          new(p->mem_ctx) ir_constant(-0.5f));
+      return add(add(mul(src[0], src[1]), mul(src[2], src[3])),
+                new(p->mem_ctx) ir_constant(-0.5f));

     case MODE_BUMP_ENVMAP_ATI:
        /* special - not handled here */
@@ -798,15 +778,6 @@ emit_combine(struct texenv_fragment_program *p,
     }
  }

-static ir_rvalue *
-saturate(struct texenv_fragment_program *p, ir_rvalue *val)
-{
-   val = new(p->mem_ctx) ir_expression(ir_binop_min, val,
-                                      new(p->mem_ctx) ir_constant(1.0f));
-   return new(p->mem_ctx) ir_expression(ir_binop_max, val,
-                                       new(p->mem_ctx) ir_constant(0.0f));
-}
-
  /**
   * Generate instructions for one texture unit's env/combiner mode.
   */
@@ -876,7 +847,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
                         key->unit[unit].OptRGB);
        val = smear(p, val);
        if (rgb_saturate)
-        val = saturate(p, val);
+        val = saturate(val);

        deref = new(p->mem_ctx) ir_dereference_variable(temp_var);
        assign = new(p->mem_ctx) ir_assignment(deref, val);
@@ -890,7 +861,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
                                    key->unit[unit].OptRGB);
        val = smear(p, val);
        if (rgb_saturate)
-        val = saturate(p, val);
+        val = saturate(val);
        deref = new(p->mem_ctx) ir_dereference_variable(temp_var);
        assign = new(p->mem_ctx) ir_assignment(deref, val);
        p->instructions->push_tail(assign);
@@ -906,7 +877,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
        val = smear(p, val);
        val = new(p->mem_ctx) ir_swizzle(val, 0, 1, 2, 3, 3);
        if (rgb_saturate)
-        val = saturate(p, val);
+        val = saturate(val);
        deref = new(p->mem_ctx) ir_dereference_variable(temp_var);
        assign = new(p->mem_ctx) ir_assignment(deref, val, NULL, WRITEMASK_XYZ);
        p->instructions->push_tail(assign);
@@ -918,7 +889,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
        val = smear(p, val);
        val = new(p->mem_ctx) ir_swizzle(val, 3, 3, 3, 3, 1);
        if (alpha_saturate)
-        val = saturate(p, val);
+        val = saturate(val);
        deref = new(p->mem_ctx) ir_dereference_variable(temp_var);
        assign = new(p->mem_ctx) ir_assignment(deref, val, NULL, WRITEMASK_W);
        p->instructions->push_tail(assign);
@@ -945,8 +916,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
                                             (ir_constant_data *)const_data);
        }

-      return saturate(p, new(p->mem_ctx) ir_expression(ir_binop_mul,
-                                                      deref, shift));
+      return saturate(mul(deref, shift));
     }
     else
        return deref;
@@ -1185,18 +1155,16 @@ load_texunit_bumpmap( struct texenv_fragment_program 
*p, GLuint unit )
     bump = bump->clone(p->mem_ctx, NULL);
     bump_y = new(p->mem_ctx) ir_swizzle(bump, 1, 0, 0, 0, 1);

-   bump_x = new(p->mem_ctx) ir_expression(ir_binop_mul, bump_x, rot_mat_0);
-   bump_y = new(p->mem_ctx) ir_expression(ir_binop_mul, bump_y, rot_mat_1);
+   bump_x = mul(bump_x, rot_mat_0);
+   bump_y = mul(bump_y, rot_mat_1);

     ir_expression *expr;
-   expr = new(p->mem_ctx) ir_expression(ir_binop_add, bump_x, bump_y);

     deref = new(p->mem_ctx) ir_dereference_variable(bumped);
-   expr = new(p->mem_ctx) ir_expression(ir_binop_add,
-                                       new(p->mem_ctx) ir_swizzle(deref,
-                                                                  0, 1, 1, 1,
-                                                                  2),
-                                       expr);
+   expr = add(new(p->mem_ctx) ir_swizzle(deref,
+                                        0, 1, 1, 1,
+                                        2),
+             add(bump_x, bump_y));

     deref = new(p->mem_ctx) ir_dereference_variable(bumped);
     assign = new(p->mem_ctx) ir_assignment(deref, expr, NULL, WRITEMASK_XY);
@@ -1255,11 +1223,11 @@ emit_fog_instructions(struct texenv_fragment_program *p,
         */
        temp = new(p->mem_ctx) ir_dereference_variable(oparams);
        temp = new(p->mem_ctx) ir_swizzle(temp, 0, 0, 0, 0, 1);
-      f = new(p->mem_ctx) ir_expression(ir_binop_mul, f, temp);
+      f = mul(f, temp);

        temp = new(p->mem_ctx) ir_dereference_variable(oparams);
        temp = new(p->mem_ctx) ir_swizzle(temp, 1, 0, 0, 0, 1);
-      f = new(p->mem_ctx) ir_expression(ir_binop_add, f, temp);
+      f = add(f, temp);
        break;
     case FOG_EXP:
        /* f = e^(-(density * fogcoord))
@@ -1270,7 +1238,7 @@ emit_fog_instructions(struct texenv_fragment_program *p,
         */
        temp = new(p->mem_ctx) ir_dereference_variable(oparams);
        temp = new(p->mem_ctx) ir_swizzle(temp, 2, 0, 0, 0, 1);
-      f = new(p->mem_ctx) ir_expression(ir_binop_mul, f, temp);
+      f = mul(f, temp);
        f = new(p->mem_ctx) ir_expression(ir_unop_neg, f);
        f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f);
        break;
@@ -1288,8 +1256,7 @@ emit_fog_instructions(struct texenv_fragment_program *p,

        temp = new(p->mem_ctx) ir_dereference_variable(oparams);
        temp = new(p->mem_ctx) ir_swizzle(temp, 3, 0, 0, 0, 1);
-      f = new(p->mem_ctx) ir_expression(ir_binop_mul,
-                                       f, temp);
+      f = mul(f, temp);

        temp = new(p->mem_ctx) ir_dereference_variable(temp_var);
        ir_assignment *assign = new(p->mem_ctx) ir_assignment(temp, f);
@@ -1297,30 +1264,27 @@ emit_fog_instructions(struct texenv_fragment_program *p,

        f = new(p->mem_ctx) ir_dereference_variable(temp_var);
        temp = new(p->mem_ctx) ir_dereference_variable(temp_var);
-      f = new(p->mem_ctx) ir_expression(ir_binop_mul, f, temp);
+      f = mul(f, temp);
        f = new(p->mem_ctx) ir_expression(ir_unop_neg, f);
        f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f);
        break;
     }

-   f = saturate(p, f);
+   f = saturate(f);

     temp = new(p->mem_ctx) ir_dereference_variable(f_var);
     assign = new(p->mem_ctx) ir_assignment(temp, f);
     p->instructions->push_tail(assign);

     f = new(p->mem_ctx) ir_dereference_variable(f_var);
-   f = new(p->mem_ctx) ir_expression(ir_binop_sub,
-                                    new(p->mem_ctx) ir_constant(1.0f),
-                                    f);
+   f = sub(new(p->mem_ctx) ir_constant(1.0f), f);
     temp = new(p->mem_ctx) ir_dereference_variable(params);
     temp = new(p->mem_ctx) ir_dereference_record(temp, "color");
     temp = new(p->mem_ctx) ir_swizzle(temp, 0, 1, 2, 3, 3);
-   temp = new(p->mem_ctx) ir_expression(ir_binop_mul, temp, f);
+   temp = mul(temp, f);

     f = new(p->mem_ctx) ir_dereference_variable(f_var);
-   f = new(p->mem_ctx) ir_expression(ir_binop_mul, fragcolor, f);
-   f = new(p->mem_ctx) ir_expression(ir_binop_add, temp, f);
+   f = add(temp, mul(fragcolor, f));

     ir_dereference *deref = new(p->mem_ctx) 
ir_dereference_variable(fog_result);
     assign = new(p->mem_ctx) ir_assignment(deref, f, NULL, WRITEMASK_XYZ);
@@ -1392,7 +1356,7 @@ emit_instructions(struct texenv_fragment_program *p)
        }
        secondary = new(p->mem_ctx) ir_swizzle(secondary, 0, 1, 2, 3, 3);

-      tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, secondary);
+      tmp0 = add(tmp0, secondary);

        deref = new(p->mem_ctx) ir_dereference_variable(spec_result);
        assign = new(p->mem_ctx) ir_assignment(deref, tmp0, NULL, 
WRITEMASK_XYZ);

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to