glsl_to_tgsi: implement ir_unop_any using DP4 w/saturate or DP4 w/SLT
authorBryan Cain <bryancain3@gmail.com>
Sat, 20 Aug 2011 18:26:12 +0000 (13:26 -0500)
committerBryan Cain <bryancain3@gmail.com>
Sat, 20 Aug 2011 19:00:41 +0000 (14:00 -0500)
This is a port of commit 92ca560d68e8 to glsl_to_tgsi, with integer support
added.

src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index 62127afadde2b5e28a571399ce7dcde32d1b721e..f7d79e9f50cd6b320d01d4f85b49a25e21359a17 100644 (file)
@@ -1482,12 +1482,36 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       }
       break;
 
-   case ir_unop_any:
+   case ir_unop_any: {
       assert(ir->operands[0]->type->is_vector());
-      emit_dp(ir, result_dst, op[0], op[0],
-              ir->operands[0]->type->vector_elements);
-      emit(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_float(0.0));
+
+      /* After the dot-product, the value will be an integer on the
+       * range [0,4].  Zero stays zero, and positive values become 1.0.
+       */
+      glsl_to_tgsi_instruction *const dp =
+         emit_dp(ir, result_dst, op[0], op[0],
+                 ir->operands[0]->type->vector_elements);
+      if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB &&
+          result_dst.type == GLSL_TYPE_FLOAT) {
+             /* The clamping to [0,1] can be done for free in the fragment
+              * shader with a saturate.
+              */
+             dp->saturate = true;
+      } else if (result_dst.type == GLSL_TYPE_FLOAT) {
+             /* Negating the result of the dot-product gives values on the range
+              * [-4, 0].  Zero stays zero, and negative values become 1.0.  This
+              * is achieved using SLT.
+              */
+             st_src_reg slt_src = result_src;
+             slt_src.negate = ~slt_src.negate;
+             emit(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0));
+      }
+      else {
+         /* Use SNE 0 if integers are being used as boolean values. */
+         emit(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_int(0));
+      }
       break;
+   }
 
    case ir_binop_logic_xor:
       emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]);