i915: Refine the texture indirect lookup accounting.
authorEric Anholt <eric@anholt.net>
Sun, 5 Oct 2008 01:20:35 +0000 (18:20 -0700)
committerEric Anholt <eric@anholt.net>
Sun, 5 Oct 2008 01:40:32 +0000 (18:40 -0700)
Without this, we would reject programs which sampled multiple times from
registers defined in the same phase (block of instructions with the same
texture indirection count), as each sample would count as a new phase
beginning.  Instead, keep track of which phases registers were written in,
and only bump phase when we're reading from one generated in this phase.

On the other hand, we failed to count oC or oD texture samples as being new
phases.

Bug #17865.

src/mesa/drivers/dri/i915/i915_context.h
src/mesa/drivers/dri/i915/i915_program.c

index c6958dd8d4be0a67707ab32b8fcf85e2f27d7d1d..a2376e50e157b224b5ee671c4465270afe2fd7bc 100644 (file)
@@ -125,6 +125,9 @@ struct i915_fragment_program
    GLboolean on_hardware;
    GLboolean error;             /* If program is malformed for any reason. */
 
+   /** Record of which phases R registers were last written in. */
+   GLuint register_phases[16];
+   GLuint indirections;
    GLuint nr_tex_indirect;
    GLuint nr_tex_insn;
    GLuint nr_alu_insn;
index 49193297a8c8776d7d9c74264013cce5c88f31f8..350da5e16978415f620dc2eda3008d45c4654559 100644 (file)
@@ -190,6 +190,9 @@ i915_emit_arith(struct i915_fragment_program * p,
    *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1));
    *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2));
 
+   if (GET_UREG_TYPE(dest) == REG_TYPE_R)
+      p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect;
+
    p->nr_alu_insn++;
    return dest;
 }
@@ -237,10 +240,22 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
    else {
       assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
       assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
+      /* Can't use unsaved temps for coords, as the phase boundary would result
+       * in the contents becoming undefined.
+       */
+      assert(GET_UREG_TYPE(coord) != REG_TYPE_U);
+
+      /* Output register being oC or oD defines a phase boundary */
+      if (GET_UREG_TYPE(dest) == REG_TYPE_OC ||
+         GET_UREG_TYPE(dest) == REG_TYPE_OD)
+        p->nr_tex_indirect++;
 
-      if (GET_UREG_TYPE(coord) != REG_TYPE_T) {
+      /* Reading from an r# register whose contents depend on output of the
+       * current phase defines a phase boundary.
+       */
+      if (GET_UREG_TYPE(coord) == REG_TYPE_R &&
+         p->register_phases[GET_UREG_NR(coord)] == p->nr_tex_indirect)
         p->nr_tex_indirect++;
-      }
 
       *(p->csr++) = (op | 
                     T0_DEST( dest ) |
@@ -249,6 +264,9 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
       *(p->csr++) = T1_ADDRESS_REG( coord );
       *(p->csr++) = T2_MBZ;
 
+      if (GET_UREG_TYPE(dest) == REG_TYPE_R)
+        p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect;
+
       p->nr_tex_insn++;
       return dest;
    }
@@ -413,7 +431,8 @@ i915_init_program(struct i915_context *i915, struct i915_fragment_program *p)
    p->on_hardware = 0;
    p->error = 0;
 
-   p->nr_tex_indirect = 1;      /* correct? */
+   memset(&p->register_phases, 0, sizeof(p->register_phases));
+   p->nr_tex_indirect = 1;
    p->nr_tex_insn = 0;
    p->nr_alu_insn = 0;
    p->nr_decl_insn = 0;