summaryrefslogtreecommitdiffstats
path: root/src/glsl/lower_instructions.cpp
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2013-04-09 22:43:05 -0700
committerMatt Turner <mattst88@gmail.com>2013-05-06 10:17:13 -0700
commitdafd050883660a42b2902388826cfecbfc9b8b83 (patch)
treeea6bba7a3f32ffab590953297a141c97148d1365 /src/glsl/lower_instructions.cpp
parent9c04b8c28c3a8b60e896492fd1bccc923916c1c4 (diff)
downloadexternal_mesa3d-dafd050883660a42b2902388826cfecbfc9b8b83.zip
external_mesa3d-dafd050883660a42b2902388826cfecbfc9b8b83.tar.gz
external_mesa3d-dafd050883660a42b2902388826cfecbfc9b8b83.tar.bz2
glsl: Add a pass to lower bitfield-insert into bfm+bfi.
i965/Gen7+ and Radeon/Evergreen+ have bfm/bfi instructions to implement bitfieldInsert() from ARB_gpu_shader5. v2: Add ir_binop_bfm and ir_triop_bfi to st_glsl_to_tgsi.cpp. Remove spurious temporary assignment and dereference. Reviewed-by: Chris Forbes <chrisf@ijw.co.nz>
Diffstat (limited to 'src/glsl/lower_instructions.cpp')
-rw-r--r--src/glsl/lower_instructions.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/glsl/lower_instructions.cpp b/src/glsl/lower_instructions.cpp
index 1ce7b7c..d32ec80 100644
--- a/src/glsl/lower_instructions.cpp
+++ b/src/glsl/lower_instructions.cpp
@@ -38,6 +38,7 @@
* - LOG_TO_LOG2
* - MOD_TO_FRACT
* - LRP_TO_ARITH
+ * - BITFIELD_INSERT_TO_BFM_BFI
*
* SUB_TO_ADD_NEG:
* ---------------
@@ -84,6 +85,15 @@
* LRP_TO_ARITH:
* -------------
* Converts ir_triop_lrp to (op0 * (1.0f - op2)) + (op1 * op2).
+ *
+ * BITFIELD_INSERT_TO_BFM_BFI:
+ * ---------------------------
+ * Breaks ir_quadop_bitfield_insert into ir_binop_bfm (bitfield mask) and
+ * ir_triop_bfi (bitfield insert).
+ *
+ * Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5
+ * with a pair of instructions.
+ *
*/
#include "main/core.h" /* for M_LOG2E */
@@ -114,6 +124,7 @@ private:
void pow_to_exp2(ir_expression *);
void log_to_log2(ir_expression *);
void lrp_to_arith(ir_expression *);
+ void bitfield_insert_to_bfm_bfi(ir_expression *);
};
/**
@@ -298,6 +309,29 @@ lower_instructions_visitor::lrp_to_arith(ir_expression *ir)
this->progress = true;
}
+void
+lower_instructions_visitor::bitfield_insert_to_bfm_bfi(ir_expression *ir)
+{
+ /* Translates
+ * ir_quadop_bitfield_insert base insert offset bits
+ * into
+ * ir_triop_bfi (ir_binop_bfm bits offset) insert base
+ */
+
+ ir_rvalue *base_expr = ir->operands[0];
+
+ ir->operation = ir_triop_bfi;
+ ir->operands[0] = new(ir) ir_expression(ir_binop_bfm,
+ ir->type->get_base_type(),
+ ir->operands[3],
+ ir->operands[2]);
+ /* ir->operands[1] is still the value to insert. */
+ ir->operands[2] = base_expr;
+ ir->operands[3] = NULL;
+
+ this->progress = true;
+}
+
ir_visitor_status
lower_instructions_visitor::visit_leave(ir_expression *ir)
{
@@ -339,6 +373,11 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
lrp_to_arith(ir);
break;
+ case ir_quadop_bitfield_insert:
+ if (lowering(BITFIELD_INSERT_TO_BFM_BFI))
+ bitfield_insert_to_bfm_bfi(ir);
+ break;
+
default:
return visit_continue;
}