From 3d7a88674f9eb3320eeff511968f041426e25023 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Fri, 21 Aug 2009 13:49:10 +0100 Subject: [PATCH] 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 +- .../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 58f6f6cd8ff..c5f6710c469 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 f372210a7a0..962ea9fafab 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 0cd6a5a95a0..118c7c52137 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 4df6cdf9849..a5de698ebbf 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 5fc85a19b84..d94af0dea40 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 */ +#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, diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.h b/src/gallium/drivers/llvmpipe/lp_bld_flow.h index 7281b278a0c..1b634ff038d 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_flow.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_flow.h @@ -38,6 +38,40 @@ #include +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 1ce9a9109e8..5b8efb05778 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 8ba73b94eda..0989f9f2078 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_logic.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_logic.h @@ -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 */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h b/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h index 7ad711e396d..e77cf26de35 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 e392a50005f..d35c8c6b7b9 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 51962e63171..521700acd52 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);; -- 2.30.2