llvmpipe: Early depth testing.
authorJosé Fonseca <jfonseca@vmware.com>
Fri, 21 Aug 2009 12:49:10 +0000 (13:49 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Sat, 29 Aug 2009 08:21:39 +0000 (09:21 +0100)
src/gallium/drivers/llvmpipe/lp_bld_alpha.c
src/gallium/drivers/llvmpipe/lp_bld_alpha.h
src/gallium/drivers/llvmpipe/lp_bld_depth.c
src/gallium/drivers/llvmpipe/lp_bld_depth.h
src/gallium/drivers/llvmpipe/lp_bld_flow.c
src/gallium/drivers/llvmpipe/lp_bld_flow.h
src/gallium/drivers/llvmpipe/lp_bld_logic.c
src/gallium/drivers/llvmpipe/lp_bld_logic.h
src/gallium/drivers/llvmpipe/lp_bld_tgsi.h
src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 58f6f6cd8ff265b0a5ab5df4cea9d79b5a20ba13..c5f6710c469a40bff91e0f8c40150c384e55f6cd 100644 (file)
@@ -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);
    }
 }
index f372210a7a0201b1d61d80fde3bb2de0a93deda1..962ea9fafab8de6cc0433de05982b9ad3dc5567c 100644 (file)
 
 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);
 
 
index 0cd6a5a95a00e30e05ab07e2809817fa584dfa24..118c7c521379e0f340544aa15c59ddad8442e04b 100644 (file)
@@ -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);
index 4df6cdf9849f9312d0863eee3a313201fbc0e65e..a5de698ebbfe7182ca293f22f698efc05b6f8116 100644 (file)
@@ -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);
 
index 5fc85a19b843961f3ccd4f1be566c139acbd30f9..d94af0dea4006c1e42ade3afc7fbc84c1fa42ba2 100644 (file)
  * @author Jose Fonseca <jfonseca@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,
index 7281b278a0c3a285ea843dad207b6c4d0fcb325c..1b634ff038dec03102f05af7fd36decc6c5ee148 100644 (file)
 #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
index 1ce9a9109e89f2e00b2596c615d0729436cab9a2..5b8efb05778a8249564537fa12efe011e4f7f146 100644 (file)
 #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,
index 8ba73b94eda05f0328ce34bb1d4b2ddde19e9ced..0989f9f20784a0c9e48eedc746304823c51e17d0 100644 (file)
@@ -44,15 +44,6 @@ union lp_type type;
 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
  */
index 7ad711e396d2fcc633b7a9c9b8b0fb4a606fdd1d..e77cf26de354b562f2be9c30d48657fe06b63517 100644 (file)
@@ -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,
index e392a50005fe79e60d72c482af9ec3f0cc3a3595..d35c8c6b7b99a89bc9d6429b7002081686601e13 100644 (file)
@@ -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,
index 51962e63171b47d555a83fd9511d5790a232eaef..521700acd52180f0d6f35fa0cc4eb37f97d4c179 100644 (file)
@@ -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);;