llvmpipe: Early depth testing.

This commit is contained in:
José Fonseca 2009-08-21 13:49:10 +01:00
parent 90b5df8d1b
commit 3d7a88674f
11 changed files with 166 additions and 46 deletions

View 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);
}
}

View file

@ -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);

View 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);

View 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);

View file

@ -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,

View file

@ -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

View file

@ -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,

View 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
*/

View 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,

View 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,

View 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);;