summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/i965/brw_fs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_fs.cpp')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp146
1 files changed, 61 insertions, 85 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 4eead32cbb..22e6e2e736 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -89,6 +89,9 @@ brw_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
GLboolean
brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
{
+ struct brw_context *brw = brw_context(ctx);
+ struct intel_context *intel = &brw->intel;
+
struct brw_shader *shader =
(struct brw_shader *)prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
if (shader != NULL) {
@@ -107,7 +110,15 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
SUB_TO_ADD_NEG |
EXP_TO_EXP2 |
LOG_TO_LOG2);
+
+ /* Pre-gen6 HW can only nest if-statements 16 deep. Beyond this,
+ * if-statements need to be flattened.
+ */
+ if (intel->gen < 6)
+ lower_if_to_cond_assign(shader->ir, 16);
+
do_lower_texture_projection(shader->ir);
+ do_vec_index_to_cond_assign(shader->ir);
brw_do_cubemap_normalize(shader->ir);
do {
@@ -775,6 +786,30 @@ fs_visitor::try_emit_saturate(ir_expression *ir)
return true;
}
+static uint32_t
+brw_conditional_for_comparison(unsigned int op)
+{
+ switch (op) {
+ case ir_binop_less:
+ return BRW_CONDITIONAL_L;
+ case ir_binop_greater:
+ return BRW_CONDITIONAL_G;
+ case ir_binop_lequal:
+ return BRW_CONDITIONAL_LE;
+ case ir_binop_gequal:
+ return BRW_CONDITIONAL_GE;
+ case ir_binop_equal:
+ case ir_binop_all_equal: /* same as equal for scalars */
+ return BRW_CONDITIONAL_Z;
+ case ir_binop_nequal:
+ case ir_binop_any_nequal: /* same as nequal for scalars */
+ return BRW_CONDITIONAL_NZ;
+ default:
+ assert(!"not reached: bad operation for comparison");
+ return BRW_CONDITIONAL_NZ;
+ }
+}
+
void
fs_visitor::visit(ir_expression *ir)
{
@@ -890,35 +925,20 @@ fs_visitor::visit(ir_expression *ir)
break;
case ir_binop_less:
- inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_L;
- emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
- break;
case ir_binop_greater:
- inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_G;
- emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
- break;
case ir_binop_lequal:
- inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_LE;
- emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
- break;
case ir_binop_gequal:
- inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_GE;
- emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
- break;
case ir_binop_equal:
- case ir_binop_all_equal: /* same as nequal for scalars */
- inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_Z;
- emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
- break;
+ case ir_binop_all_equal:
case ir_binop_nequal:
- case ir_binop_any_nequal: /* same as nequal for scalars */
- inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
+ case ir_binop_any_nequal:
+ temp = this->result;
+ /* original gen4 does implicit conversion before comparison. */
+ if (intel->gen < 5)
+ temp.type = op[0].type;
+
+ inst = emit(fs_inst(BRW_OPCODE_CMP, temp, op[0], op[1]));
+ inst->conditional_mod = brw_conditional_for_comparison(ir->operation);
emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
break;
@@ -963,7 +983,12 @@ fs_visitor::visit(ir_expression *ir)
break;
case ir_unop_f2b:
case ir_unop_i2b:
- inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], fs_reg(0.0f)));
+ temp = this->result;
+ /* original gen4 does implicit conversion before comparison. */
+ if (intel->gen < 5)
+ temp.type = op[0].type;
+
+ inst = emit(fs_inst(BRW_OPCODE_CMP, temp, op[0], fs_reg(0.0f)));
inst->conditional_mod = BRW_CONDITIONAL_NZ;
inst = emit(fs_inst(BRW_OPCODE_AND, this->result,
this->result, fs_reg(1)));
@@ -1546,7 +1571,7 @@ fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir)
inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d,
op[0], fs_reg(0.0f)));
} else {
- inst = emit(fs_inst(BRW_OPCODE_MOV, reg_null_d, op[0]));
+ inst = emit(fs_inst(BRW_OPCODE_MOV, reg_null_f, op[0]));
}
inst->conditional_mod = BRW_CONDITIONAL_NZ;
break;
@@ -1561,31 +1586,18 @@ fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir)
break;
case ir_binop_greater:
- inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_G;
- break;
case ir_binop_gequal:
- inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_GE;
- break;
case ir_binop_less:
- inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_L;
- break;
case ir_binop_lequal:
- inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_LE;
- break;
case ir_binop_equal:
case ir_binop_all_equal:
- inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_Z;
- break;
case ir_binop_nequal:
case ir_binop_any_nequal:
- inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
+ inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_cmp, op[0], op[1]));
+ inst->conditional_mod =
+ brw_conditional_for_comparison(expr->operation);
break;
+
default:
assert(!"not reached");
this->fail = true;
@@ -1664,30 +1676,16 @@ fs_visitor::emit_if_gen6(ir_if *ir)
return;
case ir_binop_greater:
- inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_G;
- return;
case ir_binop_gequal:
- inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_GE;
- return;
case ir_binop_less:
- inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_L;
- return;
case ir_binop_lequal:
- inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_LE;
- return;
case ir_binop_equal:
case ir_binop_all_equal:
- inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_Z;
- return;
case ir_binop_nequal:
case ir_binop_any_nequal:
inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1]));
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
+ inst->conditional_mod =
+ brw_conditional_for_comparison(expr->operation);
return;
default:
assert(!"not reached");
@@ -1769,32 +1767,9 @@ fs_visitor::visit(ir_loop *ir)
this->base_ir = ir->to;
ir->to->accept(this);
- fs_inst *inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d,
+ fs_inst *inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_cmp,
counter, this->result));
- switch (ir->cmp) {
- case ir_binop_equal:
- inst->conditional_mod = BRW_CONDITIONAL_Z;
- break;
- case ir_binop_nequal:
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
- break;
- case ir_binop_gequal:
- inst->conditional_mod = BRW_CONDITIONAL_GE;
- break;
- case ir_binop_lequal:
- inst->conditional_mod = BRW_CONDITIONAL_LE;
- break;
- case ir_binop_greater:
- inst->conditional_mod = BRW_CONDITIONAL_G;
- break;
- case ir_binop_less:
- inst->conditional_mod = BRW_CONDITIONAL_L;
- break;
- default:
- assert(!"not reached: unknown loop condition");
- this->fail = true;
- break;
- }
+ inst->conditional_mod = brw_conditional_for_comparison(ir->cmp);
inst = emit(fs_inst(BRW_OPCODE_BREAK));
inst->predicated = true;
@@ -2163,7 +2138,8 @@ fs_visitor::generate_fb_write(fs_inst *inst)
inst->target,
inst->mlen,
0,
- eot);
+ eot,
+ inst->header_present);
}
void