summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-06-03 16:37:17 -0700
committerEric Anholt <eric@anholt.net>2010-06-24 15:05:21 -0700
commit8364fc85b8273b4d0f2ecebe7e0085e250d29990 (patch)
treed32acea2aedcdac6de93029800ff1ea854c62f98
parent76720647566db8126b9f29a0e705ba03ebcdad27 (diff)
ir_to_mesa: Handle a limited subset of matrix multiplication.
glsl-mvp.vert now generates believable code, and mesa mode fails only 5 tests that master doesn't. I must have left out some asserts...
-rw-r--r--ir_to_mesa.cpp253
1 files changed, 137 insertions, 116 deletions
diff --git a/ir_to_mesa.cpp b/ir_to_mesa.cpp
index 2ec2b11f03..b496a87df5 100644
--- a/ir_to_mesa.cpp
+++ b/ir_to_mesa.cpp
@@ -92,9 +92,7 @@ public:
temp_entry *find_variable_storage(ir_variable *var);
- ir_to_mesa_src_reg get_temp(int size);
-
- ir_to_mesa_src_reg get_temp_for_var(ir_variable *var);
+ ir_to_mesa_src_reg get_temp(const glsl_type *type);
struct ir_to_mesa_src_reg src_reg_for_float(float val);
@@ -180,6 +178,56 @@ static int swizzle_for_size(int size)
return size_swizzles[size - 1];
}
+/* This list should match up with builtin_variables.h */
+static const struct {
+ const char *name;
+ int file;
+ int index;
+} builtin_var_to_mesa_reg[] = {
+ /* core_vs */
+ {"gl_Position", PROGRAM_OUTPUT, VERT_RESULT_HPOS},
+ {"gl_PointSize", PROGRAM_OUTPUT, VERT_RESULT_PSIZ},
+
+ /* core_fs */
+ {"gl_FragCoord", PROGRAM_INPUT, FRAG_ATTRIB_WPOS},
+ {"gl_FrontFacing", PROGRAM_INPUT, FRAG_ATTRIB_FACE},
+ {"gl_FragColor", PROGRAM_OUTPUT, FRAG_ATTRIB_COL0},
+ {"gl_FragDepth", PROGRAM_UNDEFINED, FRAG_ATTRIB_WPOS}, /* FINISHME: WPOS.z */
+
+ /* 110_deprecated_fs */
+ {"gl_Color", PROGRAM_INPUT, FRAG_ATTRIB_COL0},
+ {"gl_SecondaryColor", PROGRAM_INPUT, FRAG_ATTRIB_COL1},
+ {"gl_FogFragCoord", PROGRAM_INPUT, FRAG_ATTRIB_FOGC},
+ {"gl_TexCoord", PROGRAM_INPUT, FRAG_ATTRIB_TEX0}, /* array */
+
+ /* 110_deprecated_vs */
+ {"gl_Vertex", PROGRAM_INPUT, VERT_ATTRIB_POS},
+ {"gl_Normal", PROGRAM_INPUT, VERT_ATTRIB_NORMAL},
+ {"gl_Color", PROGRAM_INPUT, VERT_ATTRIB_COLOR0},
+ {"gl_SecondaryColor", PROGRAM_INPUT, VERT_ATTRIB_COLOR1},
+ {"gl_MultiTexCoord0", PROGRAM_INPUT, VERT_ATTRIB_TEX0},
+ {"gl_MultiTexCoord1", PROGRAM_INPUT, VERT_ATTRIB_TEX1},
+ {"gl_MultiTexCoord2", PROGRAM_INPUT, VERT_ATTRIB_TEX2},
+ {"gl_MultiTexCoord3", PROGRAM_INPUT, VERT_ATTRIB_TEX3},
+ {"gl_MultiTexCoord4", PROGRAM_INPUT, VERT_ATTRIB_TEX4},
+ {"gl_MultiTexCoord5", PROGRAM_INPUT, VERT_ATTRIB_TEX5},
+ {"gl_MultiTexCoord6", PROGRAM_INPUT, VERT_ATTRIB_TEX6},
+ {"gl_MultiTexCoord7", PROGRAM_INPUT, VERT_ATTRIB_TEX7},
+ {"gl_TexCoord", PROGRAM_OUTPUT, VERT_RESULT_TEX0}, /* array */
+ {"gl_FogCoord", PROGRAM_INPUT, VERT_RESULT_FOGC},
+ /*{"gl_ClipVertex", PROGRAM_OUTPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
+ {"gl_FrontColor", PROGRAM_OUTPUT, VERT_RESULT_COL0},
+ {"gl_BackColor", PROGRAM_OUTPUT, VERT_RESULT_BFC0},
+ {"gl_FrontSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_COL1},
+ {"gl_BackSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_BFC1},
+ {"gl_FogFragCoord", PROGRAM_OUTPUT, VERT_RESULT_FOGC},
+
+ /* 130_vs */
+ /*{"gl_VertexID", PROGRAM_INPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
+
+ {"gl_FragData", PROGRAM_OUTPUT, FRAG_RESULT_DATA0}, /* array */
+};
+
ir_to_mesa_instruction *
ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
enum prog_opcode op,
@@ -307,20 +355,22 @@ ir_to_mesa_visitor::src_reg_for_float(float val)
* pass over the Mesa IR later.
*/
ir_to_mesa_src_reg
-ir_to_mesa_visitor::get_temp(int size)
+ir_to_mesa_visitor::get_temp(const glsl_type *type)
{
ir_to_mesa_src_reg src_reg;
int swizzle[4];
int i;
+ assert(!type->is_array());
+
src_reg.file = PROGRAM_TEMPORARY;
- src_reg.index = this->next_temp++;
+ src_reg.index = type->matrix_columns;
src_reg.reladdr = false;
- for (i = 0; i < size; i++)
+ for (i = 0; i < type->vector_elements; i++)
swizzle[i] = i;
for (; i < 4; i++)
- swizzle[i] = size - 1;
+ swizzle[i] = type->vector_elements - 1;
src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
swizzle[2], swizzle[3]);
@@ -377,41 +427,10 @@ ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
return NULL;
}
-ir_to_mesa_src_reg
-ir_to_mesa_visitor::get_temp_for_var(ir_variable *var)
-{
- temp_entry *entry;
- ir_to_mesa_src_reg src_reg;
-
- entry = find_variable_storage(var);
- if (!entry) {
- entry = new temp_entry(var, PROGRAM_TEMPORARY, this->next_temp);
- this->variable_storage.push_tail(entry);
-
- next_temp += type_size(var->type);
- }
-
- src_reg.file = entry->file;
- src_reg.index = entry->index;
- src_reg.swizzle = swizzle_for_size(var->type->vector_elements);
- src_reg.reladdr = false;
-
- return src_reg;
-}
-
void
ir_to_mesa_visitor::visit(ir_variable *ir)
{
- if (ir->mode == ir_var_uniform) {
- temp_entry *entry = find_variable_storage(ir);
-
- if (!entry) {
- entry = new temp_entry(ir, PROGRAM_UNIFORM, this->next_uniform);
- this->variable_storage.push_tail(entry);
-
- this->next_uniform += type_size(ir->type);
- }
- }
+ (void)ir;
}
void
@@ -497,6 +516,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
exit(1);
}
op[operand] = this->result;
+
+ /* Only expression implemented for matrices yet */
+ assert(!ir->operands[operand]->type->is_matrix() ||
+ ir->operation == ir_binop_mul);
}
this->result.file = PROGRAM_UNDEFINED;
@@ -504,7 +527,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
/* Storage for our result. Ideally for an assignment we'd be using
* the actual storage for the result here, instead.
*/
- result_src = get_temp(ir->type->vector_elements);
+ result_src = get_temp(ir->type);
/* convenience for the emit functions below. */
result_dst = ir_to_mesa_dst_reg_from_src(result_src);
/* Limit writes to the channels that will be used by result_src later.
@@ -547,7 +570,34 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]);
break;
case ir_binop_mul:
- ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
+ if (ir->operands[0]->type->is_matrix() &&
+ !ir->operands[1]->type->is_matrix()) {
+ if (ir->operands[0]->type->is_scalar()) {
+ ir_to_mesa_dst_reg dst_column = result_dst;
+ ir_to_mesa_src_reg src_column = op[0];
+ for (int i = 0; i < ir->operands[0]->type->matrix_columns; i++) {
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ dst_column, src_column, op[1]);
+ dst_column.index++;
+ src_column.index++;
+ }
+ } else {
+ ir_to_mesa_dst_reg dst_chan = result_dst;
+ ir_to_mesa_src_reg src_column = op[0];
+ ir_to_mesa_src_reg src_chan = op[1];
+ for (int i = 0; i < ir->operands[0]->type->matrix_columns; i++) {
+ dst_chan.writemask = (1 << i);
+ src_chan.swizzle = MAKE_SWIZZLE4(i, i, i, i);
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ dst_chan, src_column, src_chan);
+ src_column.index++;
+ }
+ }
+ } else {
+ assert(!ir->operands[0]->type->is_matrix());
+ assert(!ir->operands[1]->type->is_matrix());
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
+ }
break;
case ir_binop_div:
ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[1]);
@@ -705,92 +755,63 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
this->result = src_reg;
}
-/* This list should match up with builtin_variables.h */
-static const struct {
- const char *name;
- int file;
- int index;
-} builtin_var_to_mesa_reg[] = {
- /* core_vs */
- {"gl_Position", PROGRAM_OUTPUT, VERT_RESULT_HPOS},
- {"gl_PointSize", PROGRAM_OUTPUT, VERT_RESULT_PSIZ},
-
- /* core_fs */
- {"gl_FragCoord", PROGRAM_INPUT, FRAG_ATTRIB_WPOS},
- {"gl_FrontFacing", PROGRAM_INPUT, FRAG_ATTRIB_FACE},
- {"gl_FragColor", PROGRAM_OUTPUT, FRAG_ATTRIB_COL0},
- {"gl_FragDepth", PROGRAM_UNDEFINED, FRAG_ATTRIB_WPOS}, /* FINISHME: WPOS.z */
-
- /* 110_deprecated_fs */
- {"gl_Color", PROGRAM_INPUT, FRAG_ATTRIB_COL0},
- {"gl_SecondaryColor", PROGRAM_INPUT, FRAG_ATTRIB_COL1},
- {"gl_FogFragCoord", PROGRAM_INPUT, FRAG_ATTRIB_FOGC},
- {"gl_TexCoord", PROGRAM_INPUT, FRAG_ATTRIB_TEX0}, /* array */
-
- /* 110_deprecated_vs */
- {"gl_Vertex", PROGRAM_INPUT, VERT_ATTRIB_POS},
- {"gl_Normal", PROGRAM_INPUT, VERT_ATTRIB_NORMAL},
- {"gl_Color", PROGRAM_INPUT, VERT_ATTRIB_COLOR0},
- {"gl_SecondaryColor", PROGRAM_INPUT, VERT_ATTRIB_COLOR1},
- {"gl_MultiTexCoord0", PROGRAM_INPUT, VERT_ATTRIB_TEX0},
- {"gl_MultiTexCoord1", PROGRAM_INPUT, VERT_ATTRIB_TEX1},
- {"gl_MultiTexCoord2", PROGRAM_INPUT, VERT_ATTRIB_TEX2},
- {"gl_MultiTexCoord3", PROGRAM_INPUT, VERT_ATTRIB_TEX3},
- {"gl_MultiTexCoord4", PROGRAM_INPUT, VERT_ATTRIB_TEX4},
- {"gl_MultiTexCoord5", PROGRAM_INPUT, VERT_ATTRIB_TEX5},
- {"gl_MultiTexCoord6", PROGRAM_INPUT, VERT_ATTRIB_TEX6},
- {"gl_MultiTexCoord7", PROGRAM_INPUT, VERT_ATTRIB_TEX7},
- {"gl_TexCoord", PROGRAM_OUTPUT, VERT_RESULT_TEX0}, /* array */
- {"gl_FogCoord", PROGRAM_INPUT, VERT_RESULT_FOGC},
- /*{"gl_ClipVertex", PROGRAM_OUTPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
- {"gl_FrontColor", PROGRAM_OUTPUT, VERT_RESULT_COL0},
- {"gl_BackColor", PROGRAM_OUTPUT, VERT_RESULT_BFC0},
- {"gl_FrontSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_COL1},
- {"gl_BackSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_BFC1},
- {"gl_FogFragCoord", PROGRAM_OUTPUT, VERT_RESULT_FOGC},
-
- /* 130_vs */
- /*{"gl_VertexID", PROGRAM_INPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */
-
- {"gl_FragData", PROGRAM_OUTPUT, FRAG_RESULT_DATA0}, /* array */
-};
-
void
ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
{
ir_to_mesa_src_reg src_reg;
+ temp_entry *entry = find_variable_storage(ir->var);
+ unsigned int i;
+ bool var_in;
- /* By the time we make it to this stage, matrices should be broken down
- * to vectors.
- */
- assert(!ir->var->type->is_matrix());
-
- if (strncmp(ir->var->name, "gl_", 3) == 0) {
- unsigned int i;
- bool var_in = (ir->var->mode == ir_var_in ||
- ir->var->mode == ir_var_inout);
+ if (!entry) {
+ switch (ir->var->mode) {
+ case ir_var_uniform:
+ entry = new temp_entry(ir->var, PROGRAM_UNIFORM, this->next_uniform);
+ this->variable_storage.push_tail(entry);
- for (i = 0; i < ARRAY_SIZE(builtin_var_to_mesa_reg); i++) {
- bool in = builtin_var_to_mesa_reg[i].file == PROGRAM_INPUT;
+ this->next_uniform += type_size(ir->var->type);
+ break;
+ case ir_var_in:
+ case ir_var_out:
+ case ir_var_inout:
+ var_in = (ir->var->mode == ir_var_in ||
+ ir->var->mode == ir_var_inout);
+
+ for (i = 0; i < ARRAY_SIZE(builtin_var_to_mesa_reg); i++) {
+ bool in = builtin_var_to_mesa_reg[i].file == PROGRAM_INPUT;
+
+ if (strcmp(ir->var->name, builtin_var_to_mesa_reg[i].name) == 0 &&
+ !(var_in ^ in))
+ break;
+ }
+ if (i == ARRAY_SIZE(builtin_var_to_mesa_reg)) {
+ printf("Failed to find builtin for %s variable %s\n",
+ var_in ? "in" : "out",
+ ir->var->name);
+ abort();
+ }
+ entry = new temp_entry(ir->var,
+ builtin_var_to_mesa_reg[i].file,
+ builtin_var_to_mesa_reg[i].index);
+ break;
+ case ir_var_auto:
+ entry = new temp_entry(ir->var, PROGRAM_TEMPORARY, this->next_temp);
+ this->variable_storage.push_tail(entry);
- if (strcmp(ir->var->name, builtin_var_to_mesa_reg[i].name) == 0 &&
- !(var_in ^ in))
- break;
+ next_temp += type_size(ir->var->type);
+ break;
}
- if (i == ARRAY_SIZE(builtin_var_to_mesa_reg)) {
- printf("Failed to find builtin for %s variable %s\n",
- var_in ? "in" : "out",
- ir->var->name);
- abort();
+
+ if (!entry) {
+ printf("Failed to make storage for %s\n", ir->var->name);
+ exit(1);
}
- src_reg.file = builtin_var_to_mesa_reg[i].file;
- src_reg.index = builtin_var_to_mesa_reg[i].index;
- } else {
- src_reg = get_temp_for_var(ir->var);
}
+ src_reg.file = entry->file;
+ src_reg.index = entry->index;
/* If the type is smaller than a vec4, replicate the last channel out. */
- src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
+ src_reg.swizzle = swizzle_for_size(ir->var->type->vector_elements);
src_reg.reladdr = false;
src_reg.negate = 0;
@@ -836,7 +857,7 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
this->result);
- this->result = get_temp(ir->type->vector_elements);
+ this->result = get_temp(ir->type);
ir_to_mesa_emit_op1(ir, OPCODE_MOV,
ir_to_mesa_dst_reg_from_src(this->result),
src_reg);