i965/fs: Emit shader w/a for Gen6 gather
authorChris Forbes <chrisf@ijw.co.nz>
Mon, 3 Feb 2014 09:15:16 +0000 (22:15 +1300)
committerChris Forbes <chrisf@ijw.co.nz>
Fri, 7 Feb 2014 21:32:20 +0000 (10:32 +1300)
Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 9c5c13ae3932e482c711b58247b7ee24ad50f2b4..3d668b9e471409e39b0937e319078ea9d1202b31 100644 (file)
@@ -360,6 +360,7 @@ public:
                               fs_reg shadow_comp, fs_reg lod, fs_reg lod2,
                               fs_reg sample_index, fs_reg mcs, int sampler);
    fs_reg emit_mcs_fetch(ir_texture *ir, fs_reg coordinate, int sampler);
+   void emit_gen6_gather_wa(uint8_t wa, fs_reg dst);
    fs_reg fix_math_operand(fs_reg src);
    fs_inst *emit_math(enum opcode op, fs_reg dst, fs_reg src0);
    fs_inst *emit_math(enum opcode op, fs_reg dst, fs_reg src0, fs_reg src1);
index d88d24c4d84c499addf2eacde33da04e5142261a..fd0813c373cdc13032a2da974bd17b6b32553fde 100644 (file)
@@ -1699,9 +1699,43 @@ fs_visitor::visit(ir_texture *ir)
       }
    }
 
+   if (brw->gen == 6 && ir->op == ir_tg4) {
+      emit_gen6_gather_wa(c->key.tex.gen6_gather_wa[sampler], dst);
+   }
+
    swizzle_result(ir, dst, sampler);
 }
 
+/**
+ * Apply workarounds for Gen6 gather with UINT/SINT
+ */
+void
+fs_visitor::emit_gen6_gather_wa(uint8_t wa, fs_reg dst)
+{
+   if (!wa)
+      return;
+
+   int width = (wa & WA_8BIT) ? 8 : 16;
+
+   for (int i = 0; i < 4; i++) {
+      fs_reg dst_f = dst.retype(BRW_REGISTER_TYPE_F);
+      /* Convert from UNORM to UINT */
+      emit(MUL(dst_f, dst_f, fs_reg((float)((1 << width) - 1))));
+      emit(MOV(dst, dst_f));
+
+      if (wa & WA_SIGN) {
+         /* Reinterpret the UINT value as a signed INT value by
+          * shifting the sign bit into place, then shifting back
+          * preserving sign.
+          */
+         emit(SHL(dst, dst, fs_reg(32 - width)));
+         emit(ASR(dst, dst, fs_reg(32 - width)));
+      }
+
+      dst.reg_offset++;
+   }
+}
+
 /**
  * Set up the gather channel based on the swizzle, for gather4.
  */