glsl_to_tgsi: implement ir_binop_any_nequal using DP4 w/saturate or DP4 w/SLT
authorBryan Cain <bryancain3@gmail.com>
Sat, 20 Aug 2011 18:56:06 +0000 (13:56 -0500)
committerBryan Cain <bryancain3@gmail.com>
Sat, 20 Aug 2011 19:00:41 +0000 (14:00 -0500)
Implement the any() part of the operation the same way regular ir_unop_any
is implemented.

This is a port of commit e7bf096e8b04 to glsl_to_tgsi, with added integer
support.

src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index f7d79e9f50cd6b320d01d4f85b49a25e21359a17..b238c267c817d288ea345de6226343d8dcce02c6 100644 (file)
@@ -1475,8 +1475,29 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
                glsl_type::vec4_type);
          assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
          emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]);
-         emit_dp(ir, result_dst, temp, temp, 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, temp, temp, 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
+             * 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 {
+            emit(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_float(0.0));
+         }
       } else {
          emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]);
       }