i965: fix bugs in projective texture coordinates

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...
This commit is contained in:
Brian Paul
2009-06-16 18:19:45 -06:00
parent 742ba08406
commit 6b917d0b17
5 changed files with 54 additions and 20 deletions
+3 -2
View 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];
+33 -11
View 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;
}
}
+1 -1
View 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);
+1 -1
View 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 */
+16 -5
View 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 )
{