summaryrefslogtreecommitdiff
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/shader/ir_to_mesa.cpp96
1 files changed, 67 insertions, 29 deletions
diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp
index 110fc100db..f4a8ceb09e 100644
--- a/src/mesa/shader/ir_to_mesa.cpp
+++ b/src/mesa/shader/ir_to_mesa.cpp
@@ -61,7 +61,8 @@ typedef struct ir_to_mesa_src_reg {
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
int negate; /**< NEGATE_XYZW mask from mesa */
- bool reladdr; /**< Register index should be offset by address reg. */
+ /** Register index should be offset by the integer in this reg. */
+ ir_to_mesa_src_reg *reladdr;
} ir_to_mesa_src_reg;
typedef struct ir_to_mesa_dst_reg {
@@ -69,6 +70,8 @@ typedef struct ir_to_mesa_dst_reg {
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
GLuint cond_mask:4;
+ /** Register index should be offset by the integer in this reg. */
+ ir_to_mesa_src_reg *reladdr;
} ir_to_mesa_dst_reg;
extern ir_to_mesa_src_reg ir_to_mesa_undef;
@@ -111,6 +114,8 @@ public:
temp_entry *find_variable_storage(ir_variable *var);
ir_to_mesa_src_reg get_temp(const glsl_type *type);
+ void reladdr_to_temp(ir_instruction *ir,
+ ir_to_mesa_src_reg *reg, int *num_reladdr);
struct ir_to_mesa_src_reg src_reg_for_float(float val);
@@ -191,15 +196,15 @@ public:
};
ir_to_mesa_src_reg ir_to_mesa_undef = {
- PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, NEGATE_NONE, false,
+ PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, NEGATE_NONE, NULL,
};
ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
- PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR
+ PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR, NULL,
};
ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
- PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR
+ PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL
};
static int swizzle_for_size(int size)
@@ -223,6 +228,28 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
ir_to_mesa_src_reg src2)
{
ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction();
+ int num_reladdr = 0;
+
+ /* If we have to do relative addressing, we want to load the ARL
+ * reg directly for one of the regs, and preload the other reladdr
+ * sources into temps.
+ */
+ num_reladdr += dst.reladdr != NULL;
+ num_reladdr += src0.reladdr != NULL;
+ num_reladdr += src1.reladdr != NULL;
+ num_reladdr += src2.reladdr != NULL;
+
+ reladdr_to_temp(ir, &src2, &num_reladdr);
+ reladdr_to_temp(ir, &src1, &num_reladdr);
+ reladdr_to_temp(ir, &src0, &num_reladdr);
+
+ if (dst.reladdr) {
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
+ *dst.reladdr);
+
+ num_reladdr--;
+ }
+ assert(num_reladdr == 0);
inst->op = op;
inst->dst_reg = dst;
@@ -285,6 +312,7 @@ ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)
dst_reg.index = reg.index;
dst_reg.writemask = WRITEMASK_XYZW;
dst_reg.cond_mask = COND_TR;
+ dst_reg.reladdr = reg.reladdr;
return dst_reg;
}
@@ -298,7 +326,7 @@ ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg)
src_reg.index = reg.index;
src_reg.swizzle = SWIZZLE_XYZW;
src_reg.negate = 0;
- src_reg.reladdr = 0;
+ src_reg.reladdr = reg.reladdr;
return src_reg;
}
@@ -378,7 +406,7 @@ ir_to_mesa_visitor::src_reg_for_float(float val)
src_reg.file = PROGRAM_CONSTANT;
src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
&val, 1, &src_reg.swizzle);
- src_reg.reladdr = GL_FALSE;
+ src_reg.reladdr = NULL;
src_reg.negate = 0;
return src_reg;
@@ -435,7 +463,7 @@ ir_to_mesa_visitor::get_temp(const glsl_type *type)
src_reg.file = PROGRAM_TEMPORARY;
src_reg.index = next_temp;
- src_reg.reladdr = false;
+ src_reg.reladdr = NULL;
next_temp += type_size(type);
for (i = 0; i < type->vector_elements; i++)
@@ -558,6 +586,26 @@ ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)
}
void
+ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,
+ ir_to_mesa_src_reg *reg, int *num_reladdr)
+{
+ if (!reg->reladdr)
+ return;
+
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, *reg->reladdr);
+
+ if (*num_reladdr != 1) {
+ ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV,
+ ir_to_mesa_dst_reg_from_src(temp), *reg);
+ *reg = temp;
+ }
+
+ (*num_reladdr)--;
+}
+
+void
ir_to_mesa_visitor::visit(ir_expression *ir)
{
unsigned int operand;
@@ -1045,7 +1093,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
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->var->type->vector_elements);
- src_reg.reladdr = false;
+ src_reg.reladdr = NULL;
src_reg.negate = 0;
this->result = src_reg;
@@ -1077,7 +1125,7 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
src_reg.negate = 0;
if (index) {
- src_reg.reladdr = GL_FALSE;
+ src_reg.reladdr = NULL;
} else {
ir_to_mesa_src_reg index_reg = get_temp(glsl_type::float_type);
@@ -1086,9 +1134,8 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
ir_to_mesa_dst_reg_from_src(index_reg),
this->result, src_reg_for_float(element_size));
- src_reg.reladdr = true;
- ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
- index_reg);
+ src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
+ memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
}
this->result = src_reg;
@@ -1126,17 +1173,10 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
this->result, src_reg_for_float(element_size));
}
- /* FINISHME: This doesn't work when we're trying to do the LHS
- * of an assignment.
- */
- src_reg.reladdr = true;
- ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
- index_reg);
-
- 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);
+ src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
+ memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
+
+ this->result = src_reg;
}
}
@@ -1183,9 +1223,6 @@ get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v)
/* This should have been handled by ir_vec_index_to_cond_assign */
if (deref_array) {
assert(!deref_array->array->type->is_vector());
-
- /* We don't handle relative addressing on the LHS yet. */
- assert(deref_array->array_index->constant_expression_value() != NULL);
}
/* Use the rvalue deref handler for the most part. We'll ignore
@@ -1313,7 +1350,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
values,
ir->type->vector_elements,
&src_reg.swizzle);
- src_reg.reladdr = false;
+ src_reg.reladdr = NULL;
src_reg.negate = 0;
ir_to_mesa_emit_op1(ir, OPCODE_MOV, mat_column, src_reg);
@@ -1350,7 +1387,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
values, ir->type->vector_elements,
&src_reg.swizzle);
- src_reg.reladdr = false;
+ src_reg.reladdr = NULL;
src_reg.negate = 0;
this->result = src_reg;
@@ -1578,7 +1615,7 @@ mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
assert(reg.index < (1 << INST_INDEX_BITS) - 1);
mesa_reg.Index = reg.index;
mesa_reg.Swizzle = reg.swizzle;
- mesa_reg.RelAddr = reg.reladdr;
+ mesa_reg.RelAddr = reg.reladdr != NULL;
mesa_reg.Negate = reg.negate;
mesa_reg.Abs = 0;
@@ -1813,6 +1850,7 @@ get_mesa_program(GLcontext *ctx, void *mem_ctx, struct gl_shader *shader)
mesa_inst->DstReg.Index = inst->dst_reg.index;
mesa_inst->DstReg.CondMask = inst->dst_reg.cond_mask;
mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask;
+ mesa_inst->DstReg.RelAddr = inst->dst_reg.reladdr != NULL;
mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);
mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);
mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]);