Mesa (gallium-0.2): CELL: fix stencil test bugs

Robert Ellison papillo at kemper.freedesktop.org
Wed Nov 12 19:21:15 UTC 2008


Module: Mesa
Branch: gallium-0.2
Commit: 44257a8e752a5f10aed7e5797b23cdb42120703c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=44257a8e752a5f10aed7e5797b23cdb42120703c

Author: Robert Ellison <papillo at tungstengraphics.com>
Date:   Wed Nov 12 12:23:52 2008 -0700

CELL: fix stencil test bugs

Fixed a boneheaded error in the generation of SPU code that calculates
the results of the stencil test.  Basically, all the greater than/less than
calculations were exactly inverted: they were coded as though the
given comparison took the stencil value as a left-hand operand and the
reference value as a right-hand operand, but the actual semantics always
put the reference as the left-hand operand and the stencil as the right-hand
operand.

With this fix, tests/dinoshade runs, as do all the other Mesa tests
and samples that use stencil (and that don't use texture formats
unsupported by Cell).

---

 src/gallium/drivers/cell/ppu/cell_gen_fragment.c |   25 ++++++++++++---------
 src/gallium/drivers/cell/ppu/cell_gen_fragment.h |    2 +-
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c
index 6e425ea..82336d6 100644
--- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c
+++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c
@@ -1190,14 +1190,14 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state,
       }
       break;
 
-   case PIPE_FUNC_GREATER:
+   case PIPE_FUNC_LESS:
       if (state->value_mask == stencil_max_value) {
-         /* stencil_pass = fragment_mask & (s > reference) */
+         /* stencil_pass = fragment_mask & (reference < s)  */
          spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
          spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
       }
       else {
-         /* stencil_pass = fragment_mask & ((s&mask) > (reference&mask)) */
+         /* stencil_pass = fragment_mask & ((reference&mask) < (s & mask)) */
          unsigned int tmp_masked_stencil = spe_allocate_available_register(f);
          spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->value_mask);
          spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil, state->value_mask & state->ref_value);
@@ -1206,7 +1206,7 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state,
       }
       break;
 
-   case PIPE_FUNC_LESS:
+   case PIPE_FUNC_GREATER:
       if (state->value_mask == stencil_max_value) {
          /* stencil_pass = fragment_mask & (reference > s) */
          /* There's no convenient Compare Less Than Immediate instruction, so
@@ -1233,9 +1233,9 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state,
       }
       break;
 
-   case PIPE_FUNC_LEQUAL:
+   case PIPE_FUNC_GEQUAL:
       if (state->value_mask == stencil_max_value) {
-         /* stencil_pass = fragment_mask & (s <= reference) 
+         /* stencil_pass = fragment_mask & (reference >= s) 
           *              = fragment_mask & ~(s > reference) */
          spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
          spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
@@ -1250,9 +1250,9 @@ gen_stencil_test(struct spe_function *f, const struct pipe_stencil_state *state,
       }
       break;
 
-   case PIPE_FUNC_GEQUAL:
+   case PIPE_FUNC_LEQUAL:
       if (state->value_mask == stencil_max_value) {
-         /* stencil_pass = fragment_mask & (s >= reference) ]
+         /* stencil_pass = fragment_mask & (reference <= s) ]
           *               = fragment_mask & ~(reference > s) */
          /* As above, we have to do this by loading a register */
          unsigned int tmp_reg = spe_allocate_available_register(f);
@@ -1779,7 +1779,7 @@ gen_stencil_depth_test(struct spe_function *f,
  * \param f     the generated function (out)
  */
 void
-cell_gen_fragment_function(struct cell_context *cell, uint facing, struct spe_function *f)
+cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct spe_function *f)
 {
    const struct pipe_depth_stencil_alpha_state *dsa = cell->depth_stencil;
    const struct pipe_blend_state *blend = cell->blend;
@@ -1813,7 +1813,7 @@ cell_gen_fragment_function(struct cell_context *cell, uint facing, struct spe_fu
    if (cell->debug_flags & CELL_DEBUG_ASM) {
       spe_print_code(f, true);
       spe_indent(f, 8);
-      spe_comment(f, -4, "Begin per-fragment ops");
+      spe_comment(f, -4, facing == CELL_FACING_FRONT ? "Begin front-facing per-fragment ops": "Begin back-facing per-fragment ops");
    }
 
    spe_allocate_register(f, x_reg);
@@ -2092,6 +2092,9 @@ cell_gen_fragment_function(struct cell_context *cell, uint facing, struct spe_fu
    spe_release_register(f, quad_offset_reg);
 
    if (cell->debug_flags & CELL_DEBUG_ASM) {
-      spe_comment(f, -4, "End per-fragment ops");
+      char buffer[1024];
+      sprintf(buffer, "End %s-facing per-fragment ops: %d instructions", 
+         facing == CELL_FACING_FRONT ? "front" : "back", f->num_inst);
+      spe_comment(f, -4, buffer);
    }
 }
diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.h b/src/gallium/drivers/cell/ppu/cell_gen_fragment.h
index 2fabfdf..21b35d1 100644
--- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.h
+++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.h
@@ -31,7 +31,7 @@
 
 
 extern void
-cell_gen_fragment_function(struct cell_context *cell, uint facing, struct spe_function *f);
+cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct spe_function *f);
 
 
 #endif /* CELL_GEN_FRAGMENT_H */




More information about the mesa-commit mailing list