Mesa (gallium-llvmpipe): llvmpipe: Early depth testing.

Jose Fonseca jrfonseca at kemper.freedesktop.org
Sat Aug 22 11:40:44 UTC 2009


Module: Mesa
Branch: gallium-llvmpipe
Commit: 0b1bb7e445422360f70e1bf268795e0be79f48b5
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=0b1bb7e445422360f70e1bf268795e0be79f48b5

Author: José Fonseca <jfonseca at vmware.com>
Date:   Fri Aug 21 13:49:10 2009 +0100

llvmpipe: Early depth testing.

---

 src/gallium/drivers/llvmpipe/lp_bld_alpha.c    |    5 +-
 src/gallium/drivers/llvmpipe/lp_bld_alpha.h    |    3 +-
 src/gallium/drivers/llvmpipe/lp_bld_depth.c    |    9 ++-
 src/gallium/drivers/llvmpipe/lp_bld_depth.h    |    3 +-
 src/gallium/drivers/llvmpipe/lp_bld_flow.c     |   84 ++++++++++++++++++++++++
 src/gallium/drivers/llvmpipe/lp_bld_flow.h     |   34 ++++++++++
 src/gallium/drivers/llvmpipe/lp_bld_logic.c    |   12 ----
 src/gallium/drivers/llvmpipe/lp_bld_logic.h    |    9 ---
 src/gallium/drivers/llvmpipe/lp_bld_tgsi.h     |    3 +-
 src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c |   19 ++++--
 src/gallium/drivers/llvmpipe/lp_state_fs.c     |   31 ++++++---
 11 files changed, 166 insertions(+), 46 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
index 58f6f6c..c5f6710 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
@@ -37,6 +37,7 @@
 #include "lp_bld_const.h"
 #include "lp_bld_arit.h"
 #include "lp_bld_logic.h"
+#include "lp_bld_flow.h"
 #include "lp_bld_debug.h"
 #include "lp_bld_alpha.h"
 
@@ -45,7 +46,7 @@ void
 lp_build_alpha_test(LLVMBuilderRef builder,
                     const struct pipe_alpha_state *state,
                     union lp_type type,
-                    LLVMValueRef *mask,
+                    struct lp_build_mask_context *mask,
                     LLVMValueRef alpha)
 {
    struct lp_build_context bld;
@@ -58,6 +59,6 @@ lp_build_alpha_test(LLVMBuilderRef builder,
 
       lp_build_name(test, "alpha_mask");
 
-      lp_build_mask_and(builder, mask, test);
+      lp_build_mask_update(mask, test);
    }
 }
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
index f372210..962ea9f 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
@@ -39,13 +39,14 @@
 
 struct pipe_alpha_state;
 union lp_type;
+struct lp_build_mask_context;
 
 
 void
 lp_build_alpha_test(LLVMBuilderRef builder,
                     const struct pipe_alpha_state *state,
                     union lp_type type,
-                    LLVMValueRef *mask,
+                    struct lp_build_mask_context *mask,
                     LLVMValueRef alpha);
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
index 0cd6a5a..118c7c5 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
@@ -37,6 +37,7 @@
 #include "lp_bld_type.h"
 #include "lp_bld_const.h"
 #include "lp_bld_logic.h"
+#include "lp_bld_flow.h"
 #include "lp_bld_debug.h"
 #include "lp_bld_depth.h"
 
@@ -83,7 +84,7 @@ lp_build_depth_test(LLVMBuilderRef builder,
                     const struct pipe_depth_state *state,
                     union lp_type type,
                     const struct util_format_description *format_desc,
-                    LLVMValueRef *mask,
+                    struct lp_build_mask_context *mask,
                     LLVMValueRef src,
                     LLVMValueRef dst_ptr)
 {
@@ -165,13 +166,13 @@ lp_build_depth_test(LLVMBuilderRef builder,
    lp_build_name(dst, "zsbuf.z");
 
    test = lp_build_cmp(&bld, state->func, src, dst);
-   lp_build_mask_and(bld.builder, mask, test);
+   lp_build_mask_update(mask, test);
 
    if(state->writemask) {
       if(z_bitmask)
-         z_bitmask = LLVMBuildAnd(builder, *mask, z_bitmask, "");
+         z_bitmask = LLVMBuildAnd(builder, mask->value, z_bitmask, "");
       else
-         z_bitmask = *mask;
+         z_bitmask = mask->value;
 
       dst = lp_build_select(&bld, z_bitmask, src, dst);
       LLVMBuildStore(builder, dst, dst_ptr);
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
index 4df6cdf..a5de698 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
@@ -42,6 +42,7 @@
 struct pipe_depth_state;
 struct util_format_description;
 union lp_type;
+struct lp_build_mask_context;
 
 
 /**
@@ -57,7 +58,7 @@ lp_build_depth_test(LLVMBuilderRef builder,
                     const struct pipe_depth_state *state,
                     union lp_type type,
                     const struct util_format_description *format_desc,
-                    LLVMValueRef *mask,
+                    struct lp_build_mask_context *mask,
                     LLVMValueRef src,
                     LLVMValueRef dst_ptr);
 
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.c b/src/gallium/drivers/llvmpipe/lp_bld_flow.c
index 5fc85a1..d94af0d 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_flow.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_flow.c
@@ -31,9 +31,93 @@
  * @author Jose Fonseca <jfonseca at vmware.com>
  */
 
+#include "util/u_debug.h"
+
+#include "lp_bld_type.h"
 #include "lp_bld_flow.h"
 
 
+void
+lp_build_mask_begin(struct lp_build_mask_context *mask,
+                    LLVMBuilderRef builder,
+                    union lp_type type,
+                    LLVMValueRef value)
+{
+   memset(mask, 0, sizeof *mask);
+
+   mask->builder = builder;
+   mask->reg_type = LLVMIntType(type.width * type.length);
+   mask->value = value;
+}
+
+
+void
+lp_build_mask_update(struct lp_build_mask_context *mask,
+                     LLVMValueRef value)
+{
+
+   LLVMValueRef cond;
+   LLVMBasicBlockRef current_block;
+   LLVMBasicBlockRef next_block;
+   LLVMBasicBlockRef new_block;
+
+   if(mask->value)
+      mask->value = LLVMBuildAnd(mask->builder, mask->value, value, "");
+   else
+      mask->value = value;
+
+   cond = LLVMBuildICmp(mask->builder,
+                        LLVMIntEQ,
+                        LLVMBuildBitCast(mask->builder, mask->value, mask->reg_type, ""),
+                        LLVMConstNull(mask->reg_type),
+                        "");
+
+   current_block = LLVMGetInsertBlock(mask->builder);
+
+   if(!mask->skip_block) {
+      LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
+      mask->skip_block = LLVMAppendBasicBlock(function, "skip");
+
+      mask->phi = LLVMBuildPhi(mask->builder, LLVMTypeOf(mask->value), "");
+   }
+
+   next_block = LLVMGetNextBasicBlock(current_block);
+   assert(next_block);
+   if(next_block) {
+      new_block = LLVMInsertBasicBlock(next_block, "");
+   }
+   else {
+      LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
+      new_block = LLVMAppendBasicBlock(function, "");
+   }
+
+   LLVMAddIncoming(mask->phi, &mask->value, &current_block, 1);
+   LLVMBuildCondBr(mask->builder, cond, mask->skip_block, new_block);
+
+   LLVMPositionBuilderAtEnd(mask->builder, new_block);
+}
+
+
+LLVMValueRef
+lp_build_mask_end(struct lp_build_mask_context *mask)
+{
+   if(mask->skip_block) {
+      LLVMBasicBlockRef current_block = LLVMGetInsertBlock(mask->builder);
+
+      LLVMAddIncoming(mask->phi, &mask->value, &current_block, 1);
+      LLVMBuildBr(mask->builder, mask->skip_block);
+
+      LLVMPositionBuilderAtEnd(mask->builder, mask->skip_block);
+
+      mask->value = mask->phi;
+      mask->phi = NULL;
+      mask->skip_block = NULL;
+   }
+
+   return mask->value;
+}
+
+
 
 void
 lp_build_loop_begin(LLVMBuilderRef builder,
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.h b/src/gallium/drivers/llvmpipe/lp_bld_flow.h
index 7281b27..1b634ff 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_flow.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_flow.h
@@ -38,6 +38,40 @@
 #include <llvm-c/Core.h>  
 
 
+union lp_type;
+
+
+struct lp_build_mask_context
+{
+   LLVMBuilderRef builder;
+
+   LLVMTypeRef reg_type;
+
+   LLVMValueRef value;
+
+   LLVMValueRef phi;
+
+   LLVMBasicBlockRef skip_block;
+};
+
+
+void
+lp_build_mask_begin(struct lp_build_mask_context *mask,
+                    LLVMBuilderRef builder,
+                    union lp_type type,
+                    LLVMValueRef value);
+
+/**
+ * Bitwise AND the mask with the given value, if a previous mask was set.
+ */
+void
+lp_build_mask_update(struct lp_build_mask_context *mask,
+                     LLVMValueRef value);
+
+LLVMValueRef
+lp_build_mask_end(struct lp_build_mask_context *mask);
+
+
 /**
  * LLVM's IR doesn't represent for-loops directly. Furthermore it
  * it requires creating code blocks, branches, phi variables, so it
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_logic.c b/src/gallium/drivers/llvmpipe/lp_bld_logic.c
index 1ce9a91..5b8efb0 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_logic.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_logic.c
@@ -33,18 +33,6 @@
 #include "lp_bld_logic.h"
 
 
-void
-lp_build_mask_and(LLVMBuilderRef builder,
-                  LLVMValueRef *mask,
-                  LLVMValueRef value)
-{
-   if(*mask)
-      *mask = LLVMBuildAnd(builder, *mask, value, "");
-   else
-      *mask = value;
-}
-
-
 LLVMValueRef
 lp_build_cmp(struct lp_build_context *bld,
              unsigned func,
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_logic.h b/src/gallium/drivers/llvmpipe/lp_bld_logic.h
index 8ba73b9..0989f9f 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_logic.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_logic.h
@@ -45,15 +45,6 @@ struct lp_build_context;
 
 
 /**
- * Bitwise AND the mask with the given value, if a previous mask was set.
- */
-void
-lp_build_mask_and(LLVMBuilderRef builder,
-                  LLVMValueRef *mask,
-                  LLVMValueRef value);
-
-
-/**
  * @param func is one of PIPE_FUNC_xxx
  */
 LLVMValueRef
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h b/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h
index 7ad711e..e77cf26 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h
@@ -34,6 +34,7 @@
 struct tgsi_token;
 union lp_type;
 struct lp_build_context;
+struct lp_build_mask_context;
 
 void PIPE_CDECL
 lp_build_tgsi_fetch_texel_soa( struct tgsi_sampler **samplers,
@@ -44,7 +45,7 @@ void
 lp_build_tgsi_soa(LLVMBuilderRef builder,
                   const struct tgsi_token *tokens,
                   union lp_type type,
-                  LLVMValueRef *mask,
+                  struct lp_build_mask_context *mask,
                   LLVMValueRef *pos,
                   LLVMValueRef a0_ptr,
                   LLVMValueRef dadx_ptr,
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c
index e392a50..d35c8c6 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c
@@ -41,6 +41,7 @@
 #include "lp_bld_arit.h"
 #include "lp_bld_logic.h"
 #include "lp_bld_swizzle.h"
+#include "lp_bld_flow.h"
 #include "lp_bld_tgsi.h"
 #include "lp_bld_debug.h"
 
@@ -88,7 +89,7 @@ struct lp_build_tgsi_soa_context
    LLVMValueRef immediates[LP_MAX_IMMEDIATES][NUM_CHANNELS];
    LLVMValueRef temps[LP_MAX_TEMPS][NUM_CHANNELS];
 
-   LLVMValueRef *mask;
+   struct lp_build_mask_context *mask;
 
    /** Coords/texels store */
    LLVMValueRef store_ptr;
@@ -367,6 +368,7 @@ emit_kil(
 {
    const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[0];
    LLVMValueRef terms[NUM_CHANNELS];
+   LLVMValueRef mask;
    unsigned chan_index;
 
    memset(&terms, 0, sizeof terms);
@@ -389,15 +391,22 @@ emit_kil(
          terms[swizzle] =  emit_fetch(bld, inst, 0, chan_index );
    }
 
+   mask = NULL;
    FOR_EACH_CHANNEL( chan_index ) {
       if(terms[chan_index]) {
-         LLVMValueRef mask;
+         LLVMValueRef chan_mask;
 
-         mask = lp_build_cmp(&bld->base, PIPE_FUNC_GEQUAL, terms[chan_index], bld->base.zero);
+         chan_mask = lp_build_cmp(&bld->base, PIPE_FUNC_GEQUAL, terms[chan_index], bld->base.zero);
 
-         lp_build_mask_and(bld->base.builder, bld->mask, mask);
+         if(mask)
+            mask = LLVMBuildAnd(bld->base.builder, mask, chan_mask, "");
+         else
+            mask = chan_mask;
       }
    }
+
+   if(mask)
+      lp_build_mask_update(bld->mask, mask);
 }
 
 
@@ -1411,7 +1420,7 @@ void
 lp_build_tgsi_soa(LLVMBuilderRef builder,
                   const struct tgsi_token *tokens,
                   union lp_type type,
-                  LLVMValueRef *mask,
+                  struct lp_build_mask_context *mask,
                   LLVMValueRef *pos,
                   LLVMValueRef a0_ptr,
                   LLVMValueRef dadx_ptr,
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 51962e6..521700a 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -42,6 +42,7 @@
 #include "lp_bld_tgsi.h"
 #include "lp_bld_alpha.h"
 #include "lp_bld_swizzle.h"
+#include "lp_bld_flow.h"
 #include "lp_bld_debug.h"
 #include "lp_screen.h"
 #include "lp_context.h"
@@ -113,7 +114,7 @@ depth_test_generate(struct llvmpipe_context *lp,
                     LLVMBuilderRef builder,
                     const struct pipe_depth_state *state,
                     union lp_type src_type,
-                    LLVMValueRef *mask,
+                    struct lp_build_mask_context *mask,
                     LLVMValueRef src,
                     LLVMValueRef dst_ptr)
 {
@@ -178,7 +179,8 @@ shader_generate(struct llvmpipe_context *lp,
    LLVMBuilderRef builder;
    LLVMValueRef pos[NUM_CHANNELS];
    LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
-   LLVMValueRef mask;
+   struct lp_build_mask_context mask;
+   boolean early_depth_test;
    LLVMValueRef fetch_texel;
    unsigned i;
    unsigned attrib;
@@ -260,16 +262,20 @@ shader_generate(struct llvmpipe_context *lp,
 
    setup_pos_vector(builder, x, y, a0_ptr, dadx_ptr, dady_ptr, pos);
 
-   mask = LLVMBuildLoad(builder, mask_ptr, "");
+   lp_build_mask_begin(&mask, builder, type,
+                       LLVMBuildLoad(builder, mask_ptr, ""));
 
-   /* FIXME:
    early_depth_test =
       lp->depth_stencil->depth.enabled &&
       lp->framebuffer.zsbuf &&
       !lp->depth_stencil->alpha.enabled &&
       !lp->fs->info.uses_kill &&
       !lp->fs->info.writes_z;
-   */
+
+   if(early_depth_test)
+      depth_test_generate(lp, builder, &key->depth,
+                          type, &mask,
+                          pos[2], depth_ptr);
 
    memset(outputs, 0, sizeof outputs);
 
@@ -294,7 +300,8 @@ shader_generate(struct llvmpipe_context *lp,
                   /* Alpha test */
                   /* XXX: should the alpha reference value be passed separately? */
                   if(cbuf == 0 && chan == 3)
-                     lp_build_alpha_test(builder, &key->alpha, type, &mask,
+                     lp_build_alpha_test(builder, &key->alpha, type,
+                                         &mask,
                                          outputs[attrib][chan]);
 
                   break;
@@ -309,12 +316,14 @@ shader_generate(struct llvmpipe_context *lp,
       }
    }
 
-   depth_test_generate(lp, builder, &key->depth,
-                       type, &mask,
-                       pos[2], depth_ptr);
+   if(!early_depth_test)
+      depth_test_generate(lp, builder, &key->depth,
+                          type, &mask,
+                          pos[2], depth_ptr);
 
-   if(mask)
-      LLVMBuildStore(builder, mask, mask_ptr);
+   lp_build_mask_end(&mask);
+   if(mask.value)
+      LLVMBuildStore(builder, mask.value, mask_ptr);
 
    LLVMBuildRetVoid(builder);;
 




More information about the mesa-commit mailing list