nv50/ir: add support for gl_PrimitiveIDIn
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 12 Jan 2014 00:42:04 +0000 (19:42 -0500)
committerMaarten Lankhorst <maarten.lankhorst@canonical.com>
Mon, 27 Jan 2014 15:40:42 +0000 (16:40 +0100)
Note that the primitive id is stored in a[0x18], while usually the
geometry instructions are of the form a[$a1 + 0x4] which gets mapped to
p[] space. We need to avoid the change from a[] to p[] here, so it's
keyed on whether the access is indirect or not.

Note that there's also a use-case for accessing e.g. a[$r1], however
that's not supported for now. (Could be added by checking the register
file of the indirect parameter.)

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target_nv50.cpp

index 173497723c2e4f2ecb72b946b164309040636fd9..c73508c67c11b1623dd5172a46cb453fdf01973f 100644 (file)
@@ -381,7 +381,7 @@ CodeEmitterNV50::setSrcFileBits(const Instruction *i, int enc)
    case 0x00: // rrr
       break;
    case 0x01: // arr/grr
-      if (progType == Program::TYPE_GEOMETRY) {
+      if (progType == Program::TYPE_GEOMETRY && i->src(0).isIndirect(0)) {
          code[0] |= 0x01800000;
          if (enc == NV50_OP_ENC_LONG || enc == NV50_OP_ENC_LONG_ALT)
             code[1] |= 0x00200000;
@@ -412,7 +412,7 @@ CodeEmitterNV50::setSrcFileBits(const Instruction *i, int enc)
       code[1] |= (i->getSrc(1)->reg.fileIndex << 22);
       break;
    case 0x09: // acr/gcr
-      if (progType == Program::TYPE_GEOMETRY) {
+      if (progType == Program::TYPE_GEOMETRY && i->src(0).isIndirect(0)) {
          code[0] |= 0x01800000;
       } else {
          code[0] |= (enc == NV50_OP_ENC_LONG_ALT) ? 0x01000000 : 0x00800000;
@@ -617,7 +617,7 @@ CodeEmitterNV50::emitLOAD(const Instruction *i)
 
    switch (sf) {
    case FILE_SHADER_INPUT:
-      if (progType == Program::TYPE_GEOMETRY)
+      if (progType == Program::TYPE_GEOMETRY && i->src(0).isIndirect(0))
          code[0] = 0x11800001;
       else
          // use 'mov' where we can
index 3c790cfe77ffc1e22086c905a2163a2a9bbf95b9..321410e4d45768ab110c70e5063ae603a5c747dd 100644 (file)
@@ -1434,13 +1434,16 @@ Converter::fetchSrc(tgsi::Instruction::SrcRegister src, int c, Value *ptr)
             return mkOp1v(OP_RDSV, TYPE_F32, getSSA(), mkSysVal(SV_FACE, 0));
          return interpolate(src, c, shiftAddress(ptr));
       } else
-      if (ptr && prog->getType() == Program::TYPE_GEOMETRY) {
+      if (prog->getType() == Program::TYPE_GEOMETRY) {
+         if (!ptr && info->in[idx].sn == TGSI_SEMANTIC_PRIMID)
+            return mkOp1v(OP_RDSV, TYPE_U32, getSSA(), mkSysVal(SV_PRIMITIVE_ID, 0));
          // XXX: This is going to be a problem with scalar arrays, i.e. when
          // we cannot assume that the address is given in units of vec4.
          //
          // nv50 and nvc0 need different things here, so let the lowering
          // passes decide what to do with the address
-         return mkLoadv(TYPE_U32, srcToSym(src, c), ptr);
+         if (ptr)
+            return mkLoadv(TYPE_U32, srcToSym(src, c), ptr);
       }
       return mkLoadv(TYPE_U32, srcToSym(src, c), shiftAddress(ptr));
    case TGSI_FILE_OUTPUT:
index 1dc50c44b966e3e061f56a994dac92be91787d4b..636ef9ee2526473be98dd41f2fba0332ca3d2ef1 100644 (file)
@@ -238,6 +238,9 @@ TargetNV50::getSVAddress(DataFile shaderFile, const Symbol *sym) const
             addr += 4;
       return addr;
    }
+   case SV_PRIMITIVE_ID:
+      return shaderFile == FILE_SHADER_INPUT ? 0x18 :
+         sysvalLocation[sym->reg.data.sv.sv];
    case SV_NCTAID:
       return 0x8 + 2 * sym->reg.data.sv.index;
    case SV_CTAID: