diff options
author | Eric Anholt <[email protected]> | 2012-04-16 18:43:48 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2012-04-24 10:00:54 -0700 |
commit | f41ecade7b458c02d504158b522acb2231585040 (patch) | |
tree | 5708efb76f08591b770438f131bb7a7ddcda072f | |
parent | 587c221a29fe01e24c69952a7a9b0034f7652e4e (diff) |
i965/fs: Fix texelFetchOffset()
It appears that when using 'ld' with the offset bits, address bounds
checking happens before the offset is applied, so parts of the drawing
in piglit texelFetchOffset() with a negative texcoord go black.
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 8e98e1bb76c..6e8afbe5b26 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -990,8 +990,9 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, int base_mrf = 2; int reg_width = c->dispatch_width / 8; bool header_present = false; + int offsets[3]; - if (ir->offset) { + if (ir->offset && ir->op != ir_txf) { /* The offsets set up by the ir_texture visitor are in the * m1 header, so we can't go headerless. */ @@ -1054,9 +1055,23 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, mlen += reg_width; break; case ir_txf: + /* It appears that the ld instruction used for txf does its + * address bounds check before adding in the offset. To work + * around this, just add the integer offset to the integer texel + * coordinate, and don't put the offset in the header. + */ + if (ir->offset) { + ir_constant *offset = ir->offset->as_constant(); + offsets[0] = offset->value.i[0]; + offsets[1] = offset->value.i[1]; + offsets[2] = offset->value.i[2]; + } else { + memset(offsets, 0, sizeof(offsets)); + } + /* Unfortunately, the parameters for LD are intermixed: u, lod, v, r. */ - emit(BRW_OPCODE_MOV, - fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), coordinate); + emit(BRW_OPCODE_ADD, + fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), coordinate, offsets[0]); coordinate.reg_offset++; mlen += reg_width; @@ -1065,8 +1080,8 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, mlen += reg_width; for (int i = 1; i < ir->coordinate->type->vector_elements; i++) { - emit(BRW_OPCODE_MOV, - fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), coordinate); + emit(BRW_OPCODE_ADD, + fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), coordinate, offsets[i]); coordinate.reg_offset++; mlen += reg_width; } @@ -1128,7 +1143,7 @@ fs_visitor::visit(ir_texture *ir) ir->coordinate->accept(this); fs_reg coordinate = this->result; - if (ir->offset != NULL) { + if (ir->offset != NULL && !(intel->gen == 7 && ir->op == ir_txf)) { uint32_t offset_bits = brw_texture_offset(ir->offset->as_constant()); /* Explicitly set up the message header by copying g0 to msg reg m1. */ |