i965: fix bugs in projective texture coordinates
authorBrian Paul <brianp@vmware.com>
Wed, 17 Jun 2009 00:19:45 +0000 (18:19 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 17 Jun 2009 00:21:26 +0000 (18:21 -0600)
For the TXP instruction we check if the texcoord is really a 4-component
atttibute which requires the divide by W step.  This check involved the
projtex_mask field.  However, the projtex_mask field was being miscalculated
because of some confusion between vertex program outputs and fragment
program inputs.

1. Rework the size_masks calculation so we correctly set bits corresponding
to fragment program input attributes.

2. Rename projtex_mask to proj_attrib_mask since we're interested in more
than just texcoords (generic varying vars too).

3. Simply the indexing of the size_masks and proj_attrib_mask fields.

4. The tracker::active[] array was mis-dimensioned.  Use MAX_PROGRAM_TEMPS
instead of a magic number.

5. Update comments, add new assertions.

With these changes the Lightsmark demo/benchmark renders correctly, until
we eventually hit a GPU lockup...

src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_vs_constval.c
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm.h
src/mesa/drivers/dri/i965/brw_wm_fp.c

index aef2ff5f86f8926f02a93968f1ac7f88b07a2934..577497bf6b0cb88729576280f7e9237718b4e39a 100644 (file)
@@ -616,9 +616,10 @@ struct brw_context
       struct brw_wm_prog_data *prog_data;
       struct brw_wm_compile *compile_data;
 
-      /* Input sizes, calculated from active vertex program:
+      /** Input sizes, calculated from active vertex program.
+       * One bit per fragment program input attribute.
        */
-      GLuint input_size_masks[4];
+      GLbitfield input_size_masks[4];
 
       /** Array of surface default colors (texture border color) */
       dri_bo *sdc_bo[BRW_MAX_TEX_UNIT];
index 2637344b48248aa7ba2a0970fe8295cfab7f2702..249a800bf4b99585bc31fa9234b9344f03419cc2 100644 (file)
@@ -39,8 +39,8 @@
  */
 struct tracker {
    GLboolean twoside;
-   GLubyte active[PROGRAM_OUTPUT+1][128];
-   GLuint size_masks[4];
+   GLubyte active[PROGRAM_OUTPUT+1][MAX_PROGRAM_TEMPS];
+   GLbitfield size_masks[4];  /**< one bit per fragment program input attrib */
 };
 
 
@@ -53,8 +53,10 @@ static void set_active_component( struct tracker *t,
    case PROGRAM_TEMPORARY:
    case PROGRAM_INPUT:
    case PROGRAM_OUTPUT:
+      assert(file < PROGRAM_OUTPUT + 1);
+      assert(index < Elements(t->active[0]));
       t->active[file][index] |= active;
-
+      break;
    default:
       break;
    }
@@ -108,10 +110,15 @@ static GLubyte get_active( struct tracker *t,
    return active;
 }
 
+/**
+ * Return the size (1,2,3 or 4) of the output/result for VERT_RESULT_idx.
+ */
 static GLubyte get_output_size( struct tracker *t,
                                GLuint idx )
 {
-   GLubyte active = t->active[PROGRAM_OUTPUT][idx];
+   GLubyte active;
+   assert(idx < VERT_RESULT_MAX);
+   active = t->active[PROGRAM_OUTPUT][idx];
    if (active & (1<<3)) return 4;
    if (active & (1<<2)) return 3;
    if (active & (1<<1)) return 2;
@@ -123,7 +130,7 @@ static GLubyte get_output_size( struct tracker *t,
  */
 static void calc_sizes( struct tracker *t )
 {
-   GLuint i;
+   GLint vertRes;
 
    if (t->twoside) {
       t->active[PROGRAM_OUTPUT][VERT_RESULT_COL0] |= 
@@ -133,12 +140,27 @@ static void calc_sizes( struct tracker *t )
         t->active[PROGRAM_OUTPUT][VERT_RESULT_BFC1];
    }
 
-   for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
-      switch (get_output_size(t, i)) {
-      case 4: t->size_masks[4-1] |= 1<<i;
-      case 3: t->size_masks[3-1] |= 1<<i;
-      case 2: t->size_masks[2-1] |= 1<<i;
-      case 1: t->size_masks[1-1] |= 1<<i;
+   /* Examine vertex program output sizes to set the size_masks[] info
+    * which describes the fragment program input sizes.
+    */
+   for (vertRes = VERT_RESULT_TEX0; vertRes < VERT_RESULT_MAX; vertRes++) {
+      GLint fragAttrib;
+
+      /* map vertex program output index to fragment program input index */
+      if (vertRes <= VERT_RESULT_TEX7)
+         fragAttrib = FRAG_ATTRIB_TEX0 + vertRes - VERT_RESULT_TEX0;
+      else if (vertRes >= VERT_RESULT_VAR0)
+         fragAttrib = FRAG_ATTRIB_VAR0 + vertRes - VERT_RESULT_VAR0;
+      else
+         continue;
+      assert(fragAttrib >= FRAG_ATTRIB_TEX0);
+      assert(fragAttrib <= FRAG_ATTRIB_MAX);
+
+      switch (get_output_size(t, vertRes)) {
+      case 4: t->size_masks[4-1] |= 1 << fragAttrib;
+      case 3: t->size_masks[3-1] |= 1 << fragAttrib;
+      case 2: t->size_masks[2-1] |= 1 << fragAttrib;
+      case 1: t->size_masks[1-1] |= 1 << fragAttrib;
         break;
       }
    }
index 90d74c2885cae413aeca2ec5286604885161e6b7..c0b07da63b1d82b22d7b5f2e8aaba0999470077d 100644 (file)
@@ -260,7 +260,7 @@ static void brw_wm_populate_key( struct brw_context *brw,
 
 
    /* BRW_NEW_WM_INPUT_DIMENSIONS */
-   key->projtex_mask = brw->wm.input_size_masks[4-1] >> (FRAG_ATTRIB_TEX0 - FRAG_ATTRIB_WPOS); 
+   key->proj_attrib_mask = brw->wm.input_size_masks[4-1];
 
    /* _NEW_LIGHT */
    key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
index f0d31fc1ddc084e01b0f83a97d2a2724410185c1..0408034c38a6ce322df51e42328e51353d0b10dc 100644 (file)
@@ -65,7 +65,7 @@ struct brw_wm_prog_key {
    GLuint flat_shade:1;
    GLuint runtime_check_aads_emit:1;
    
-   GLuint projtex_mask:16;
+   GLbitfield proj_attrib_mask; /**< one bit per fragment program attribute */
    GLuint shadowtex_mask:16;
    GLuint yuvtex_mask:16;
    GLuint yuvtex_swap_mask:16; /* UV swaped */
index 1798d842c799ba5e4406c4b3ca483b9285529930..49aad281d7a8d8751c7e617b7db57935a2102c77 100644 (file)
@@ -834,10 +834,16 @@ static void precalc_tex( struct brw_wm_compile *c,
 }
 
 
+/**
+ * Check if the given TXP instruction really needs the divide-by-W step.
+ */
 static GLboolean projtex( struct brw_wm_compile *c,
                          const struct prog_instruction *inst )
 {
-   struct prog_src_register src = inst->SrcReg[0];
+   const struct prog_src_register src = inst->SrcReg[0];
+   GLboolean retVal;
+
+   assert(inst->Opcode == OPCODE_TXP);
 
    /* Only try to detect the simplest cases.  Could detect (later)
     * cases where we are trying to emit code like RCP {1.0}, MUL x,
@@ -847,16 +853,21 @@ static GLboolean projtex( struct brw_wm_compile *c,
     * user-provided fragment programs anyway:
     */
    if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX)
-      return 0;  /* ut2004 gun rendering !?! */
+      retVal = GL_FALSE;  /* ut2004 gun rendering !?! */
    else if (src.File == PROGRAM_INPUT && 
            GET_SWZ(src.Swizzle, W) == W &&
-           (c->key.projtex_mask & (1<<(src.Index + FRAG_ATTRIB_WPOS - FRAG_ATTRIB_TEX0))) == 0)
-      return 0;
+            (c->key.proj_attrib_mask & (1 << src.Index)) == 0)
+      retVal = GL_FALSE;
    else
-      return 1;
+      retVal = GL_TRUE;
+
+   return retVal;
 }
 
 
+/**
+ * Emit code for TXP.
+ */
 static void precalc_txp( struct brw_wm_compile *c,
                               const struct prog_instruction *inst )
 {