gallivm: Support predicates.
This commit is contained in:
parent
6e47d4f889
commit
ff6c78f44f
|
@ -42,6 +42,8 @@
|
||||||
|
|
||||||
#define LP_MAX_TGSI_IMMEDIATES 256
|
#define LP_MAX_TGSI_IMMEDIATES 256
|
||||||
|
|
||||||
|
#define LP_MAX_TGSI_PREDS 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum control flow nesting
|
* Maximum control flow nesting
|
||||||
*
|
*
|
||||||
|
|
|
@ -113,6 +113,9 @@ struct lp_build_tgsi_soa_context
|
||||||
{
|
{
|
||||||
struct lp_build_context base;
|
struct lp_build_context base;
|
||||||
|
|
||||||
|
/* Builder for integer masks and indices */
|
||||||
|
struct lp_build_context int_bld;
|
||||||
|
|
||||||
LLVMValueRef consts_ptr;
|
LLVMValueRef consts_ptr;
|
||||||
const LLVMValueRef *pos;
|
const LLVMValueRef *pos;
|
||||||
const LLVMValueRef (*inputs)[NUM_CHANNELS];
|
const LLVMValueRef (*inputs)[NUM_CHANNELS];
|
||||||
|
@ -123,6 +126,7 @@ struct lp_build_tgsi_soa_context
|
||||||
LLVMValueRef immediates[LP_MAX_TGSI_IMMEDIATES][NUM_CHANNELS];
|
LLVMValueRef immediates[LP_MAX_TGSI_IMMEDIATES][NUM_CHANNELS];
|
||||||
LLVMValueRef temps[LP_MAX_TGSI_TEMPS][NUM_CHANNELS];
|
LLVMValueRef temps[LP_MAX_TGSI_TEMPS][NUM_CHANNELS];
|
||||||
LLVMValueRef addr[LP_MAX_TGSI_ADDRS][NUM_CHANNELS];
|
LLVMValueRef addr[LP_MAX_TGSI_ADDRS][NUM_CHANNELS];
|
||||||
|
LLVMValueRef preds[LP_MAX_TGSI_PREDS][NUM_CHANNELS];
|
||||||
|
|
||||||
/* we allocate an array of temps if we have indirect
|
/* we allocate an array of temps if we have indirect
|
||||||
* addressing and then the temps above is unused */
|
* addressing and then the temps above is unused */
|
||||||
|
@ -319,15 +323,25 @@ static void lp_exec_endloop(struct lp_exec_mask *mask)
|
||||||
* (0 means don't store this bit, 1 means do store).
|
* (0 means don't store this bit, 1 means do store).
|
||||||
*/
|
*/
|
||||||
static void lp_exec_mask_store(struct lp_exec_mask *mask,
|
static void lp_exec_mask_store(struct lp_exec_mask *mask,
|
||||||
|
LLVMValueRef pred,
|
||||||
LLVMValueRef val,
|
LLVMValueRef val,
|
||||||
LLVMValueRef dst)
|
LLVMValueRef dst)
|
||||||
{
|
{
|
||||||
|
/* Mix the predicate and execution mask */
|
||||||
if (mask->has_mask) {
|
if (mask->has_mask) {
|
||||||
|
if (pred) {
|
||||||
|
LLVMBuildAnd(mask->bld->builder, pred, mask->exec_mask, "");
|
||||||
|
} else {
|
||||||
|
pred = mask->exec_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pred) {
|
||||||
LLVMValueRef real_val, dst_val;
|
LLVMValueRef real_val, dst_val;
|
||||||
|
|
||||||
dst_val = LLVMBuildLoad(mask->bld->builder, dst, "");
|
dst_val = LLVMBuildLoad(mask->bld->builder, dst, "");
|
||||||
real_val = lp_build_select(mask->bld,
|
real_val = lp_build_select(mask->bld,
|
||||||
mask->exec_mask,
|
pred,
|
||||||
val, dst_val);
|
val, dst_val);
|
||||||
|
|
||||||
LLVMBuildStore(mask->bld->builder, real_val, dst);
|
LLVMBuildStore(mask->bld->builder, real_val, dst);
|
||||||
|
@ -511,6 +525,73 @@ emit_fetch_deriv(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Predicate.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
emit_fetch_predicate(
|
||||||
|
struct lp_build_tgsi_soa_context *bld,
|
||||||
|
const struct tgsi_full_instruction *inst,
|
||||||
|
LLVMValueRef *pred)
|
||||||
|
{
|
||||||
|
unsigned index;
|
||||||
|
unsigned char swizzles[4];
|
||||||
|
LLVMValueRef unswizzled[4] = {NULL, NULL, NULL, NULL};
|
||||||
|
LLVMValueRef value;
|
||||||
|
unsigned chan;
|
||||||
|
|
||||||
|
if (!inst->Instruction.Predicate) {
|
||||||
|
FOR_EACH_CHANNEL( chan ) {
|
||||||
|
pred[chan] = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
swizzles[0] = inst->Predicate.SwizzleX;
|
||||||
|
swizzles[1] = inst->Predicate.SwizzleY;
|
||||||
|
swizzles[2] = inst->Predicate.SwizzleZ;
|
||||||
|
swizzles[3] = inst->Predicate.SwizzleW;
|
||||||
|
|
||||||
|
index = inst->Predicate.Index;
|
||||||
|
assert(index < LP_MAX_TGSI_PREDS);
|
||||||
|
|
||||||
|
FOR_EACH_CHANNEL( chan ) {
|
||||||
|
unsigned swizzle = swizzles[chan];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only fetch the predicate register channels that are actually listed
|
||||||
|
* in the swizzles
|
||||||
|
*/
|
||||||
|
if (!unswizzled[swizzle]) {
|
||||||
|
value = LLVMBuildLoad(bld->base.builder,
|
||||||
|
bld->preds[index][swizzle], "");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the value to an integer mask.
|
||||||
|
*
|
||||||
|
* TODO: Short-circuit this comparison -- a D3D setp_xx instructions
|
||||||
|
* is needlessly causing two comparisons due to storing the intermediate
|
||||||
|
* result as float vector instead of an integer mask vector.
|
||||||
|
*/
|
||||||
|
value = lp_build_compare(bld->base.builder,
|
||||||
|
bld->base.type,
|
||||||
|
PIPE_FUNC_NOTEQUAL,
|
||||||
|
value,
|
||||||
|
bld->base.zero);
|
||||||
|
if (inst->Predicate.Negate) {
|
||||||
|
value = LLVMBuildNot(bld->base.builder, value, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
unswizzled[swizzle] = value;
|
||||||
|
} else {
|
||||||
|
value = unswizzled[swizzle];
|
||||||
|
}
|
||||||
|
|
||||||
|
pred[chan] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register store.
|
* Register store.
|
||||||
*/
|
*/
|
||||||
|
@ -520,6 +601,7 @@ emit_store(
|
||||||
const struct tgsi_full_instruction *inst,
|
const struct tgsi_full_instruction *inst,
|
||||||
unsigned index,
|
unsigned index,
|
||||||
unsigned chan_index,
|
unsigned chan_index,
|
||||||
|
LLVMValueRef pred,
|
||||||
LLVMValueRef value)
|
LLVMValueRef value)
|
||||||
{
|
{
|
||||||
const struct tgsi_full_dst_register *reg = &inst->Dst[index];
|
const struct tgsi_full_dst_register *reg = &inst->Dst[index];
|
||||||
|
@ -560,7 +642,7 @@ emit_store(
|
||||||
|
|
||||||
switch( reg->Register.File ) {
|
switch( reg->Register.File ) {
|
||||||
case TGSI_FILE_OUTPUT:
|
case TGSI_FILE_OUTPUT:
|
||||||
lp_exec_mask_store(&bld->exec_mask, value,
|
lp_exec_mask_store(&bld->exec_mask, pred, value,
|
||||||
bld->outputs[reg->Register.Index][chan_index]);
|
bld->outputs[reg->Register.Index][chan_index]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -569,17 +651,18 @@ emit_store(
|
||||||
chan_index,
|
chan_index,
|
||||||
reg->Register.Indirect,
|
reg->Register.Indirect,
|
||||||
addr);
|
addr);
|
||||||
lp_exec_mask_store(&bld->exec_mask, value, temp_ptr);
|
lp_exec_mask_store(&bld->exec_mask, pred, value, temp_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TGSI_FILE_ADDRESS:
|
case TGSI_FILE_ADDRESS:
|
||||||
lp_exec_mask_store(&bld->exec_mask, value,
|
lp_exec_mask_store(&bld->exec_mask, pred, value,
|
||||||
bld->addr[reg->Indirect.Index][chan_index]);
|
bld->addr[reg->Indirect.Index][chan_index]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TGSI_FILE_PREDICATE:
|
case TGSI_FILE_PREDICATE:
|
||||||
/* FIXME */
|
lp_exec_mask_store(&bld->exec_mask, pred, value,
|
||||||
|
bld->preds[index][chan_index]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -814,7 +897,10 @@ emit_declaration(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TGSI_FILE_PREDICATE:
|
case TGSI_FILE_PREDICATE:
|
||||||
_debug_printf("warning: predicate registers not yet implemented\n");
|
assert(idx < LP_MAX_TGSI_PREDS);
|
||||||
|
for (i = 0; i < NUM_CHANNELS; i++)
|
||||||
|
bld->preds[idx][i] = lp_build_alloca(bld->base.builder,
|
||||||
|
vec_type, "");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -858,7 +944,7 @@ emit_instruction(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
assert(info->num_dst <= 1);
|
assert(info->num_dst <= 1);
|
||||||
if(info->num_dst) {
|
if (info->num_dst) {
|
||||||
FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
|
FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
|
||||||
dst0[chan_index] = bld->base.undef;
|
dst0[chan_index] = bld->base.undef;
|
||||||
}
|
}
|
||||||
|
@ -1754,8 +1840,12 @@ emit_instruction(
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info->num_dst) {
|
if(info->num_dst) {
|
||||||
|
LLVMValueRef pred[NUM_CHANNELS];
|
||||||
|
|
||||||
|
emit_fetch_predicate( bld, inst, pred );
|
||||||
|
|
||||||
FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
|
FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
|
||||||
emit_store( bld, inst, 0, chan_index, dst0[chan_index]);
|
emit_store( bld, inst, 0, chan_index, pred[chan_index], dst0[chan_index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1783,6 +1873,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
|
||||||
/* Setup build context */
|
/* Setup build context */
|
||||||
memset(&bld, 0, sizeof bld);
|
memset(&bld, 0, sizeof bld);
|
||||||
lp_build_context_init(&bld.base, builder, type);
|
lp_build_context_init(&bld.base, builder, type);
|
||||||
|
lp_build_context_init(&bld.int_bld, builder, lp_int_type(type));
|
||||||
bld.mask = mask;
|
bld.mask = mask;
|
||||||
bld.pos = pos;
|
bld.pos = pos;
|
||||||
bld.inputs = inputs;
|
bld.inputs = inputs;
|
||||||
|
|
Loading…
Reference in New Issue