}
#include "brw_shader.h"
#include "brw_fs.h"
-#include "../glsl/glsl_types.h"
-#include "../glsl/ir_optimization.h"
-#include "../glsl/ir_print_visitor.h"
+#include "glsl/glsl_types.h"
+#include "glsl/ir_optimization.h"
+#include "glsl/ir_print_visitor.h"
void
fs_visitor::visit(ir_variable *ir)
this->result.type = brw_type_for_base_type(ir->type);
if (index) {
- assert(this->result.file == UNIFORM ||
- (this->result.file == GRF &&
- this->result.reg != 0));
+ assert(this->result.file == UNIFORM || this->result.file == GRF);
this->result.reg_offset += index->value.i[0] * element_size;
} else {
assert(!"FINISHME: non-constant array element");
if (!sat_val)
return false;
- this->result = reg_undef;
sat_val->accept(this);
fs_reg src = this->result;
if (try_emit_saturate(ir))
return;
- /* This is where our caller would like us to put the result, if possible. */
- fs_reg saved_result_storage = this->result;
-
for (operand = 0; operand < ir->get_num_operands(); operand++) {
- this->result = reg_undef;
ir->operands[operand]->accept(this);
if (this->result.file == BAD_FILE) {
ir_print_visitor v;
assert(!ir->operands[operand]->type->is_vector());
}
- /* Inherit storage from our parent if possible, and otherwise we
- * alloc a temporary.
+ /* Storage for our result. If our result goes into an assignment, it will
+ * just get copy-propagated out, so no worries.
*/
- if (saved_result_storage.file == BAD_FILE) {
- this->result = fs_reg(this, ir->type);
- } else {
- this->result = saved_result_storage;
- }
+ this->result = fs_reg(this, ir->type);
switch (ir->operation) {
case ir_unop_logic_not:
case ir_unop_sign:
temp = fs_reg(this, ir->type);
- /* Unalias the destination. (imagine a = sign(a)) */
- this->result = fs_reg(this, ir->type);
-
emit(BRW_OPCODE_MOV, this->result, fs_reg(0.0f));
inst = emit(BRW_OPCODE_CMP, reg_null_f, op[0], fs_reg(0.0f));
break;
case ir_unop_rcp:
- emit_math(FS_OPCODE_RCP, this->result, op[0]);
+ emit_math(SHADER_OPCODE_RCP, this->result, op[0]);
break;
case ir_unop_exp2:
- emit_math(FS_OPCODE_EXP2, this->result, op[0]);
+ emit_math(SHADER_OPCODE_EXP2, this->result, op[0]);
break;
case ir_unop_log2:
- emit_math(FS_OPCODE_LOG2, this->result, op[0]);
+ emit_math(SHADER_OPCODE_LOG2, this->result, op[0]);
break;
case ir_unop_exp:
case ir_unop_log:
break;
case ir_unop_sin:
case ir_unop_sin_reduced:
- emit_math(FS_OPCODE_SIN, this->result, op[0]);
+ emit_math(SHADER_OPCODE_SIN, this->result, op[0]);
break;
case ir_unop_cos:
case ir_unop_cos_reduced:
- emit_math(FS_OPCODE_COS, this->result, op[0]);
+ emit_math(SHADER_OPCODE_COS, this->result, op[0]);
break;
case ir_unop_dFdx:
break;
case ir_binop_mul:
- emit(BRW_OPCODE_MUL, this->result, op[0], op[1]);
+ if (ir->type->is_integer()) {
+ /* For integer multiplication, the MUL uses the low 16 bits
+ * of one of the operands (src0 on gen6, src1 on gen7). The
+ * MACH accumulates in the contribution of the upper 16 bits
+ * of that operand.
+ *
+ * FINISHME: Emit just the MUL if we know an operand is small
+ * enough.
+ */
+ struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_D);
+
+ emit(BRW_OPCODE_MUL, acc, op[0], op[1]);
+ emit(BRW_OPCODE_MACH, reg_null_d, op[0], op[1]);
+ emit(BRW_OPCODE_MOV, this->result, fs_reg(acc));
+ } else {
+ emit(BRW_OPCODE_MUL, this->result, op[0], op[1]);
+ }
break;
case ir_binop_div:
assert(!"not reached: should be handled by ir_div_to_mul_rcp");
break;
case ir_unop_sqrt:
- emit_math(FS_OPCODE_SQRT, this->result, op[0]);
+ emit_math(SHADER_OPCODE_SQRT, this->result, op[0]);
break;
case ir_unop_rsq:
- emit_math(FS_OPCODE_RSQ, this->result, op[0]);
+ emit_math(SHADER_OPCODE_RSQ, this->result, op[0]);
break;
+ case ir_unop_i2u:
+ op[0].type = BRW_REGISTER_TYPE_UD;
+ this->result = op[0];
+ break;
+ case ir_unop_u2i:
+ op[0].type = BRW_REGISTER_TYPE_D;
+ this->result = op[0];
+ break;
case ir_unop_i2f:
+ case ir_unop_u2f:
case ir_unop_b2f:
case ir_unop_b2i:
case ir_unop_f2i:
break;
case ir_binop_pow:
- emit_math(FS_OPCODE_POW, this->result, op[0], op[1]);
+ emit_math(SHADER_OPCODE_POW, this->result, op[0], op[1]);
break;
case ir_unop_bit_not:
inst = emit(BRW_OPCODE_OR, this->result, op[0], op[1]);
break;
- case ir_unop_u2f:
case ir_binop_lshift:
case ir_binop_rshift:
assert(!"GLSL 1.30 features unsupported");
}
}
+/* If the RHS processing resulted in an instruction generating a
+ * temporary value, and it would be easy to rewrite the instruction to
+ * generate its result right into the LHS instead, do so. This ends
+ * up reliably removing instructions where it can be tricky to do so
+ * later without real UD chain information.
+ */
+bool
+fs_visitor::try_rewrite_rhs_to_dst(ir_assignment *ir,
+ fs_reg dst,
+ fs_reg src,
+ fs_inst *pre_rhs_inst,
+ fs_inst *last_rhs_inst)
+{
+ if (pre_rhs_inst == last_rhs_inst)
+ return false; /* No instructions generated to work with. */
+
+ /* Only attempt if we're doing a direct assignment. */
+ if (ir->condition ||
+ !(ir->lhs->type->is_scalar() ||
+ (ir->lhs->type->is_vector() &&
+ ir->write_mask == (1 << ir->lhs->type->vector_elements) - 1)))
+ return false;
+
+ /* Make sure the last instruction generated our source reg. */
+ if (last_rhs_inst->predicated ||
+ last_rhs_inst->force_uncompressed ||
+ last_rhs_inst->force_sechalf ||
+ !src.equals(&last_rhs_inst->dst))
+ return false;
+
+ /* Success! Rewrite the instruction. */
+ last_rhs_inst->dst = dst;
+
+ return true;
+}
+
void
fs_visitor::visit(ir_assignment *ir)
{
- struct fs_reg l, r;
+ fs_reg l, r;
fs_inst *inst;
/* FINISHME: arrays on the lhs */
- this->result = reg_undef;
ir->lhs->accept(this);
l = this->result;
- /* If we're doing a direct assignment, an RHS expression could
- * drop its result right into our destination. Otherwise, tell it
- * not to.
- */
- if (ir->condition ||
- !(ir->lhs->type->is_scalar() ||
- (ir->lhs->type->is_vector() &&
- ir->write_mask == (1 << ir->lhs->type->vector_elements) - 1))) {
- this->result = reg_undef;
- }
+ fs_inst *pre_rhs_inst = (fs_inst *) this->instructions.get_tail();
ir->rhs->accept(this);
r = this->result;
+ fs_inst *last_rhs_inst = (fs_inst *) this->instructions.get_tail();
+
assert(l.file != BAD_FILE);
assert(r.file != BAD_FILE);
+ if (try_rewrite_rhs_to_dst(ir, l, r, pre_rhs_inst, last_rhs_inst))
+ return;
+
if (ir->condition) {
emit_bool_to_cond_code(ir->condition);
}
ir->lhs->type->is_vector()) {
for (int i = 0; i < ir->lhs->type->vector_elements; i++) {
if (ir->write_mask & (1 << i)) {
- if (ir->condition) {
- inst = emit(BRW_OPCODE_MOV, l, r);
+ inst = emit(BRW_OPCODE_MOV, l, r);
+ if (ir->condition)
inst->predicated = true;
- } else if (!l.equals(&r)) {
- inst = emit(BRW_OPCODE_MOV, l, r);
- }
-
r.reg_offset++;
}
l.reg_offset++;
/* g0 header. */
mlen = 1;
- if (ir->shadow_comparitor) {
+ if (ir->shadow_comparitor && ir->op != ir_txd) {
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
fs_inst *inst = emit(BRW_OPCODE_MOV,
fs_reg(MRF, base_mrf + mlen + i), coordinate);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), fs_reg(0.0f));
mlen++;
} else if (ir->op == ir_txb) {
- this->result = reg_undef;
ir->lod_info.bias->accept(this);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
mlen++;
} else {
assert(ir->op == ir_txl);
- this->result = reg_undef;
ir->lod_info.lod->accept(this);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
mlen++;
}
- this->result = reg_undef;
ir->shadow_comparitor->accept(this);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
mlen++;
* dPdx = dudx, dvdx, drdx
* dPdy = dudy, dvdy, drdy
*
+ * 1-arg: Does not exist.
+ *
* 2-arg: dudx dvdx dudy dvdy
* dPdx.x dPdx.y dPdy.x dPdy.y
* m4 m5 m6 m7
for (int i = 0; i < ir->lod_info.grad.dPdx->type->vector_elements; i++) {
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), dPdx);
dPdx.reg_offset++;
- mlen++;
}
+ mlen += MAX2(ir->lod_info.grad.dPdx->type->vector_elements, 2);
for (int i = 0; i < ir->lod_info.grad.dPdy->type->vector_elements; i++) {
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), dPdy);
dPdy.reg_offset++;
- mlen++;
}
+ mlen += MAX2(ir->lod_info.grad.dPdy->type->vector_elements, 2);
+ } else if (ir->op == ir_txs) {
+ /* There's no SIMD8 resinfo message on Gen4. Use SIMD16 instead. */
+ simd16 = true;
+ ir->lod_info.lod->accept(this);
+ emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), this->result);
+ mlen += 2;
} else {
/* Oh joy. gen4 doesn't have SIMD8 non-shadow-compare bias/lod
* instructions. We'll need to do SIMD16 here.
*/
+ simd16 = true;
assert(ir->op == ir_txb || ir->op == ir_txl);
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
mlen += 6;
if (ir->op == ir_txb) {
- this->result = reg_undef;
ir->lod_info.bias->accept(this);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
mlen++;
} else {
- this->result = reg_undef;
ir->lod_info.lod->accept(this);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
mlen++;
/* The unused upper half. */
mlen++;
+ }
+ if (simd16) {
/* Now, since we're doing simd16, the return is 2 interleaved
* vec4s where the odd-indexed ones are junk. We'll need to move
* this weirdness around to the expected layout.
*/
- simd16 = true;
orig_dst = dst;
- dst = fs_reg(this, glsl_type::get_array_instance(glsl_type::vec4_type,
- 2));
- dst.type = BRW_REGISTER_TYPE_F;
+ const glsl_type *vec_type =
+ glsl_type::get_instance(ir->type->base_type, 4, 1);
+ dst = fs_reg(this, glsl_type::get_array_instance(vec_type, 2));
+ dst.type = intel->is_g4x ? brw_type_for_base_type(ir->type)
+ : BRW_REGISTER_TYPE_F;
}
fs_inst *inst = NULL;
case ir_txd:
inst = emit(FS_OPCODE_TXD, dst);
break;
+ case ir_txs:
+ inst = emit(FS_OPCODE_TXS, dst);
+ break;
case ir_txf:
assert(!"GLSL 1.30 features unsupported");
break;
int base_mrf = 2;
int reg_width = c->dispatch_width / 8;
bool header_present = false;
+ const int vector_elements =
+ ir->coordinate ? ir->coordinate->type->vector_elements : 0;
if (ir->offset) {
/* The offsets set up by the ir_texture visitor are in the
base_mrf--;
}
- for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
+ for (int i = 0; i < vector_elements; i++) {
fs_inst *inst = emit(BRW_OPCODE_MOV,
- fs_reg(MRF, base_mrf + mlen + i * reg_width),
+ fs_reg(MRF, base_mrf + mlen + i * reg_width,
+ coordinate.type),
coordinate);
if (i < 3 && c->key.gl_clamp_mask[i] & (1 << sampler))
inst->saturate = true;
coordinate.reg_offset++;
}
- mlen += ir->coordinate->type->vector_elements * reg_width;
+ mlen += vector_elements * reg_width;
- if (ir->shadow_comparitor) {
+ if (ir->shadow_comparitor && ir->op != ir_txd) {
mlen = MAX2(mlen, header_present + 4 * reg_width);
- this->result = reg_undef;
ir->shadow_comparitor->accept(this);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
mlen += reg_width;
inst = emit(FS_OPCODE_TEX, dst);
break;
case ir_txb:
- this->result = reg_undef;
ir->lod_info.bias->accept(this);
mlen = MAX2(mlen, header_present + 4 * reg_width);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
break;
case ir_txl:
- this->result = reg_undef;
ir->lod_info.lod->accept(this);
mlen = MAX2(mlen, header_present + 4 * reg_width);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
inst = emit(FS_OPCODE_TXD, dst);
break;
}
+ case ir_txs:
+ ir->lod_info.lod->accept(this);
+ emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), this->result);
+ mlen += reg_width;
+ inst = emit(FS_OPCODE_TXS, dst);
+ break;
case ir_txf:
- assert(!"GLSL 1.30 features unsupported");
+ mlen = header_present + 4 * reg_width;
+
+ ir->lod_info.lod->accept(this);
+ emit(BRW_OPCODE_MOV,
+ fs_reg(MRF, base_mrf + mlen - reg_width, BRW_REGISTER_TYPE_UD),
+ this->result);
+ inst = emit(FS_OPCODE_TXF, dst);
break;
}
inst->base_mrf = base_mrf;
base_mrf--;
}
- if (ir->shadow_comparitor) {
+ if (ir->shadow_comparitor && ir->op != ir_txd) {
ir->shadow_comparitor->accept(this);
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
mlen += reg_width;
}
break;
}
+ case ir_txs:
+ ir->lod_info.lod->accept(this);
+ emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), this->result);
+ mlen += reg_width;
+ break;
case ir_txf:
- assert(!"GLSL 1.30 features unsupported");
+ /* Unfortunately, the parameters for LD are intermixed: u, lod, v, r. */
+ fs_inst *inst = emit(BRW_OPCODE_MOV,
+ fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D),
+ coordinate);
+ coordinate.reg_offset++;
+ mlen += reg_width;
+
+ ir->lod_info.lod->accept(this);
+ emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), this->result);
+ mlen += reg_width;
+
+ for (int i = 1; i < ir->coordinate->type->vector_elements; i++) {
+ fs_inst *inst = emit(BRW_OPCODE_MOV,
+ fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D),
+ coordinate);
+ coordinate.reg_offset++;
+ mlen += reg_width;
+ }
break;
}
- /* Set up the coordinate (except for TXD where it was done earlier) */
- if (ir->op != ir_txd) {
+ /* Set up the coordinate (except for cases where it was done above) */
+ if (ir->op != ir_txd && ir->op != ir_txs && ir->op != ir_txf) {
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
fs_inst *inst = emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen),
coordinate);
case ir_txb: inst = emit(FS_OPCODE_TXB, dst); break;
case ir_txl: inst = emit(FS_OPCODE_TXL, dst); break;
case ir_txd: inst = emit(FS_OPCODE_TXD, dst); break;
- case ir_txf: assert(!"TXF unsupported.");
+ case ir_txf: inst = emit(FS_OPCODE_TXF, dst); break;
+ case ir_txs: inst = emit(FS_OPCODE_TXS, dst); break;
}
inst->base_mrf = base_mrf;
inst->mlen = mlen;
void
fs_visitor::visit(ir_texture *ir)
{
- int sampler;
fs_inst *inst = NULL;
- this->result = reg_undef;
- ir->coordinate->accept(this);
+ int sampler = _mesa_get_sampler_uniform_value(ir->sampler, prog, &fp->Base);
+ sampler = fp->Base.SamplerUnits[sampler];
+
+ /* Our hardware doesn't have a sample_d_c message, so shadow compares
+ * for textureGrad/TXD need to be emulated with instructions.
+ */
+ bool hw_compare_supported = ir->op != ir_txd;
+ if (ir->shadow_comparitor && !hw_compare_supported) {
+ assert(c->key.compare_funcs[sampler] != GL_NONE);
+ /* No need to even sample for GL_ALWAYS or GL_NEVER...bail early */
+ if (c->key.compare_funcs[sampler] == GL_ALWAYS)
+ return swizzle_result(ir, fs_reg(1.0f), sampler);
+ else if (c->key.compare_funcs[sampler] == GL_NEVER)
+ return swizzle_result(ir, fs_reg(0.0f), sampler);
+ }
+
+ if (ir->coordinate)
+ ir->coordinate->accept(this);
fs_reg coordinate = this->result;
if (ir->offset != NULL) {
/* Should be lowered by do_lower_texture_projection */
assert(!ir->projector);
- sampler = _mesa_get_sampler_uniform_value(ir->sampler,
- prog,
- &fp->Base);
- sampler = fp->Base.SamplerUnits[sampler];
-
/* The 965 requires the EU to do the normalization of GL rectangle
* texture coordinates. We use the program parameter state
* tracking to get the scaling factor.
*/
- if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_RECT) {
+ if (intel->gen < 6 &&
+ ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_RECT) {
struct gl_program_parameter_list *params = c->fp->program.Base.Parameters;
int tokens[STATE_LENGTH] = {
STATE_INTERNAL,
/* Writemasking doesn't eliminate channels on SIMD8 texture
* samples, so don't worry about them.
*/
- fs_reg dst = fs_reg(this, glsl_type::vec4_type);
+ fs_reg dst = fs_reg(this, glsl_type::get_instance(ir->type->base_type, 4, 1));
if (intel->gen >= 7) {
inst = emit_texture_gen7(ir, dst, coordinate, sampler);
inst->sampler = sampler;
- this->result = dst;
+ if (ir->shadow_comparitor) {
+ if (hw_compare_supported) {
+ inst->shadow_compare = true;
+ } else {
+ ir->shadow_comparitor->accept(this);
+ fs_reg ref = this->result;
+
+ fs_reg value = dst;
+ dst = fs_reg(this, glsl_type::vec4_type);
+
+ /* FINISHME: This needs to be done pre-filtering. */
+
+ uint32_t conditional = 0;
+ switch (c->key.compare_funcs[sampler]) {
+ /* GL_ALWAYS and GL_NEVER were handled at the top of the function */
+ case GL_LESS: conditional = BRW_CONDITIONAL_L; break;
+ case GL_GREATER: conditional = BRW_CONDITIONAL_G; break;
+ case GL_LEQUAL: conditional = BRW_CONDITIONAL_LE; break;
+ case GL_GEQUAL: conditional = BRW_CONDITIONAL_GE; break;
+ case GL_EQUAL: conditional = BRW_CONDITIONAL_EQ; break;
+ case GL_NOTEQUAL: conditional = BRW_CONDITIONAL_NEQ; break;
+ default: assert(!"Should not get here: bad shadow compare function");
+ }
+
+ /* Use conditional moves to load 0 or 1 as the result */
+ this->current_annotation = "manual shadow comparison";
+ for (int i = 0; i < 4; i++) {
+ inst = emit(BRW_OPCODE_MOV, dst, fs_reg(0.0f));
+
+ inst = emit(BRW_OPCODE_CMP, reg_null_f, ref, value);
+ inst->conditional_mod = conditional;
+
+ inst = emit(BRW_OPCODE_MOV, dst, fs_reg(1.0f));
+ inst->predicated = true;
+
+ dst.reg_offset++;
+ value.reg_offset++;
+ }
+ dst.reg_offset = 0;
+ }
+ }
+
+ swizzle_result(ir, dst, sampler);
+}
- if (ir->shadow_comparitor)
- inst->shadow_compare = true;
+/**
+ * Swizzle the result of a texture result. This is necessary for
+ * EXT_texture_swizzle as well as DEPTH_TEXTURE_MODE for shadow comparisons.
+ */
+void
+fs_visitor::swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler)
+{
+ this->result = orig_val;
if (ir->type == glsl_type::float_type) {
/* Ignore DEPTH_TEXTURE_MODE swizzling. */
assert(ir->sampler->type->sampler_shadow);
- } else if (c->key.tex_swizzles[inst->sampler] != SWIZZLE_NOOP) {
- fs_reg swizzle_dst = fs_reg(this, glsl_type::vec4_type);
+ } else if (c->key.tex_swizzles[sampler] != SWIZZLE_NOOP) {
+ fs_reg swizzled_result = fs_reg(this, glsl_type::vec4_type);
for (int i = 0; i < 4; i++) {
- int swiz = GET_SWZ(c->key.tex_swizzles[inst->sampler], i);
- fs_reg l = swizzle_dst;
+ int swiz = GET_SWZ(c->key.tex_swizzles[sampler], i);
+ fs_reg l = swizzled_result;
l.reg_offset += i;
if (swiz == SWIZZLE_ZERO) {
} else if (swiz == SWIZZLE_ONE) {
emit(BRW_OPCODE_MOV, l, fs_reg(1.0f));
} else {
- fs_reg r = dst;
- r.reg_offset += GET_SWZ(c->key.tex_swizzles[inst->sampler], i);
+ fs_reg r = orig_val;
+ r.reg_offset += GET_SWZ(c->key.tex_swizzles[sampler], i);
emit(BRW_OPCODE_MOV, l, r);
}
}
- this->result = swizzle_dst;
+ this->result = swizzled_result;
}
}
void
fs_visitor::visit(ir_swizzle *ir)
{
- this->result = reg_undef;
ir->val->accept(this);
fs_reg val = this->result;
const unsigned size = type_size(ir->type->fields.array);
for (unsigned i = 0; i < ir->type->length; i++) {
- this->result = reg_undef;
ir->array_elements[i]->accept(this);
fs_reg src_reg = this->result;
ir_instruction *const field = (ir_instruction *) node;
const unsigned size = type_size(field->type);
- this->result = reg_undef;
field->accept(this);
fs_reg src_reg = this->result;
for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
assert(expr->operands[i]->type->is_scalar());
- this->result = reg_undef;
expr->operands[i]->accept(this);
op[i] = this->result;
}
return;
}
- this->result = reg_undef;
ir->accept(this);
if (intel->gen >= 6) {
for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
assert(expr->operands[i]->type->is_scalar());
- this->result = reg_undef;
expr->operands[i]->accept(this);
op[i] = this->result;
}
return;
}
- this->result = reg_undef;
ir->condition->accept(this);
fs_inst *inst = emit(BRW_OPCODE_IF, reg_null_d, this->result, fs_reg(0));
inst->predicated = true;
}
- foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
- ir_instruction *ir = (ir_instruction *)iter.get();
+ foreach_list(node, &ir->then_instructions) {
+ ir_instruction *ir = (ir_instruction *)node;
this->base_ir = ir;
- this->result = reg_undef;
+
ir->accept(this);
}
if (!ir->else_instructions.is_empty()) {
emit(BRW_OPCODE_ELSE);
- foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
- ir_instruction *ir = (ir_instruction *)iter.get();
+ foreach_list(node, &ir->else_instructions) {
+ ir_instruction *ir = (ir_instruction *)node;
this->base_ir = ir;
- this->result = reg_undef;
+
ir->accept(this);
}
}
counter = *(variable_storage(ir->counter));
if (ir->from) {
- this->result = counter;
-
this->base_ir = ir->from;
- this->result = counter;
ir->from->accept(this);
- if (!this->result.equals(&counter))
- emit(BRW_OPCODE_MOV, counter, this->result);
+ emit(BRW_OPCODE_MOV, counter, this->result);
}
}
if (ir->to) {
this->base_ir = ir->to;
- this->result = reg_undef;
ir->to->accept(this);
fs_inst *inst = emit(BRW_OPCODE_CMP, reg_null_cmp, counter, this->result);
inst->predicated = true;
}
- foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
- ir_instruction *ir = (ir_instruction *)iter.get();
+ foreach_list(node, &ir->body_instructions) {
+ ir_instruction *ir = (ir_instruction *)node;
this->base_ir = ir;
- this->result = reg_undef;
ir->accept(this);
}
if (ir->increment) {
this->base_ir = ir->increment;
- this->result = reg_undef;
ir->increment->accept(this);
emit(BRW_OPCODE_ADD, counter, counter, this->result);
}
assert(sig);
- foreach_iter(exec_list_iterator, iter, sig->body) {
- ir_instruction *ir = (ir_instruction *)iter.get();
+ foreach_list(node, &sig->body) {
+ ir_instruction *ir = (ir_instruction *)node;
this->base_ir = ir;
- this->result = reg_undef;
+
ir->accept(this);
}
}
fs_inst *write;
write = emit(FS_OPCODE_FB_WRITE, fs_reg(0), fs_reg(0));
- write->base_mrf = 0;
+ write->base_mrf = 2;
}
/* The register location here is relative to the start of the URB
interp_reg(FRAG_ATTRIB_WPOS, 3));
/* Compute the pixel 1/W value from wpos.w. */
this->pixel_w = fs_reg(this, glsl_type::float_type);
- emit_math(FS_OPCODE_RCP, this->pixel_w, wpos_w);
+ emit_math(SHADER_OPCODE_RCP, this->pixel_w, wpos_w);
this->current_annotation = NULL;
}
this->current_annotation = "compute pos.w";
this->pixel_w = fs_reg(brw_vec8_grf(c->source_w_reg, 0));
this->wpos_w = fs_reg(this, glsl_type::float_type);
- emit_math(FS_OPCODE_RCP, this->wpos_w, this->pixel_w);
+ emit_math(SHADER_OPCODE_RCP, this->wpos_w, this->pixel_w);
this->delta_x = fs_reg(brw_vec8_grf(2, 0));
this->delta_y = fs_reg(brw_vec8_grf(3, 0));
fs_visitor::emit_color_write(int index, int first_color_mrf, fs_reg color)
{
int reg_width = c->dispatch_width / 8;
+ fs_inst *inst;
if (c->dispatch_width == 8 || intel->gen == 6) {
/* SIMD8 write looks like:
* m + 6: a0
* m + 7: a1
*/
- emit(BRW_OPCODE_MOV, fs_reg(MRF, first_color_mrf + index * reg_width),
- color);
+ inst = emit(BRW_OPCODE_MOV,
+ fs_reg(MRF, first_color_mrf + index * reg_width),
+ color);
+ inst->saturate = c->key.clamp_fragment_color;
} else {
/* pre-gen6 SIMD16 single source DP write looks like:
* m + 0: r0
* usual destination + 1 for the second half we get
* destination + 4.
*/
- emit(BRW_OPCODE_MOV,
- fs_reg(MRF, BRW_MRF_COMPR4 + first_color_mrf + index), color);
+ inst = emit(BRW_OPCODE_MOV,
+ fs_reg(MRF, BRW_MRF_COMPR4 + first_color_mrf + index),
+ color);
+ inst->saturate = c->key.clamp_fragment_color;
} else {
push_force_uncompressed();
- emit(BRW_OPCODE_MOV, fs_reg(MRF, first_color_mrf + index), color);
+ inst = emit(BRW_OPCODE_MOV, fs_reg(MRF, first_color_mrf + index),
+ color);
+ inst->saturate = c->key.clamp_fragment_color;
pop_force_uncompressed();
push_force_sechalf();
color.sechalf = true;
- emit(BRW_OPCODE_MOV, fs_reg(MRF, first_color_mrf + index + 4), color);
+ inst = emit(BRW_OPCODE_MOV, fs_reg(MRF, first_color_mrf + index + 4),
+ color);
+ inst->saturate = c->key.clamp_fragment_color;
pop_force_sechalf();
color.sechalf = false;
}
{
this->current_annotation = "FB write header";
GLboolean header_present = GL_TRUE;
- int nr = 0;
+ int base_mrf = 2;
+ int nr = base_mrf;
int reg_width = c->dispatch_width / 8;
if (intel->gen >= 6 &&
}
if (header_present) {
- /* m0, m1 header */
+ /* m2, m3 header */
nr += 2;
}
fs_inst *inst = emit(FS_OPCODE_FB_WRITE);
inst->target = target;
- inst->base_mrf = 0;
- inst->mlen = nr;
+ inst->base_mrf = base_mrf;
+ inst->mlen = nr - base_mrf;
if (target == c->key.nr_color_regions - 1)
inst->eot = true;
inst->header_present = header_present;
}
fs_inst *inst = emit(FS_OPCODE_FB_WRITE);
- inst->base_mrf = 0;
- inst->mlen = nr;
+ inst->base_mrf = base_mrf;
+ inst->mlen = nr - base_mrf;
inst->eot = true;
inst->header_present = header_present;
}