summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2012-04-16 18:43:48 -0700
committerEric Anholt <[email protected]>2012-04-24 10:00:54 -0700
commitf41ecade7b458c02d504158b522acb2231585040 (patch)
tree5708efb76f08591b770438f131bb7a7ddcda072f
parent587c221a29fe01e24c69952a7a9b0034f7652e4e (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.cpp27
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. */