[Mesa-dev] [PATCH 7/8] i965/fs: Add support for TXD with shadow comparisons on gen4-6.

Kenneth Graunke kenneth at whitecape.org
Wed Jun 15 01:24:54 PDT 2011


Gen4-6 don't have a sample_d_c message, so we have to do a regular
sample_d and emit instructions to manually perform the comparison.

This requires a state dependent recompile whenever ctx->Depth.Func
changes.  do_wm_prog looks for a compiled program in the cache based off
of brw_wm_prog_key, and if it doesn't find one, recompiles.  So we
simply need to add the depth comparison function to the key; the
_NEW_DEPTH dirty bit was already in-place.

Of course, this is unnecessary in every other case, so I leave
key->depth_comparison_func as 0 unless it's actually relevant.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
 src/mesa/drivers/dri/i965/brw_fs_emit.cpp    |    4 +-
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp |   51 ++++++++++++++++++++++++--
 src/mesa/drivers/dri/i965/brw_wm.h           |    1 +
 3 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
index 636ef4e..8bd8b01 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
@@ -276,7 +276,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
 	 if (inst->shadow_compare && intel->gen >= 7) {
 	    msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_DERIVS_COMPARE;
 	 } else {
-	    assert(intel->gen >= 7 || !inst->shadow_compare); // shadow comparisons not supported on gen5-6 yet.
+	    /* TXD with shadow comparison is handled specially pre-Ivybridge */
 	    msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS;
 	 }
 	 break;
@@ -316,7 +316,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
 	 }
 	 break;
       case FS_OPCODE_TXD:
-	 assert(!inst->shadow_compare); // not supported yet
+	 /* TXD with shadow comparison is handled specially pre-Ivybridge */
 	 assert(inst->mlen == 7 || inst->mlen == 10);
 	 msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS;
 	 break;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 03687ce..67344bd 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -744,7 +744,7 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate,
    }
    mlen += ir->coordinate->type->vector_elements * reg_width;
 
-   if (ir->shadow_comparitor) {
+   if (ir->shadow_comparitor && ir->op != ir_txd) {
       mlen = MAX2(mlen, header_present + 4 * reg_width);
 
       this->result = reg_undef;
@@ -934,6 +934,21 @@ fs_visitor::visit(ir_texture *ir)
    int sampler = _mesa_get_sampler_uniform_value(ir->sampler, prog, &fp->Base);
    sampler = fp->Base.SamplerUnits[sampler];
 
+   /* Pre-Ivybridge doesn't have a sample_d_c message, so shadow compares
+    * for textureGrad/TXD need to be emulated with instructions.
+    */
+   bool hw_compare_supported = ir->op != ir_txd || intel->gen > 7;
+   if (ir->shadow_comparitor && !hw_compare_supported) {
+      /* Mark that this program is only valid for the current glDepthFunc */
+      c->key.depth_compare_func = ctx->Depth.Func;
+
+      /* No need to even sample for GL_ALWAYS or GL_NEVER...bail early */
+      if (ctx->Depth.Func == GL_ALWAYS)
+	 return swizzle_shadow_result(ir, fs_reg(1.0f), sampler);
+      else if (ctx->Depth.Func == GL_NEVER)
+	 return swizzle_shadow_result(ir, fs_reg(0.0f), sampler);
+   }
+
    this->result = reg_undef;
    ir->coordinate->accept(this);
    fs_reg coordinate = this->result;
@@ -1044,8 +1059,38 @@ fs_visitor::visit(ir_texture *ir)
 
    this->result = dst;
 
-   if (ir->shadow_comparitor)
-      inst->shadow_compare = true;
+   if (ir->shadow_comparitor) {
+      if (hw_compare_supported) {
+	 inst->shadow_compare = true;
+      } else {
+	 fs_reg result = fs_reg(this, glsl_type::vec4_type);
+	 fs_reg z = coordinate;
+	 z.reg_offset = 2;
+
+	 /* FINISHME: This needs to be done pre-filtering. */
+
+	 uint32_t conditional = 0;
+	 switch (ctx->Depth.Func) {
+	 /* GL_ALWAYS and GL_NEVER were handled at the top of the function */
+	 case GL_LESS:     conditional = BRW_CONDITIONAL_L;   break;
+	 case GL_GREATER:  conditional = BRW_CONDITIONAL_G;   break;
+	 case GL_LEQUAL:   conditional = BRW_CONDITIONAL_LE;  break;
+	 case GL_GEQUAL:   conditional = BRW_CONDITIONAL_GE;  break;
+	 case GL_EQUAL:    conditional = BRW_CONDITIONAL_EQ;  break;
+	 case GL_NOTEQUAL: conditional = BRW_CONDITIONAL_NEQ; break;
+	 default: assert(!"Should not get here: bad ctx->Depth.Func");
+	 }
+
+	 /* r = (coordinate.z < sample result) ? 1.0 : 0.0 */
+	 inst = emit(BRW_OPCODE_MOV, result, fs_reg(0.0f));
+	 inst = emit(BRW_OPCODE_CMP, reg_null_f, z, dst);
+	 inst->conditional_mod = conditional;
+	 inst = emit(BRW_OPCODE_MOV, result, fs_reg(1.0f));
+	 inst->predicated = true;
+
+	 dst = result;
+      }
+   }
 
    swizzle_shadow_result(ir, dst, sampler);
 }
diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h
index e244b55..0b284b6 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.h
+++ b/src/mesa/drivers/dri/i965/brw_wm.h
@@ -67,6 +67,7 @@ struct brw_wm_prog_key {
    GLuint alpha_test:1;
    GLuint clamp_fragment_color:1;
    GLuint line_aa:2;
+   uint8_t depth_compare_func; /* 0 if irrelevant, GL_LESS etc. otherwise */
 
    GLbitfield proj_attrib_mask; /**< one bit per fragment program attribute */
    GLuint yuvtex_mask:16;
-- 
1.7.5.4



More information about the mesa-dev mailing list