mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 14:38:06 +02:00
llvmpipe: Early depth testing.
This commit is contained in:
parent
90b5df8d1b
commit
3d7a88674f
11 changed files with 166 additions and 46 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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, ¤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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue