mask->bld = bld;
mask->has_mask = FALSE;
+ mask->ret_in_main = FALSE;
mask->cond_stack_size = 0;
mask->loop_stack_size = 0;
mask->call_stack_size = 0;
} else
mask->exec_mask = mask->cond_mask;
- if (mask->call_stack_size) {
+ if (mask->call_stack_size || mask->ret_in_main) {
mask->exec_mask = LLVMBuildAnd(builder,
mask->exec_mask,
mask->ret_mask,
mask->has_mask = (mask->cond_stack_size > 0 ||
mask->loop_stack_size > 0 ||
- mask->call_stack_size > 0);
+ mask->call_stack_size > 0 ||
+ mask->ret_in_main);
}
static void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
lp_exec_mask_update(mask);
}
+static void lp_exec_break_condition(struct lp_exec_mask *mask,
+ LLVMValueRef cond)
+{
+ LLVMBuilderRef builder = mask->bld->gallivm->builder;
+ LLVMValueRef exec_mask = LLVMBuildNot(builder,
+ mask->exec_mask,
+ "break");
+
+ exec_mask = LLVMBuildAnd(builder, exec_mask, cond, "");
+
+ mask->break_mask = LLVMBuildAnd(builder,
+ mask->break_mask,
+ exec_mask, "break_full");
+
+ lp_exec_mask_update(mask);
+}
+
static void lp_exec_continue(struct lp_exec_mask *mask)
{
LLVMBuilderRef builder = mask->bld->gallivm->builder;
LLVMBuilderRef builder = mask->bld->gallivm->builder;
LLVMValueRef exec_mask;
- if (mask->call_stack_size == 0) {
+ if (mask->cond_stack_size == 0 &&
+ mask->loop_stack_size == 0 &&
+ mask->call_stack_size == 0) {
/* returning from main() */
*pc = -1;
return;
}
+
+ if (mask->call_stack_size == 0) {
+ /*
+ * This requires special handling since we need to ensure
+ * we don't drop the mask even if we have no call stack
+ * (e.g. after a ret in a if clause after the endif)
+ */
+ mask->ret_in_main = TRUE;
+ }
+
exec_mask = LLVMBuildNot(builder,
mask->exec_mask,
"ret");
}
}
+/*
+ * If we have indirect addressing in outputs copy our alloca array
+ * to the outputs slots specified by the caller to make sure
+ * our outputs are delivered consistently via the same interface.
+ */
+static void
+gather_outputs(struct lp_build_tgsi_soa_context * bld)
+{
+ if ((bld->indirect_files & (1 << TGSI_FILE_OUTPUT))) {
+ unsigned index, chan;
+ assert(bld->bld_base.info->num_outputs <=
+ bld->bld_base.info->file_max[TGSI_FILE_OUTPUT] + 1);
+ for (index = 0; index < bld->bld_base.info->num_outputs; ++index) {
+ for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
+ bld->outputs[index][chan] = lp_get_output_ptr(bld, index, chan);
+ }
+ }
+ }
+}
+
/**
* Gather vector.
* XXX the lp_build_gather() function should be capable of doing this
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)
+ const struct tgsi_ind_register *indirect_reg)
{
LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
struct lp_build_context *uint_bld = &bld->bld_base.uint_bld;
/* always use X component of address register */
- unsigned swizzle = indirect_reg->SwizzleX;
+ unsigned swizzle = indirect_reg->Swizzle;
LLVMValueRef base;
LLVMValueRef rel;
LLVMValueRef max_index;
LLVMBuilderRef builder = gallivm->builder;
struct lp_build_context *uint_bld = &bld_base->uint_bld;
LLVMValueRef indirect_index = NULL;
- struct lp_build_context *bld_fetch = stype_to_fetch(bld_base, stype);
unsigned dimension = 0;
LLVMValueRef dimension_index;
LLVMValueRef consts_ptr;
+ LLVMValueRef res;
/* XXX: Handle fetching xyzw components as a vector */
assert(swizzle != ~0);
index_vec = lp_build_add(uint_bld, index_vec, swizzle_vec);
/* Gather values from the constant buffer */
- return build_gather(bld_fetch, consts_ptr, index_vec);
+ res = build_gather(&bld_base->base, consts_ptr, index_vec);
}
else {
LLVMValueRef index; /* index into the const buffer */
index = lp_build_const_int32(gallivm, reg->Register.Index*4 + swizzle);
scalar_ptr = LLVMBuildGEP(builder, consts_ptr,
- &index, 1, "");
-
- if (stype != TGSI_TYPE_FLOAT && stype != TGSI_TYPE_UNTYPED) {
- LLVMTypeRef ivtype = LLVMPointerType(LLVMInt32TypeInContext(gallivm->context), 0);
- LLVMValueRef temp_ptr;
- temp_ptr = LLVMBuildBitCast(builder, scalar_ptr, ivtype, "");
- scalar = LLVMBuildLoad(builder, temp_ptr, "");
- } else
- scalar = LLVMBuildLoad(builder, scalar_ptr, "");
+ &index, 1, "");
+ scalar = LLVMBuildLoad(builder, scalar_ptr, "");
+ res = lp_build_broadcast_scalar(&bld_base->base, scalar);
+ }
- return lp_build_broadcast_scalar(bld_fetch, scalar);
+ if (stype == TGSI_TYPE_SIGNED || stype == TGSI_TYPE_UNSIGNED) {
+ struct lp_build_context *bld_fetch = stype_to_fetch(bld_base, stype);
+ res = LLVMBuildBitCast(builder, res, bld_fetch->vec_type, "");
}
+ return res;
}
static LLVMValueRef
return res;
}
+
+static LLVMValueRef
+emit_fetch_gs_input(
+ struct lp_build_tgsi_context * bld_base,
+ const struct tgsi_full_src_register * reg,
+ enum tgsi_opcode_type stype,
+ unsigned swizzle)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef attrib_index = NULL;
+ LLVMValueRef vertex_index = NULL;
+ LLVMValueRef swizzle_index = lp_build_const_int32(gallivm, swizzle);
+ LLVMValueRef res;
+
+ if (reg->Register.Indirect) {
+ attrib_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Register.Index,
+ ®->Indirect);
+ } else {
+ attrib_index = lp_build_const_int32(gallivm, reg->Register.Index);
+ }
+
+ if (reg->Dimension.Indirect) {
+ vertex_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Dimension.Index,
+ ®->DimIndirect);
+ } else {
+ vertex_index = lp_build_const_int32(gallivm, reg->Dimension.Index);
+ }
+
+
+ res = bld->gs_iface->fetch_input(bld->gs_iface, bld_base,
+ vertex_index, attrib_index,
+ swizzle_index);
+
+ assert(res);
+
+ if (stype == TGSI_TYPE_UNSIGNED) {
+ res = LLVMBuildBitCast(builder, res, bld_base->uint_bld.vec_type, "");
+ } else if (stype == TGSI_TYPE_SIGNED) {
+ res = LLVMBuildBitCast(builder, res, bld_base->int_bld.vec_type, "");
+ }
+
+ return res;
+}
+
static LLVMValueRef
emit_fetch_temporary(
struct lp_build_tgsi_context * bld_base,
}
else {
LLVMValueRef temp_ptr;
- if (stype != TGSI_TYPE_FLOAT && stype != TGSI_TYPE_UNTYPED) {
- LLVMTypeRef itype = LLVMPointerType(bld->bld_base.int_bld.vec_type, 0);
- LLVMValueRef tint_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index,
- swizzle);
- temp_ptr = LLVMBuildBitCast(builder, tint_ptr, itype, "");
- } else
- temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, swizzle);
+ temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, swizzle);
res = LLVMBuildLoad(builder, temp_ptr, "");
- if (!res)
- return bld->bld_base.base.undef;
+ }
+
+ if (stype == TGSI_TYPE_SIGNED || stype == TGSI_TYPE_UNSIGNED) {
+ struct lp_build_context *bld_fetch = stype_to_fetch(bld_base, stype);
+ res = LLVMBuildBitCast(builder, res, bld_fetch->vec_type, "");
}
return res;
atype = TGSI_TYPE_UNSIGNED;
break;
+ case TGSI_SEMANTIC_PRIMID:
+ res = bld->system_values.prim_id;
+ atype = TGSI_TYPE_UNSIGNED;
+ break;
+
default:
assert(!"unexpected semantic in emit_fetch_system_value");
res = bld_base->base.zero;
enum lp_build_tex_modifier modifier,
LLVMValueRef *texel)
{
- LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
- struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
unsigned unit;
LLVMValueRef lod_bias, explicit_lod;
LLVMValueRef oow = NULL;
LLVMValueRef coords[4];
LLVMValueRef offsets[3] = { NULL };
struct lp_derivatives derivs;
- unsigned num_coords;
- unsigned dims;
+ struct lp_derivatives *deriv_ptr = NULL;
+ unsigned num_coords, num_derivs, num_offsets;
unsigned i;
if (!bld->sampler) {
return;
}
- derivs.ddx_ddy[0] = bld->bld_base.base.undef;
- derivs.ddx_ddy[1] = bld->bld_base.base.undef;
-
switch (inst->Texture.Texture) {
case TGSI_TEXTURE_1D:
num_coords = 1;
- dims = 1;
+ num_offsets = 1;
+ num_derivs = 1;
break;
case TGSI_TEXTURE_1D_ARRAY:
num_coords = 2;
- dims = 1;
+ num_offsets = 1;
+ num_derivs = 1;
break;
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
num_coords = 2;
- dims = 2;
+ num_offsets = 2;
+ num_derivs = 2;
break;
case TGSI_TEXTURE_SHADOW1D:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
num_coords = 3;
- dims = 1;
+ num_offsets = 1;
+ num_derivs = 1;
break;
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_2D_ARRAY:
+ num_coords = 3;
+ num_offsets = 2;
+ num_derivs = 2;
+ break;
case TGSI_TEXTURE_CUBE:
num_coords = 3;
- dims = 2;
+ num_offsets = 2;
+ num_derivs = 3;
break;
case TGSI_TEXTURE_3D:
num_coords = 3;
- dims = 3;
+ num_offsets = 3;
+ num_derivs = 3;
break;
case TGSI_TEXTURE_SHADOW2D_ARRAY:
+ num_coords = 4;
+ num_offsets = 2;
+ num_derivs = 2;
+ break;
case TGSI_TEXTURE_SHADOWCUBE:
num_coords = 4;
- dims = 2;
+ num_offsets = 2;
+ num_derivs = 3;
break;
default:
assert(0);
}
if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV) {
- LLVMValueRef i32undef = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
- LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
- LLVMValueRef ddxdyonec[3];
- unsigned length = bld->bld_base.base.type.length;
- unsigned num_quads = length / 4;
unsigned dim;
- unsigned quad;
-
- for (dim = 0; dim < dims; ++dim) {
- LLVMValueRef srcx = lp_build_emit_fetch( &bld->bld_base, inst, 1, dim );
- LLVMValueRef srcy = lp_build_emit_fetch( &bld->bld_base, inst, 2, dim );
- for (quad = 0; quad < num_quads; ++quad) {
- unsigned s1 = 4*quad;
- unsigned s2 = 4*quad + length;
- shuffles[4*quad + 0] = lp_build_const_int32(gallivm, s1);
- shuffles[4*quad + 1] = lp_build_const_int32(gallivm, s2);
- shuffles[4*quad + 2] = i32undef;
- shuffles[4*quad + 3] = i32undef;
- }
- ddxdyonec[dim] = LLVMBuildShuffleVector(builder, srcx, srcy,
- LLVMConstVector(shuffles, length), "");
- }
- if (dims == 1) {
- derivs.ddx_ddy[0] = ddxdyonec[0];
- }
- else if (dims >= 2) {
- for (quad = 0; quad < num_quads; ++quad) {
- unsigned s1 = 4*quad;
- unsigned s2 = 4*quad + length;
- shuffles[4*quad + 0] = lp_build_const_int32(gallivm, s1);
- shuffles[4*quad + 1] = lp_build_const_int32(gallivm, s1 + 1);
- shuffles[4*quad + 2] = lp_build_const_int32(gallivm, s2);
- shuffles[4*quad + 3] = lp_build_const_int32(gallivm, s2 + 1);
- }
- derivs.ddx_ddy[0] = LLVMBuildShuffleVector(builder, ddxdyonec[0], ddxdyonec[1],
- LLVMConstVector(shuffles, length), "");
- if (dims == 3) {
- derivs.ddx_ddy[1] = ddxdyonec[2];
- }
+ for (dim = 0; dim < num_derivs; ++dim) {
+ derivs.ddx[dim] = lp_build_emit_fetch( &bld->bld_base, inst, 1, dim );
+ derivs.ddy[dim] = lp_build_emit_fetch( &bld->bld_base, inst, 2, dim );
}
+ deriv_ptr = &derivs;
unit = inst->Src[3].Register.Index;
- } else {
- if (dims == 1) {
- derivs.ddx_ddy[0] = lp_build_packed_ddx_ddy_onecoord(&bld->bld_base.base, coords[0]);
- }
- else if (dims >= 2) {
- derivs.ddx_ddy[0] = lp_build_packed_ddx_ddy_twocoord(&bld->bld_base.base,
- coords[0], coords[1]);
- if (dims == 3) {
- derivs.ddx_ddy[1] = lp_build_packed_ddx_ddy_onecoord(&bld->bld_base.base, coords[2]);
- }
- }
+ } else {
unit = inst->Src[1].Register.Index;
}
/* some advanced gather instructions (txgo) would require 4 offsets */
if (inst->Texture.NumOffsets == 1) {
unsigned dim;
- for (dim = 0; dim < dims; dim++) {
+ for (dim = 0; dim < num_offsets; dim++) {
offsets[dim] = lp_build_emit_fetch_texoffset(&bld->bld_base, inst, 0, dim );
}
}
unit, unit,
coords,
offsets,
- &derivs,
+ deriv_ptr,
lod_bias, explicit_lod,
texel);
}
emit_sample(struct lp_build_tgsi_soa_context *bld,
const struct tgsi_full_instruction *inst,
enum lp_build_tex_modifier modifier,
+ boolean compare,
LLVMValueRef *texel)
{
- LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
unsigned texture_unit, sampler_unit;
LLVMValueRef lod_bias, explicit_lod;
LLVMValueRef coords[4];
LLVMValueRef offsets[3] = { NULL };
struct lp_derivatives derivs;
- unsigned num_coords, dims;
+ struct lp_derivatives *deriv_ptr = NULL;
+ unsigned num_coords, num_offsets, num_derivs;
unsigned i;
- boolean compare = FALSE;
if (!bld->sampler) {
_debug_printf("warning: found texture instruction but no sampler generator supplied\n");
return;
}
- derivs.ddx_ddy[0] = bld->bld_base.base.undef;
- derivs.ddx_ddy[1] = bld->bld_base.base.undef;
+ /*
+ * unlike old-style tex opcodes the texture/sampler indices
+ * always come from src1 and src2 respectively.
+ */
+ texture_unit = inst->Src[1].Register.Index;
+ sampler_unit = inst->Src[2].Register.Index;
- switch (inst->Texture.Texture) {
- case TGSI_TEXTURE_SHADOW1D:
- compare = TRUE;
- /* Fallthrough */
+ /*
+ * Note inst->Texture.Texture will contain the number of offsets,
+ * however the target information is NOT there and comes from the
+ * declared sampler views instead.
+ */
+ switch (bld->sv[texture_unit].Resource) {
case TGSI_TEXTURE_1D:
num_coords = 1;
- dims = 1;
+ num_offsets = 1;
+ num_derivs = 1;
break;
- case TGSI_TEXTURE_SHADOW1D_ARRAY:
- compare = TRUE;
- /* Fallthrough */
case TGSI_TEXTURE_1D_ARRAY:
num_coords = 2;
- dims = 1;
+ num_offsets = 1;
+ num_derivs = 1;
break;
- case TGSI_TEXTURE_SHADOW2D:
- case TGSI_TEXTURE_SHADOWRECT:
- compare = TRUE;
- /* Fallthrough */
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
num_coords = 2;
- dims = 2;
+ num_offsets = 2;
+ num_derivs = 2;
break;
- case TGSI_TEXTURE_SHADOW2D_ARRAY:
- case TGSI_TEXTURE_SHADOWCUBE:
- compare = TRUE;
- /* Fallthrough */
case TGSI_TEXTURE_2D_ARRAY:
+ num_coords = 3;
+ num_offsets = 2;
+ num_derivs = 2;
+ break;
case TGSI_TEXTURE_CUBE:
num_coords = 3;
- dims = 2;
+ num_offsets = 2;
+ num_derivs = 3;
break;
case TGSI_TEXTURE_3D:
num_coords = 3;
- dims = 3;
+ num_offsets = 3;
+ num_derivs = 3;
break;
- case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
- compare = TRUE;
- /* Fallthrough */
case TGSI_TEXTURE_CUBE_ARRAY:
num_coords = 4;
- dims = 3;
+ num_offsets = 2;
+ num_derivs = 3;
break;
default:
assert(0);
explicit_lod = NULL;
}
else if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_LOD) {
- /* lod bias comes from src 3.r but explicit lod from 0.a */
lod_bias = NULL;
- explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 3 );
+ explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 3, 0 );
}
else if (modifier == LP_BLD_TEX_MODIFIER_LOD_ZERO) {
lod_bias = NULL;
}
if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV) {
- LLVMValueRef i32undef = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
- LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
- LLVMValueRef ddxdyonec[3];
- unsigned length = bld->bld_base.base.type.length;
- unsigned num_quads = length / 4;
unsigned dim;
- unsigned quad;
-
- for (dim = 0; dim < dims; ++dim) {
- LLVMValueRef srcx = lp_build_emit_fetch( &bld->bld_base, inst, 3, dim );
- LLVMValueRef srcy = lp_build_emit_fetch( &bld->bld_base, inst, 4, dim );
- for (quad = 0; quad < num_quads; ++quad) {
- unsigned s1 = 4*quad;
- unsigned s2 = 4*quad + length;
- shuffles[4*quad + 0] = lp_build_const_int32(gallivm, s1);
- shuffles[4*quad + 1] = lp_build_const_int32(gallivm, s2);
- shuffles[4*quad + 2] = i32undef;
- shuffles[4*quad + 3] = i32undef;
- }
- ddxdyonec[dim] = LLVMBuildShuffleVector(builder, srcx, srcy,
- LLVMConstVector(shuffles, length), "");
- }
- if (dims == 1) {
- derivs.ddx_ddy[0] = ddxdyonec[0];
- }
- else if (dims >= 2) {
- for (quad = 0; quad < num_quads; ++quad) {
- unsigned s1 = 4*quad;
- unsigned s2 = 4*quad + length;
- shuffles[4*quad + 0] = lp_build_const_int32(gallivm, s1);
- shuffles[4*quad + 1] = lp_build_const_int32(gallivm, s1 + 1);
- shuffles[4*quad + 2] = lp_build_const_int32(gallivm, s2);
- shuffles[4*quad + 3] = lp_build_const_int32(gallivm, s2 + 1);
- }
- derivs.ddx_ddy[0] = LLVMBuildShuffleVector(builder, ddxdyonec[0], ddxdyonec[1],
- LLVMConstVector(shuffles, length), "");
- if (dims == 3) {
- derivs.ddx_ddy[1] = ddxdyonec[2];
- }
- }
- } else {
- if (dims == 1) {
- derivs.ddx_ddy[0] = lp_build_packed_ddx_ddy_onecoord(&bld->bld_base.base, coords[0]);
- }
- else if (dims >= 2) {
- derivs.ddx_ddy[0] = lp_build_packed_ddx_ddy_twocoord(&bld->bld_base.base,
- coords[0], coords[1]);
- if (dims == 3) {
- derivs.ddx_ddy[1] = lp_build_packed_ddx_ddy_onecoord(&bld->bld_base.base, coords[2]);
- }
+ for (dim = 0; dim < num_derivs; ++dim) {
+ derivs.ddx[dim] = lp_build_emit_fetch( &bld->bld_base, inst, 3, dim );
+ derivs.ddy[dim] = lp_build_emit_fetch( &bld->bld_base, inst, 4, dim );
}
+ deriv_ptr = &derivs;
}
/* some advanced gather instructions (txgo) would require 4 offsets */
if (inst->Texture.NumOffsets == 1) {
unsigned dim;
- for (dim = 0; dim < dims; dim++) {
+ for (dim = 0; dim < num_offsets; dim++) {
offsets[dim] = lp_build_emit_fetch_texoffset(&bld->bld_base, inst, 0, dim );
}
}
texture_unit, sampler_unit,
coords,
offsets,
- &derivs,
+ deriv_ptr,
lod_bias, explicit_lod,
texel);
}
static void
-emit_txf( struct lp_build_tgsi_soa_context *bld,
- const struct tgsi_full_instruction *inst,
- LLVMValueRef *texel)
+emit_fetch_texels( struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_full_instruction *inst,
+ LLVMValueRef *texel,
+ boolean is_samplei)
{
- unsigned unit;
+ unsigned unit, target;
LLVMValueRef coord_undef = LLVMGetUndef(bld->bld_base.base.int_vec_type);
LLVMValueRef explicit_lod = NULL;
LLVMValueRef coords[3];
LLVMValueRef offsets[3] = { NULL };
- struct lp_derivatives derivs;
unsigned num_coords;
unsigned dims;
unsigned i;
return;
}
- derivs.ddx_ddy[0] = coord_undef;
- derivs.ddx_ddy[1] = coord_undef;
+ unit = inst->Src[1].Register.Index;
- switch (inst->Texture.Texture) {
+ if (is_samplei) {
+ target = bld->sv[unit].Resource;
+ }
+ else {
+ target = inst->Texture.Texture;
+ }
+
+ switch (target) {
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_BUFFER:
num_coords = 1;
}
/* always have lod except for buffers ? */
- if (inst->Texture.Texture != TGSI_TEXTURE_BUFFER) {
+ if (target != TGSI_TEXTURE_BUFFER) {
explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 3 );
}
coords[i] = coord_undef;
}
- unit = inst->Src[1].Register.Index;
-
if (inst->Texture.NumOffsets == 1) {
unsigned dim;
for (dim = 0; dim < dims; dim++) {
unit, unit,
coords,
offsets,
- &derivs,
+ NULL,
NULL, explicit_lod,
texel);
}
LLVMValueRef explicit_lod;
unsigned has_lod;
unsigned i;
+ unsigned unit = inst->Src[1].Register.Index;
+ unsigned target;
- switch (inst->Texture.Texture) {
+ if (is_sviewinfo) {
+ target = bld->sv[unit].Resource;
+ }
+ else {
+ target = inst->Texture.Texture;
+ }
+ switch (target) {
case TGSI_TEXTURE_BUFFER:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_SHADOWRECT:
bld->sampler->emit_size_query(bld->sampler,
bld->bld_base.base.gallivm,
bld->bld_base.int_bld.type,
- inst->Src[1].Register.Index,
+ unit,
is_sviewinfo,
explicit_lod,
sizes_out);
break;
case TGSI_FILE_ADDRESS:
- /* ADDR registers are the only allocated with an integer LLVM IR type,
+ /* ADDR registers are only allocated with an integer LLVM IR type,
* as they are guaranteed to always have integers.
* XXX: Not sure if this exception is worthwhile (or the whole idea of
* an ADDR register for that matter).
"predicate");
break;
+ case TGSI_FILE_SAMPLER_VIEW:
+ /*
+ * The target stored here MUST match whatever there actually
+ * is in the set sampler views (what about return type?).
+ */
+ assert(idx < PIPE_MAX_SHADER_SAMPLER_VIEWS);
+ bld->sv[idx] = decl->SamplerView;
+ break;
+
default:
/* don't need to declare other vars */
break;
{
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
- emit_txf(bld, emit_data->inst, emit_data->output);
+ emit_fetch_texels(bld, emit_data->inst, emit_data->output, FALSE);
+}
+
+static void
+sample_i_emit(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+
+ emit_fetch_texels(bld, emit_data->inst, emit_data->output, TRUE);
}
static void
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_NONE,
- emit_data->output);
+ FALSE, emit_data->output);
}
static void
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_LOD_BIAS,
- emit_data->output);
+ FALSE, emit_data->output);
}
static void
struct lp_build_emit_data * emit_data)
{
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
- /*
- * note that we can ignore this is a comparison instruction here
- * since it should be encoded elsewhere (SHADOW target).
- */
+
emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_NONE,
- emit_data->output);
+ TRUE, emit_data->output);
}
static void
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_LOD_ZERO,
- emit_data->output);
+ TRUE, emit_data->output);
}
static void
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV,
- emit_data->output);
+ FALSE, emit_data->output);
}
static void
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_EXPLICIT_LOD,
- emit_data->output);
+ FALSE, emit_data->output);
}
static void
emit_size_query(bld, emit_data->inst, emit_data->output, TRUE);
}
+static LLVMValueRef
+mask_to_one_vec(struct lp_build_tgsi_context *bld_base)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+ LLVMValueRef one_vec = bld_base->int_bld.one;
+ struct lp_exec_mask *exec_mask = &bld->exec_mask;
+
+ if (exec_mask->has_mask) {
+ one_vec = LLVMBuildAnd(builder, one_vec, exec_mask->exec_mask, "");
+ }
+ one_vec = LLVMBuildAnd(builder, one_vec,
+ lp_build_mask_value(bld->mask), "");
+ return one_vec;
+}
+
+static void
+emit_vertex(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+
+ if (bld->gs_iface->emit_vertex) {
+ LLVMValueRef masked_ones = mask_to_one_vec(bld_base);
+ gather_outputs(bld);
+ bld->gs_iface->emit_vertex(bld->gs_iface, &bld->bld_base,
+ bld->outputs,
+ bld->total_emitted_vertices_vec);
+ bld->emitted_vertices_vec =
+ LLVMBuildAdd(builder, bld->emitted_vertices_vec, masked_ones, "");
+ bld->total_emitted_vertices_vec =
+ LLVMBuildAdd(builder, bld->total_emitted_vertices_vec, masked_ones, "");
+ bld->pending_end_primitive = TRUE;
+ }
+}
+
+
+static void
+end_primitive(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+
+ if (bld->gs_iface->end_primitive) {
+ LLVMValueRef masked_ones = mask_to_one_vec(bld_base);
+ bld->gs_iface->end_primitive(bld->gs_iface, &bld->bld_base,
+ bld->emitted_vertices_vec,
+ bld->emitted_prims_vec);
+ bld->emitted_prims_vec =
+ LLVMBuildAdd(builder, bld->emitted_prims_vec, masked_ones, "");
+ bld->emitted_vertices_vec = bld_base->uint_bld.zero;
+ bld->pending_end_primitive = FALSE;
+ }
+}
+
static void
cal_emit(
const struct lp_build_tgsi_action * action,
lp_exec_break(&bld->exec_mask);
}
+static void
+breakc_emit(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ LLVMValueRef tmp;
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+
+ tmp = lp_build_cmp(&bld_base->base, PIPE_FUNC_NOTEQUAL,
+ emit_data->args[0], bld->bld_base.base.zero);
+
+ lp_exec_break_condition(&bld->exec_mask, tmp);
+}
+
static void
if_emit(
const struct lp_build_tgsi_action * action,
/* If we have indirect addressing in inputs we need to copy them into
* our alloca array to be able to iterate over them */
- if (bld->indirect_files & (1 << TGSI_FILE_INPUT)) {
+ if (bld->indirect_files & (1 << TGSI_FILE_INPUT) && !bld->gs_iface) {
unsigned index, chan;
LLVMTypeRef vec_type = bld_base->base.vec_type;
LLVMValueRef array_size = lp_build_const_int32(gallivm,
}
}
}
+
+ if (bld->gs_iface) {
+ struct lp_build_context *uint_bld = &bld->bld_base.uint_bld;
+ bld->emitted_prims_vec = uint_bld->zero;
+ bld->emitted_vertices_vec = uint_bld->zero;
+ bld->total_emitted_vertices_vec = uint_bld->zero;
+ }
}
static void emit_epilogue(struct lp_build_tgsi_context * bld_base)
}
/* If we have indirect addressing in outputs we need to copy our alloca array
- * to the outputs slots specified by the called */
- if (bld->indirect_files & (1 << TGSI_FILE_OUTPUT)) {
- unsigned index, chan;
- assert(bld_base->info->num_outputs <=
- bld_base->info->file_max[TGSI_FILE_OUTPUT] + 1);
- for (index = 0; index < bld_base->info->num_outputs; ++index) {
- for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
- bld->outputs[index][chan] = lp_get_output_ptr(bld, index, chan);
- }
+ * to the outputs slots specified by the caller */
+ if (bld->gs_iface) {
+ /* flush the accumulated vertices as a primitive */
+ if (bld->pending_end_primitive) {
+ end_primitive(NULL, bld_base, NULL);
+ bld->pending_end_primitive = FALSE;
}
+
+ bld->gs_iface->gs_epilogue(bld->gs_iface,
+ &bld->bld_base,
+ bld->total_emitted_vertices_vec,
+ bld->emitted_prims_vec);
+ } else {
+ gather_outputs(bld);
}
}
const LLVMValueRef (*inputs)[TGSI_NUM_CHANNELS],
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
struct lp_build_sampler_soa *sampler,
- const struct tgsi_shader_info *info)
+ const struct tgsi_shader_info *info,
+ const struct lp_build_tgsi_gs_iface *gs_iface)
{
struct lp_build_tgsi_soa_context bld;
bld.bld_base.op_actions[TGSI_OPCODE_BGNLOOP].emit = bgnloop_emit;
bld.bld_base.op_actions[TGSI_OPCODE_BGNSUB].emit = bgnsub_emit;
bld.bld_base.op_actions[TGSI_OPCODE_BRK].emit = brk_emit;
+ bld.bld_base.op_actions[TGSI_OPCODE_BREAKC].emit = breakc_emit;
bld.bld_base.op_actions[TGSI_OPCODE_CAL].emit = cal_emit;
bld.bld_base.op_actions[TGSI_OPCODE_CONT].emit = cont_emit;
bld.bld_base.op_actions[TGSI_OPCODE_DDX].emit = ddx_emit;
bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_C].emit = sample_c_emit;
bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_C_LZ].emit = sample_c_lz_emit;
bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_D].emit = sample_d_emit;
- bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_I].emit = txf_emit;
+ bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_I].emit = sample_i_emit;
bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_L].emit = sample_l_emit;
bld.bld_base.op_actions[TGSI_OPCODE_SVIEWINFO].emit = sviewinfo_emit;
+ if (gs_iface) {
+ /* inputs are always indirect with gs */
+ bld.indirect_files |= (1 << TGSI_FILE_INPUT);
+ bld.gs_iface = gs_iface;
+ bld.pending_end_primitive = FALSE;
+ bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_gs_input;
+ bld.bld_base.op_actions[TGSI_OPCODE_EMIT].emit = emit_vertex;
+ bld.bld_base.op_actions[TGSI_OPCODE_ENDPRIM].emit = end_primitive;
+ }
+
lp_exec_mask_init(&bld.exec_mask, &bld.bld_base.base);
bld.system_values = *system_values;