summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_alpha.c5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_alpha.h3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_depth.c9
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_depth.h3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_flow.c84
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_flow.h34
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_logic.c12
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_logic.h9
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_tgsi.h3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c19
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c31
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 58f6f6cd8f..c5f6710c46 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 f372210a7a..962ea9fafa 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 0cd6a5a95a..118c7c5213 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 4df6cdf984..a5de698ebb 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 5fc85a19b8..d94af0dea4 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@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 7281b278a0..1b634ff038 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 1ce9a9109e..5b8efb0577 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 8ba73b94ed..0989f9f207 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 7ad711e396..e77cf26de3 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 e392a50005..d35c8c6b7b 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 51962e6317..521700acd5 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);;