nvc0: improve shader support for texturing
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sun, 19 Dec 2010 20:49:32 +0000 (21:49 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sun, 19 Dec 2010 20:49:32 +0000 (21:49 +0100)
Fixed shadow and cube texture fetches, add array texture fetches.

src/gallium/drivers/nvc0/nvc0_pc.c
src/gallium/drivers/nvc0/nvc0_pc.h
src/gallium/drivers/nvc0/nvc0_pc_emit.c
src/gallium/drivers/nvc0/nvc0_pc_print.c
src/gallium/drivers/nvc0/nvc0_pc_regalloc.c
src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c

index cf7b8e347fb70153c07636776a60008a876c35fb..72483f120ed19ffce94e2f29d4766e50fd55b0e6 100644 (file)
@@ -397,7 +397,7 @@ nvc0_generate_code(struct nvc0_translation_info *ti)
    if (ret)
       goto out;
 #if NOUVEAU_DEBUG > 1
-   nv_print_program(pc);
+   nvc0_print_program(pc);
    nv_print_cfgraph(pc, "nvc0_shader_cfgraph.dot", 0);
 #endif
 
index df0314965a33410b47d23697290543fa008a223e..74867f02e722f030aa99caf4ae130f228d73ff48 100644 (file)
@@ -52,7 +52,8 @@
 #define NV_OP_NOP        5
 
 /**
- * BIND forces source operand i into the same register as destination operand i
+ * BIND forces source operand i into the same register as destination operand i,
+ *  and the operands will be assigned consecutive registers (needed for TEX)
  * SELECT forces its multiple source operands and its destination operand into
  *  one and the same register.
  */
 #define NV_OP_SUB_S32     81
 #define NV_OP_MAD_F32     NV_OP_MAD
 #define NV_OP_FSET_F32    82
+#define NV_OP_TXG         83
 
-#define NV_OP_COUNT     83
+#define NV_OP_COUNT     84
 
 /* nv50 files omitted */
 #define NV_FILE_GPR      0
@@ -380,9 +382,11 @@ struct nv_instruction {
    unsigned flat       : 1;
    unsigned patch      : 1;
    unsigned lanes      : 4; /* 3rd byte */
-   unsigned tex_argc   : 3;
+   unsigned tex_dim    : 2;
+   unsigned tex_array  : 1;
+   unsigned tex_cube   : 1;
+   unsigned tex_shadow : 1; /* 4th byte */
    unsigned tex_live   : 1;
-   unsigned tex_cube   : 1; /* 4th byte */
    unsigned tex_mask   : 4;
 
    uint8_t quadop;
index cd1ad03b00bbdd6ad5a9b550f7a00516ac05a441..2f99d5a339fde424b161894c71ea29c5d6328e4b 100644 (file)
@@ -391,23 +391,37 @@ emit_minmax(struct nv_pc *pc, struct nv_instruction *i)
 static void
 emit_tex(struct nv_pc *pc, struct nv_instruction *i)
 {
+   int src1 = i->tex_array + i->tex_dim + i->tex_cube;
+
    pc->emit[0] = 0x00000086;
    pc->emit[1] = 0x80000000;
 
-   if (i->opcode == NV_OP_TXB) pc->emit[1] |= 0x04000000;
-   else
-   if (i->opcode == NV_OP_TXL) pc->emit[1] |= 0x06000000;
+   switch (i->opcode) {
+   case NV_OP_TEX: pc->emit[1] = 0x80000000; break;
+   case NV_OP_TXB: pc->emit[1] = 0x84000000; break;
+   case NV_OP_TXL: pc->emit[1] = 0x86000000; break;
+   case NV_OP_TXF: pc->emit[1] = 0x90000000; break;
+   case NV_OP_TXG: pc->emit[1] = 0xe0000000; break;
+   default:
+      assert(0);
+      break;
+   }
 
-   set_pred(pc, i);
+   if (i->tex_array)
+      pc->emit[1] |= 0x00080000; /* layer index is u16, first value of SRC0 */
+   if (i->tex_shadow)
+      pc->emit[1] |= 0x01000000; /* shadow is part of SRC1, after bias/lod */
 
-   if (1)
-      pc->emit[0] |= 63 << 26; /* explicit derivatives */
+   set_pred(pc, i);
 
    DID(pc, i->def[0], 14);
    SID(pc, i->src[0], 20);
+   SID(pc, i->src[src1], 26); /* may be NULL -> $r63 */
 
    pc->emit[1] |= i->tex_mask << 14;
-   pc->emit[1] |= (i->tex_argc - 1) << 20;
+   pc->emit[1] |= (i->tex_dim - 1) << 20;
+   if (i->tex_cube)
+      pc->emit[1] |= 3 << 20;
 
    assert(i->ext.tex.s < 16);
 
index 9eac5ad900ad722d02805a0f4348c84ac7c4b729..6249f1fd1cdfb2b2cdb28cdbb11bde9d01f721f0 100644 (file)
@@ -371,5 +371,7 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] =
 
    { NV_OP_FSET_F32, "fset", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 2 },
 
+   { NV_OP_TXG, "texgrad", NV_TYPE_F32, 0, 0, 0, 1, 1, 0, 0, 0 },
+
    { NV_OP_UNDEF, "BAD_OP", NV_TYPE_ANY, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
index 6f9d5de19766108029446b26d23e01f09318da40..d24f09a1507f5af94445f8cfbfec6be8674fd275 100644 (file)
@@ -492,6 +492,8 @@ pass_join_values(struct nv_pc_pass *ctx, int iter)
       case NV_OP_TXB:
       case NV_OP_TXL:
       case NV_OP_TXQ:
+         /* on nvc0, TEX src and dst can differ */
+         break;
       case NV_OP_BIND:
          if (iter)
             break;
index d0c82754894f32638a135e09e8de695b113fc2f6..fecfc76fb79e4bb3db7f8ed728056ad71de03c99 100644 (file)
@@ -1156,30 +1156,59 @@ bld_lit(struct bld_context *bld, struct nv_value *dst0[4],
 }
 
 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;
@@ -1215,13 +1244,13 @@ bld_clone(struct bld_context *bld, struct nv_instruction *nvi)
 /* 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);
@@ -1279,33 +1308,68 @@ bld_quadop(struct bld_context *bld, ubyte qop, struct nv_value *src0, int lane,
    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;
 }
@@ -1326,24 +1390,25 @@ bld_tex(struct bld_context *bld, struct nv_value *dst0[4],
 {
    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]);
 
@@ -1355,9 +1420,10 @@ bld_tex(struct bld_context *bld, struct nv_value *dst0[4],
          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 *