summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2013-03-06 11:05:14 -0800
committerIan Romanick <[email protected]>2013-05-13 12:05:18 -0700
commitf274a2ca8733059bdd4f1c456ed4f6df7d7ec008 (patch)
tree002b5b4e0268463d283b4ab2cbcb757c97312533
parentb0bb6103d23c16d23b0ec617746b4b0d1c22075d (diff)
glsl: Add ir_binop_vector_extract
The new opcode is used to get a single field from a vector. The field index may not be constant. This will eventually replace ir_dereference_array of vectors. This is similar to the extractelement instruction in LLVM IR. http://llvm.org/docs/LangRef.html#extractelement-instruction v2: Convert tabs to spaces. Suggested by Eric. v3: Add array index range checking to ir_binop_vector_extract constant expression handling. Suggested by Ken. v4: Use CLAMP instead of MIN2(MAX2()). Suggested by Ken. Signed-off-by: Ian Romanick <[email protected]> Reviewed-by: Eric Anholt <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r--src/glsl/ir.cpp5
-rw-r--r--src/glsl/ir.h10
-rw-r--r--src/glsl/ir_constant_expression.cpp38
-rw-r--r--src/glsl/ir_validate.cpp6
-rw-r--r--src/mesa/program/ir_to_mesa.cpp1
5 files changed, 55 insertions, 5 deletions
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 2c545259380..737d8d43f63 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -399,6 +399,10 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
this->type = op0->type;
break;
+ case ir_binop_vector_extract:
+ this->type = op0->type->get_scalar_type();
+ break;
+
default:
assert(!"not reached: missing automatic type setup for ir_expression");
this->type = glsl_type::float_type;
@@ -510,6 +514,7 @@ static const char *const operator_strs[] = {
"packHalf2x16_split",
"bfm",
"ubo_load",
+ "vector_extract",
"lrp",
"bfi",
"bitfield_extract",
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 6783ecaf2e9..e3e3b7119a8 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -1136,9 +1136,17 @@ enum ir_expression_operation {
ir_binop_ubo_load,
/**
+ * Extract a scalar from a vector
+ *
+ * operand0 is the vector
+ * operand1 is the index of the field to read from operand0
+ */
+ ir_binop_vector_extract,
+
+ /**
* A sentinel marking the last of the binary operations.
*/
- ir_last_binop = ir_binop_ubo_load,
+ ir_last_binop = ir_binop_vector_extract,
ir_triop_lrp,
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
index a4a117e683d..990f9835d99 100644
--- a/src/glsl/ir_constant_expression.cpp
+++ b/src/glsl/ir_constant_expression.cpp
@@ -391,10 +391,17 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
}
if (op[1] != NULL)
- assert(op[0]->type->base_type == op[1]->type->base_type ||
- this->operation == ir_binop_lshift ||
- this->operation == ir_binop_rshift ||
- this->operation == ir_triop_bitfield_extract);
+ switch (this->operation) {
+ case ir_binop_lshift:
+ case ir_binop_rshift:
+ case ir_binop_vector_extract:
+ case ir_triop_bitfield_extract:
+ break;
+
+ default:
+ assert(op[0]->type->base_type == op[1]->type->base_type);
+ break;
+ }
bool op0_scalar = op[0]->type->is_scalar();
bool op1_scalar = op[1] != NULL && op[1]->type->is_scalar();
@@ -1231,6 +1238,29 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
}
break;
+ case ir_binop_vector_extract: {
+ const int c = CLAMP(op[1]->value.i[0], 0,
+ (int) op[0]->type->vector_elements - 1);
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[0] = op[0]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[0] = op[0]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[0] = op[0]->value.f[c];
+ break;
+ case GLSL_TYPE_BOOL:
+ data.b[0] = op[0]->value.b[c];
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ }
+
case ir_binop_bit_xor:
for (unsigned c = 0, c0 = 0, c1 = 0;
c < components;
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
index 26f09c71f63..03480ccd364 100644
--- a/src/glsl/ir_validate.cpp
+++ b/src/glsl/ir_validate.cpp
@@ -487,6 +487,12 @@ ir_validate::visit_leave(ir_expression *ir)
assert(ir->operands[1]->type == glsl_type::uint_type);
break;
+ case ir_binop_vector_extract:
+ assert(ir->operands[0]->type->is_vector());
+ assert(ir->operands[1]->type->is_scalar()
+ && ir->operands[1]->type->is_integer());
+ break;
+
case ir_triop_lrp:
assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
assert(ir->operands[0]->type == ir->operands[1]->type);
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 258b864f559..98281140aae 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -1489,6 +1489,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]);
break;
+ case ir_binop_vector_extract:
case ir_binop_bfm:
case ir_triop_bfi:
case ir_triop_bitfield_extract: