#include "lp_bld_type.h"
#include "lp_bld_const.h"
#include "lp_bld_arit.h"
+#include "lp_bld_bitarit.h"
#include "lp_bld_gather.h"
#include "lp_bld_logic.h"
#include "lp_bld_swizzle.h"
struct lp_build_context base;
/* Builder for integer masks and indices */
- struct lp_build_context int_bld;
+ struct lp_build_context uint_bld;
LLVMValueRef consts_ptr;
const LLVMValueRef *pos;
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
- * addressing and then the temps above is unused */
+ /* We allocate/use this array of temps if (1 << TGSI_FILE_TEMPORARY) is
+ * set in the indirect_files field.
+ * The temps[] array above is unused then.
+ */
LLVMValueRef temps_array;
- boolean has_indirect_addressing;
+
+ const struct tgsi_shader_info *info;
+ /** bitmask indicating which register files are accessed indirectly */
+ unsigned indirect_files;
struct lp_build_mask_context *mask;
struct lp_exec_mask exec_mask;
}
mask->cond_stack[mask->cond_stack_size++] = mask->cond_mask;
assert(LLVMTypeOf(val) == mask->int_vec_type);
- mask->cond_mask = val;
-
+ mask->cond_mask = LLVMBuildAnd(mask->bld->builder,
+ mask->cond_mask,
+ val,
+ "");
lp_exec_mask_update(mask);
}
unsigned chan)
{
assert(chan < 4);
- if (bld->has_indirect_addressing) {
+ if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
LLVMValueRef lindex = lp_build_const_int32(index * 4 + chan);
return LLVMBuildGEP(bld->base.builder, bld->temps_array, &lindex, 1, "");
}
}
+/**
+ * Read the current value of the ADDR register, convert the floats to
+ * ints, multiply by four and return the vector of offsets.
+ * The offsets will be used to index into the constant buffer or
+ * temporary register file.
+ */
+static LLVMValueRef
+get_indirect_index(struct lp_build_tgsi_soa_context *bld,
+ unsigned reg_file, unsigned reg_index,
+ const struct tgsi_src_register *indirect_reg)
+{
+ struct lp_build_context *uint_bld = &bld->uint_bld;
+ /* always use X component of address register */
+ unsigned swizzle = indirect_reg->SwizzleX;
+ LLVMValueRef base;
+ LLVMValueRef rel;
+ LLVMValueRef max_index;
+ LLVMValueRef index;
+
+ assert(bld->indirect_files & (1 << reg_file));
+
+ base = lp_build_const_int_vec(uint_bld->type, reg_index);
+
+ assert(swizzle < 4);
+ rel = LLVMBuildLoad(bld->base.builder,
+ bld->addr[indirect_reg->Index][swizzle],
+ "load addr reg");
+
+ /* for indexing we want integers */
+ rel = LLVMBuildFPToSI(bld->base.builder,
+ rel,
+ uint_bld->vec_type, "");
+
+ index = lp_build_add(uint_bld, base, rel);
+
+ max_index = lp_build_const_int_vec(uint_bld->type,
+ bld->info->file_max[reg_file]);
+
+ assert(!uint_bld->type.sign);
+ index = lp_build_min(uint_bld, index, max_index);
+
+ return index;
+}
+
+
/**
* Register fetch.
*/
unsigned src_op,
const unsigned chan_index )
{
+ struct lp_build_context *uint_bld = &bld->uint_bld;
const struct tgsi_full_src_register *reg = &inst->Src[src_op];
const unsigned swizzle =
tgsi_util_get_full_src_register_swizzle(reg, chan_index);
LLVMValueRef res;
- LLVMValueRef addr_vec = NULL;
+ LLVMValueRef indirect_index = NULL;
if (swizzle > 3) {
assert(0 && "invalid swizzle in emit_fetch()");
}
if (reg->Register.Indirect) {
- LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
- unsigned swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, chan_index );
-
- LLVMValueRef vec4 = lp_build_const_int_vec(bld->int_bld.type, 4);
-
- assert(bld->has_indirect_addressing);
-
- addr_vec = LLVMBuildLoad(bld->base.builder,
- bld->addr[reg->Indirect.Index][swizzle],
- "load addr");
-
- /* for indexing we want integers */
- addr_vec = LLVMBuildFPToSI(bld->base.builder, addr_vec,
- int_vec_type, "");
-
- /* addr_vec = addr_vec * 4 */
- addr_vec = lp_build_mul(&bld->base, addr_vec, vec4);
+ indirect_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Register.Index,
+ ®->Indirect);
+ } else {
+ assert(reg->Register.Index <= bld->info->file_max[reg->Register.File]);
}
switch (reg->Register.File) {
case TGSI_FILE_CONSTANT:
if (reg->Register.Indirect) {
+ LLVMValueRef swizzle_vec =
+ lp_build_const_int_vec(uint_bld->type, swizzle);
LLVMValueRef index_vec; /* index into the const buffer */
- /* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
- index_vec = lp_build_const_int_vec(bld->int_bld.type,
- reg->Register.Index * 4 + swizzle);
-
- /* index_vec = index_vec + addr_vec */
- index_vec = lp_build_add(&bld->base, index_vec, addr_vec);
+ /* index_vec = indirect_index * 4 + swizzle */
+ index_vec = lp_build_shl_imm(uint_bld, indirect_index, 2);
+ index_vec = lp_build_add(uint_bld, index_vec, swizzle_vec);
/* Gather values from the constant buffer */
res = build_gather(bld, bld->consts_ptr, index_vec);
case TGSI_FILE_TEMPORARY:
if (reg->Register.Indirect) {
- LLVMValueRef vec_len =
- lp_build_const_int_vec(bld->int_bld.type, bld->base.type.length);
+ LLVMValueRef swizzle_vec =
+ lp_build_const_int_vec(uint_bld->type, swizzle);
+ LLVMValueRef length_vec =
+ lp_build_const_int_vec(uint_bld->type, bld->base.type.length);
LLVMValueRef index_vec; /* index into the const buffer */
LLVMValueRef temps_array;
LLVMTypeRef float4_ptr_type;
- assert(bld->has_indirect_addressing);
-
- /* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
- index_vec = lp_build_const_int_vec(bld->int_bld.type,
- reg->Register.Index * 4 + swizzle);
-
- /* index_vec += addr_vec */
- index_vec = lp_build_add(&bld->int_bld, index_vec, addr_vec);
-
- /* index_vec *= vector_length */
- index_vec = lp_build_mul(&bld->int_bld, index_vec, vec_len);
+ /* index_vec = (indirect_index * 4 + swizzle) * length */
+ index_vec = lp_build_shl_imm(uint_bld, indirect_index, 2);
+ index_vec = lp_build_add(uint_bld, index_vec, swizzle_vec);
+ index_vec = lp_build_mul(uint_bld, index_vec, length_vec);
/* cast temps_array pointer to float* */
float4_ptr_type = LLVMPointerType(LLVMFloatType(), 0);
- temps_array = LLVMBuildBitCast(bld->int_bld.builder, bld->temps_array,
+ temps_array = LLVMBuildBitCast(uint_bld->builder, bld->temps_array,
float4_ptr_type, "");
/* Gather values from the temporary register array */
break;
case TGSI_UTIL_SIGN_SET:
- /* TODO: Use bitwese OR for floating point */
res = lp_build_abs( &bld->base, res );
- res = LLVMBuildNeg( bld->base.builder, res, "" );
- break;
-
+ /* fall through */
case TGSI_UTIL_SIGN_TOGGLE:
- res = LLVMBuildNeg( bld->base.builder, res, "" );
+ res = lp_build_negate( &bld->base, res );
break;
case TGSI_UTIL_SIGN_KEEP:
LLVMValueRef value)
{
const struct tgsi_full_dst_register *reg = &inst->Dst[index];
- LLVMValueRef addr = NULL;
+ LLVMValueRef indirect_index = NULL;
switch( inst->Instruction.Saturate ) {
case TGSI_SAT_NONE:
}
if (reg->Register.Indirect) {
- LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
- unsigned swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, chan_index );
- addr = LLVMBuildLoad(bld->base.builder,
- bld->addr[reg->Indirect.Index][swizzle],
- "");
- /* for indexing we want integers */
- addr = LLVMBuildFPToSI(bld->base.builder, addr,
- int_vec_type, "");
- addr = LLVMBuildExtractElement(bld->base.builder,
- addr, LLVMConstInt(LLVMInt32Type(), 0, 0),
- "");
- addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0));
+ indirect_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Register.Index,
+ ®->Indirect);
+ } else {
+ assert(reg->Register.Index <= bld->info->file_max[reg->Register.File]);
}
switch( reg->Register.File ) {
case TGSI_FILE_PREDICATE:
lp_exec_mask_store(&bld->exec_mask, pred, value,
- bld->preds[index][chan_index]);
+ bld->preds[reg->Register.Index][chan_index]);
break;
default:
* High-level instruction translators.
*/
-enum tex_modifier {
- TEX_MODIFIER_NONE = 0,
- TEX_MODIFIER_PROJECTED,
- TEX_MODIFIER_LOD_BIAS,
- TEX_MODIFIER_EXPLICIT_LOD,
- TEX_MODIFIER_EXPLICIT_DERIV
-};
-
static void
emit_tex( struct lp_build_tgsi_soa_context *bld,
const struct tgsi_full_instruction *inst,
- enum tex_modifier modifier,
+ enum lp_build_tex_modifier modifier,
LLVMValueRef *texel)
{
unsigned unit;
return;
}
- if (modifier == TEX_MODIFIER_LOD_BIAS) {
+ if (modifier == LP_BLD_TEX_MODIFIER_LOD_BIAS) {
lod_bias = emit_fetch( bld, inst, 0, 3 );
explicit_lod = NULL;
}
- else if (modifier == TEX_MODIFIER_EXPLICIT_LOD) {
+ else if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_LOD) {
lod_bias = NULL;
explicit_lod = emit_fetch( bld, inst, 0, 3 );
}
explicit_lod = NULL;
}
- if (modifier == TEX_MODIFIER_PROJECTED) {
+ if (modifier == LP_BLD_TEX_MODIFIER_PROJECTED) {
oow = emit_fetch( bld, inst, 0, 3 );
oow = lp_build_rcp(&bld->base, oow);
}
for (i = 0; i < num_coords; i++) {
coords[i] = emit_fetch( bld, inst, 0, i );
- if (modifier == TEX_MODIFIER_PROJECTED)
+ if (modifier == LP_BLD_TEX_MODIFIER_PROJECTED)
coords[i] = lp_build_mul(&bld->base, coords[i], oow);
}
for (i = num_coords; i < 3; i++) {
coords[i] = bld->base.undef;
}
- if (modifier == TEX_MODIFIER_EXPLICIT_DERIV) {
+ if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV) {
for (i = 0; i < num_coords; i++) {
ddx[i] = emit_fetch( bld, inst, 1, i );
ddy[i] = emit_fetch( bld, inst, 2, i );
struct lp_build_tgsi_soa_context *bld,
const struct tgsi_full_declaration *decl)
{
- LLVMTypeRef vec_type = lp_build_vec_type(bld->base.type);
+ LLVMTypeRef vec_type = bld->base.vec_type;
unsigned first = decl->Range.First;
unsigned last = decl->Range.Last;
unsigned idx, i;
for (idx = first; idx <= last; ++idx) {
+ assert(last <= bld->info->file_max[decl->Declaration.File]);
switch (decl->Declaration.File) {
case TGSI_FILE_TEMPORARY:
assert(idx < LP_MAX_TGSI_TEMPS);
- if (bld->has_indirect_addressing) {
+ if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
LLVMValueRef array_size = LLVMConstInt(LLVMInt32Type(),
last*4 + 4, 0);
bld->temps_array = lp_build_array_alloca(bld->base.builder,
break;
case TGSI_OPCODE_TEX:
- emit_tex( bld, inst, TEX_MODIFIER_NONE, dst0 );
+ emit_tex( bld, inst, LP_BLD_TEX_MODIFIER_NONE, dst0 );
break;
case TGSI_OPCODE_TXD:
- emit_tex( bld, inst, TEX_MODIFIER_EXPLICIT_DERIV, dst0 );
+ emit_tex( bld, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV, dst0 );
break;
case TGSI_OPCODE_UP2H:
break;
case TGSI_OPCODE_TXB:
- emit_tex( bld, inst, TEX_MODIFIER_LOD_BIAS, dst0 );
+ emit_tex( bld, inst, LP_BLD_TEX_MODIFIER_LOD_BIAS, dst0 );
break;
case TGSI_OPCODE_NRM:
break;
case TGSI_OPCODE_TXL:
- emit_tex( bld, inst, TEX_MODIFIER_EXPLICIT_LOD, dst0 );
+ emit_tex( bld, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_LOD, dst0 );
break;
case TGSI_OPCODE_TXP:
- emit_tex( bld, inst, TEX_MODIFIER_PROJECTED, dst0 );
+ emit_tex( bld, inst, LP_BLD_TEX_MODIFIER_PROJECTED, dst0 );
break;
case TGSI_OPCODE_BRK:
unsigned i;
int pc = 0;
+ struct lp_type res_type;
+
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
+ memset(&res_type, 0, sizeof res_type);
+ res_type.width = type.width;
+ res_type.length = type.length;
+ res_type.sign = 1;
+
/* Setup build context */
memset(&bld, 0, sizeof bld);
lp_build_context_init(&bld.base, builder, type);
- lp_build_context_init(&bld.int_bld, builder, lp_int_type(type));
+ lp_build_context_init(&bld.uint_bld, builder, lp_uint_type(type));
bld.mask = mask;
bld.pos = pos;
bld.inputs = inputs;
bld.outputs = outputs;
bld.consts_ptr = consts_ptr;
bld.sampler = sampler;
- bld.has_indirect_addressing = info->opcode_count[TGSI_OPCODE_ARR] > 0 ||
- info->opcode_count[TGSI_OPCODE_ARL] > 0;
+ bld.info = info;
+ bld.indirect_files = info->indirect_files;
bld.instructions = (struct tgsi_full_instruction *)
MALLOC( LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction) );
bld.max_instructions = LP_MAX_INSTRUCTIONS;
{
/* save expanded instruction */
if (num_instructions == bld.max_instructions) {
- bld.instructions = REALLOC(bld.instructions,
- bld.max_instructions
- * sizeof(struct tgsi_full_instruction),
- (bld.max_instructions + LP_MAX_INSTRUCTIONS)
- * sizeof(struct tgsi_full_instruction));
+ struct tgsi_full_instruction *instructions;
+ instructions = REALLOC(bld.instructions,
+ bld.max_instructions
+ * sizeof(struct tgsi_full_instruction),
+ (bld.max_instructions + LP_MAX_INSTRUCTIONS)
+ * sizeof(struct tgsi_full_instruction));
+ if (!instructions) {
+ break;
+ }
+ bld.instructions = instructions;
bld.max_instructions += LP_MAX_INSTRUCTIONS;
}