#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"
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;
lp_build_name(test, "alpha_mask");
- lp_build_mask_and(builder, mask, test);
+ lp_build_mask_update(mask, test);
}
}
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);
#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"
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)
{
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);
struct pipe_depth_state;
struct util_format_description;
union lp_type;
+struct lp_build_mask_context;
/**
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);
* @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, ¤t_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, ¤t_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,
#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
#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,
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
*/
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,
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,
#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"
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;
{
const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[0];
LLVMValueRef terms[NUM_CHANNELS];
+ LLVMValueRef mask;
unsigned chan_index;
memset(&terms, 0, sizeof terms);
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);
}
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,
#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"
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)
{
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;
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);
/* 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;
}
}
- 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);;