i965: fix for RHW workaround

It is possible that an object whose vertices all are outside of a
view plane is passed to clip thread due to the RHW workaround. This
object should be rejected by clip thread. Fix bug #19879
This commit is contained in:
Xiang, Haihao 2009-02-26 17:31:01 +08:00
parent 160c3617fc
commit 68915fd6fa
2 changed files with 97 additions and 41 deletions

View file

@ -181,34 +181,54 @@ static void clip_and_emit_line( struct brw_clip_compile *c )
brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
is_negative = brw_IF(p, BRW_EXECUTE_1);
{
brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
/*
* Both can be negative on GM965/G965 due to RHW workaround
* if so, this object should be rejected.
*/
if (!BRW_IS_G4X(p->brw)) {
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
is_neg2 = brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p, is_neg2);
}
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
brw_MOV(p, c->reg.t1, c->reg.t);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
brw_MOV(p, c->reg.t1, c->reg.t);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
is_negative = brw_ELSE(p, is_negative);
{
/* Coming back in. We know that both cannot be negative
* because the line would have been culled in that case.
*/
/* Coming back in. We know that both cannot be negative
* because the line would have been culled in that case.
*/
/* If both are positive, do nothing */
/* Only on GM965/G965 */
if (!BRW_IS_G4X(p->brw)) {
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
is_neg2 = brw_IF(p, BRW_EXECUTE_1);
}
/* If both are positive, do nothing */
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
is_neg2 = brw_IF(p, BRW_EXECUTE_1);
{
brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
brw_MOV(p, c->reg.t0, c->reg.t);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
brw_ENDIF(p, is_neg2);
}
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
brw_MOV(p, c->reg.t0, c->reg.t);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
if (!BRW_IS_G4X(p->brw)) {
brw_ENDIF(p, is_neg2);
}
}
brw_ENDIF(p, is_negative);
}
brw_ENDIF(p, plane_active);

View file

@ -455,6 +455,8 @@ static void brw_clip_test( struct brw_clip_compile *c )
struct brw_indirect vt2 = brw_indirect(2, 0);
struct brw_compile *p = &c->func;
struct brw_instruction *is_outside;
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
@ -462,53 +464,87 @@ static void brw_clip_test( struct brw_clip_compile *c )
brw_MOV(p, v0, deref_4f(vt0, c->offset[VERT_RESULT_HPOS]));
brw_MOV(p, v1, deref_4f(vt1, c->offset[VERT_RESULT_HPOS]));
brw_MOV(p, v2, deref_4f(vt2, c->offset[VERT_RESULT_HPOS]));
brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
/* test nearz, xmin, ymin plane */
brw_CMP(p, t1, BRW_CONDITIONAL_LE, negate(v0), get_element(v0, 3));
/* clip.xyz < -clip.w */
brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, t2, BRW_CONDITIONAL_LE, negate(v1), get_element(v1, 3));
brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, t3, BRW_CONDITIONAL_LE, negate(v2), get_element(v2, 3));
brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
/* All vertices are outside of a plane, rejected */
brw_AND(p, t, t1, t2);
brw_AND(p, t, t, t3);
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
brw_OR(p, tmp0, tmp0, get_element(t, 2));
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
is_outside = brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p, is_outside);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
/* some vertices are inside a plane, some are outside,need to clip */
brw_XOR(p, t, t1, t2);
brw_XOR(p, t1, t2, t3);
brw_OR(p, t, t, t1);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 0), brw_imm_ud(0));
brw_AND(p, t, t, brw_imm_ud(0x1));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 0), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 1), brw_imm_ud(0));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 1), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 2), brw_imm_ud(0));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 2), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
/* test farz, xmax, ymax plane */
brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, get_element(v0, 3));
/* clip.xyz > clip.w */
brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, get_element(v1, 3));
brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, get_element(v2, 3));
brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
/* All vertices are outside of a plane, rejected */
brw_AND(p, t, t1, t2);
brw_AND(p, t, t, t3);
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
brw_OR(p, tmp0, tmp0, get_element(t, 2));
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
is_outside = brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p, is_outside);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
/* some vertices are inside a plane, some are outside,need to clip */
brw_XOR(p, t, t1, t2);
brw_XOR(p, t1, t2, t3);
brw_OR(p, t, t, t1);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 0), brw_imm_ud(0));
brw_AND(p, t, t, brw_imm_ud(0x1));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 0), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 1), brw_imm_ud(0));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 1), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 2), brw_imm_ud(0));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 2), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);