[Mesa-dev] [PATCH 06/16] glsl: Add a pass to lower bitfield-insert into bfm+bfi.
Matt Turner
mattst88 at gmail.com
Mon Apr 22 17:08:22 PDT 2013
i965/Gen7+ and Radeon/Evergreen+ have bfm/bfi instructions to implement
bitfieldInsert() from ARB_gpu_shader5.
---
src/glsl/ir.cpp | 2 +
src/glsl/ir.h | 18 ++++++++++++++++
src/glsl/ir_optimization.h | 1 +
src/glsl/ir_validate.cpp | 12 +++++++++++
src/glsl/lower_instructions.cpp | 42 +++++++++++++++++++++++++++++++++++++++
src/mesa/program/ir_to_mesa.cpp | 2 +
6 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 2c989c9..2c54525 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -508,8 +508,10 @@ static const char *const operator_strs[] = {
"max",
"pow",
"packHalf2x16_split",
+ "bfm",
"ubo_load",
"lrp",
+ "bfi",
"bitfield_extract",
"bitfield_insert",
"vector",
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 277b815..f23dc19 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -1118,6 +1118,15 @@ enum ir_expression_operation {
/*@}*/
/**
+ * \name First half of a lowered bitfieldInsert() operation.
+ *
+ * \see lower_instructions::bitfield_insert_to_bfm_bfi
+ */
+ /*@{*/
+ ir_binop_bfm,
+ /*@}*/
+
+ /**
* Load a value the size of a given GLSL type from a uniform block.
*
* operand0 is the ir_constant uniform block index in the linked shader.
@@ -1132,6 +1141,15 @@ enum ir_expression_operation {
ir_triop_lrp,
+ /**
+ * \name Second half of a lowered bitfieldInsert() operation.
+ *
+ * \see lower_instructions::bitfield_insert_to_bfm_bfi
+ */
+ /*@{*/
+ ir_triop_bfi,
+ /*@}*/
+
ir_triop_bitfield_extract,
/**
diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
index a8885d7..49b1475 100644
--- a/src/glsl/ir_optimization.h
+++ b/src/glsl/ir_optimization.h
@@ -37,6 +37,7 @@
#define MOD_TO_FRACT 0x20
#define INT_DIV_TO_MUL_RCP 0x40
#define LRP_TO_ARITH 0x80
+#define BITFIELD_INSERT_TO_BFM_BFI 0x100
/**
* \see class lower_packing_builtins_visitor
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
index 4a8df69..26f09c7 100644
--- a/src/glsl/ir_validate.cpp
+++ b/src/glsl/ir_validate.cpp
@@ -474,6 +474,12 @@ ir_validate::visit_leave(ir_expression *ir)
assert(ir->operands[1]->type == glsl_type::float_type);
break;
+ case ir_binop_bfm:
+ assert(ir->type->is_integer());
+ assert(ir->operands[0]->type->is_integer());
+ assert(ir->operands[1]->type->is_integer());
+ break;
+
case ir_binop_ubo_load:
assert(ir->operands[0]->as_constant());
assert(ir->operands[0]->type == glsl_type::uint_type);
@@ -487,6 +493,12 @@ ir_validate::visit_leave(ir_expression *ir)
assert(ir->operands[2]->type == ir->operands[0]->type || ir->operands[2]->type == glsl_type::float_type);
break;
+ case ir_triop_bfi:
+ assert(ir->operands[0]->type->is_integer());
+ assert(ir->operands[1]->type == ir->operands[2]->type);
+ assert(ir->operands[1]->type == ir->type);
+ break;
+
case ir_triop_bitfield_extract:
assert(ir->operands[0]->type == ir->type);
assert(ir->operands[1]->type == glsl_type::int_type);
diff --git a/src/glsl/lower_instructions.cpp b/src/glsl/lower_instructions.cpp
index 1ce7b7c..ff9715d 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,32 @@ 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
+ */
+
+ /* Save op0 */
+ ir_variable *temp = new(ir) ir_variable(ir->operands[0]->type, "bfi_base",
+ ir_var_temporary);
+ this->base_ir->insert_before(temp);
+ this->base_ir->insert_before(assign(temp, ir->operands[0]));
+
+ ir->operation = ir_triop_bfi;
+ ir->operands[0] = new(ir) ir_expression(ir_binop_bfm, ir->type,
+ swizzle_xxxx(ir->operands[3]),
+ swizzle_xxxx(ir->operands[2]));
+ /* ir->operands[1] is still the value to insert. */
+ ir->operands[2] = new(ir) ir_dereference_variable(temp);
+ ir->operands[3] = NULL;
+
+ this->progress = true;
+}
+
ir_visitor_status
lower_instructions_visitor::visit_leave(ir_expression *ir)
{
@@ -339,6 +376,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;
}
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index c6f6bf4..0848462 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -1489,6 +1489,8 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]);
break;
+ case ir_binop_bfm:
+ case ir_triop_bfi:
case ir_triop_bitfield_extract:
case ir_quadop_bitfield_insert:
assert(!"not supported");
--
1.7.8.6
More information about the mesa-dev
mailing list