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 <ian.d.romanick@intel.com> Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
@@ -399,6 +399,10 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
|
|||||||
this->type = op0->type;
|
this->type = op0->type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ir_binop_vector_extract:
|
||||||
|
this->type = op0->type->get_scalar_type();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(!"not reached: missing automatic type setup for ir_expression");
|
assert(!"not reached: missing automatic type setup for ir_expression");
|
||||||
this->type = glsl_type::float_type;
|
this->type = glsl_type::float_type;
|
||||||
@@ -510,6 +514,7 @@ static const char *const operator_strs[] = {
|
|||||||
"packHalf2x16_split",
|
"packHalf2x16_split",
|
||||||
"bfm",
|
"bfm",
|
||||||
"ubo_load",
|
"ubo_load",
|
||||||
|
"vector_extract",
|
||||||
"lrp",
|
"lrp",
|
||||||
"bfi",
|
"bfi",
|
||||||
"bitfield_extract",
|
"bitfield_extract",
|
||||||
|
@@ -1135,10 +1135,18 @@ enum ir_expression_operation {
|
|||||||
*/
|
*/
|
||||||
ir_binop_ubo_load,
|
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.
|
* 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,
|
ir_triop_lrp,
|
||||||
|
|
||||||
|
@@ -391,10 +391,17 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (op[1] != NULL)
|
if (op[1] != NULL)
|
||||||
assert(op[0]->type->base_type == op[1]->type->base_type ||
|
switch (this->operation) {
|
||||||
this->operation == ir_binop_lshift ||
|
case ir_binop_lshift:
|
||||||
this->operation == ir_binop_rshift ||
|
case ir_binop_rshift:
|
||||||
this->operation == ir_triop_bitfield_extract);
|
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 op0_scalar = op[0]->type->is_scalar();
|
||||||
bool op1_scalar = op[1] != NULL && op[1]->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;
|
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:
|
case ir_binop_bit_xor:
|
||||||
for (unsigned c = 0, c0 = 0, c1 = 0;
|
for (unsigned c = 0, c0 = 0, c1 = 0;
|
||||||
c < components;
|
c < components;
|
||||||
|
@@ -487,6 +487,12 @@ ir_validate::visit_leave(ir_expression *ir)
|
|||||||
assert(ir->operands[1]->type == glsl_type::uint_type);
|
assert(ir->operands[1]->type == glsl_type::uint_type);
|
||||||
break;
|
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:
|
case ir_triop_lrp:
|
||||||
assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
|
assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
|
||||||
assert(ir->operands[0]->type == ir->operands[1]->type);
|
assert(ir->operands[0]->type == ir->operands[1]->type);
|
||||||
|
@@ -1489,6 +1489,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
|||||||
emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]);
|
emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ir_binop_vector_extract:
|
||||||
case ir_binop_bfm:
|
case ir_binop_bfm:
|
||||||
case ir_triop_bfi:
|
case ir_triop_bfi:
|
||||||
case ir_triop_bitfield_extract:
|
case ir_triop_bitfield_extract:
|
||||||
|
Reference in New Issue
Block a user