}
static INLINE void
-get_tex_dim(const struct tgsi_full_instruction *insn, int *dim, int *arg)
+describe_texture_target(unsigned target, int *dim,
+ int *array, int *cube, int *shadow)
{
- switch (insn->Texture.Texture) {
+ *array = *cube = *shadow = 0;
+
+ switch (target) {
case TGSI_TEXTURE_1D:
- *arg = *dim = 1;
+ *dim = 1;
break;
case TGSI_TEXTURE_SHADOW1D:
- *dim = 1;
- *arg = 2;
+ *dim = *shadow = 1;
break;
case TGSI_TEXTURE_UNKNOWN:
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
- *arg = *dim = 2;
+ *dim = 2;
break;
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
*dim = 2;
- *arg = 3;
+ *shadow = 1;
break;
case TGSI_TEXTURE_3D:
+ *dim = 3;
+ break;
case TGSI_TEXTURE_CUBE:
- *dim = *arg = 3;
+ *dim = 2;
+ *cube = 1;
+ break;
+ /*
+ case TGSI_TEXTURE_CUBE_ARRAY:
+ *dim = 2;
+ *cube = *array = 1;
break;
+ case TGSI_TEXTURE_1D_ARRAY:
+ *dim = *array = 1;
+ break;
+ case TGSI_TEXTURE_2D_ARRAY:
+ *dim = 2;
+ *array = 1;
+ break;
+ case TGSI_TEXTURE_SHADOW1D_ARRAY:
+ *dim = *array = *shadow = 1;
+ break;
+ case TGSI_TEXTURE_SHADOW2D_ARRAY:
+ *dim = 2;
+ *array = *shadow = 1;
+ break;
+ case TGSI_TEXTURE_CUBE_ARRAY:
+ *dim = 2;
+ *array = *cube = 1;
+ break;
+ */
default:
assert(0);
break;
/* NOTE: proj(t0) = (t0 / w) / (tc3 / w) = tc0 / tc2 handled by optimizer */
static void
load_proj_tex_coords(struct bld_context *bld,
- struct nv_value *t[4], int dim, int arg,
+ struct nv_value *t[4], int dim, int shadow,
const struct tgsi_full_instruction *insn)
{
int c;
unsigned mask = (1 << dim) - 1;
- if (arg != dim)
+ if (shadow)
mask |= 4; /* depth comparison value */
t[3] = emit_fetch(bld, insn, 0, 3);
return val;
}
+/* order of TGSI operands: x y z layer shadow lod/bias */
+/* order of native operands: layer x y z | lod/bias shadow */
static struct nv_instruction *
-emit_tex(struct bld_context *bld, uint opcode,
- struct nv_value *dst[4], struct nv_value *t_in[4],
- int argc, int tic, int tsc, int cube)
+emit_tex(struct bld_context *bld, uint opcode, int tic, int tsc,
+ struct nv_value *dst[4], struct nv_value *arg[4],
+ int dim, int array, int cube, int shadow)
{
- struct nv_value *t[4];
- struct nv_instruction *nvi;
+ struct nv_value *src[4];
+ struct nv_instruction *nvi, *bnd;
int c;
+ int s = 0;
+ boolean lodbias = opcode == NV_OP_TXB || opcode == NV_OP_TXL;
+
+ if (array)
+ arg[dim] = bld_cvt(bld, NV_TYPE_U32, NV_TYPE_F32, arg[dim]);
+
+ /* ensure that all inputs reside in a GPR */
+ for (c = 0; c < dim + array + cube + shadow; ++c)
+ (src[c] = bld_insn_1(bld, NV_OP_MOV, arg[c]))->insn->fixed = 1;
+
+ /* bind { layer x y z } and { lod/bias shadow } to adjacent regs */
+
+ bnd = new_instruction(bld->pc, NV_OP_BIND);
+ if (array) {
+ src[s] = new_value(bld->pc, NV_FILE_GPR, 4);
+ bld_def(bnd, s, src[s]);
+ nv_reference(bld->pc, bnd, s++, arg[dim + cube]);
+ }
+ for (c = 0; c < dim + cube; ++c, ++s) {
+ src[s] = bld_def(bnd, s, new_value(bld->pc, NV_FILE_GPR, 4));
+ nv_reference(bld->pc, bnd, s, arg[c]);
+ }
+
+ if (shadow || lodbias) {
+ bnd = new_instruction(bld->pc, NV_OP_BIND);
- /* the inputs to a tex instruction must be separate values */
- for (c = 0; c < argc; ++c) {
- t[c] = bld_insn_1(bld, NV_OP_MOV, t_in[c]);
- t[c]->insn->fixed = 1;
+ if (lodbias) {
+ src[s] = new_value(bld->pc, NV_FILE_GPR, 4);
+ bld_def(bnd, 0, src[s++]);
+ nv_reference(bld->pc, bnd, 0, arg[dim + cube + array + shadow]);
+ }
+ if (shadow) {
+ src[s] = new_value(bld->pc, NV_FILE_GPR, 4);
+ bld_def(bnd, lodbias, src[s++]);
+ nv_reference(bld->pc, bnd, lodbias, arg[dim + cube + array]);
+ }
}
nvi = new_instruction(bld->pc, opcode);
for (c = 0; c < 4; ++c)
dst[c] = bld_def(nvi, c, new_value(bld->pc, NV_FILE_GPR, 4));
- for (c = 0; c < argc; ++c)
- nv_reference(bld->pc, nvi, c, t[c]);
+ for (c = 0; c < s; ++c)
+ nv_reference(bld->pc, nvi, c, src[c]);
nvi->ext.tex.t = tic;
nvi->ext.tex.s = tsc;
nvi->tex_mask = 0xf;
nvi->tex_cube = cube;
+ nvi->tex_dim = dim;
+ nvi->tex_cube = cube;
+ nvi->tex_shadow = shadow;
nvi->tex_live = 0;
- nvi->tex_argc = argc;
return nvi;
}
{
struct nv_value *t[4], *s[3];
uint opcode = translate_opcode(insn->Instruction.Opcode);
- int arg, dim, c;
+ int c, dim, array, cube, shadow;
+ const int lodbias = opcode == NV_OP_TXB || opcode == NV_OP_TXL;
const int tic = insn->Src[1].Register.Index;
const int tsc = tic;
- const int cube = (insn->Texture.Texture == TGSI_TEXTURE_CUBE) ? 1 : 0;
- get_tex_dim(insn, &dim, &arg);
+ describe_texture_target(insn->Texture.Texture, &dim, &array, &cube, &shadow);
+
+ assert(dim + array + shadow + lodbias <= 5);
if (!cube && insn->Instruction.Opcode == TGSI_OPCODE_TXP)
- load_proj_tex_coords(bld, t, dim, arg, insn);
+ load_proj_tex_coords(bld, t, dim, shadow, insn);
else {
- for (c = 0; c < dim; ++c)
+ for (c = 0; c < dim + cube + array; ++c)
t[c] = emit_fetch(bld, insn, 0, c);
- if (arg != dim)
- t[dim] = emit_fetch(bld, insn, 0, 2);
+ if (shadow)
+ t[c] = emit_fetch(bld, insn, 0, MAX2(c, 2));
}
if (cube) {
- assert(dim >= 3);
for (c = 0; c < 3; ++c)
s[c] = bld_insn_1(bld, NV_OP_ABS_F32, t[c]);
t[c] = bld_insn_2(bld, NV_OP_MUL_F32, t[c], s[0]);
}
- if (opcode == NV_OP_TXB || opcode == NV_OP_TXL)
- t[arg++] = emit_fetch(bld, insn, 0, 3);
- emit_tex(bld, opcode, dst0, t, arg, tic, tsc, cube);
+ if (lodbias)
+ t[dim + cube + array + shadow] = emit_fetch(bld, insn, 0, 3);
+
+ emit_tex(bld, opcode, tic, tsc, dst0, t, dim, array, cube, shadow);
}
static INLINE struct nv_value *