nv50/ir,nvc0: make ClipDistance and ClipVertex work
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 7 Jan 2012 16:26:58 +0000 (17:26 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Mon, 9 Jan 2012 23:37:19 +0000 (00:37 +0100)
src/gallium/drivers/nv50/codegen/nv50_ir_driver.h
src/gallium/drivers/nv50/codegen/nv50_ir_from_sm4.cpp
src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nvc0/nvc0_program.c
src/gallium/drivers/nvc0/nvc0_program.h
src/gallium/drivers/nvc0/nvc0_state_validate.c

index a6a5e93f58c521aa77b64d26a39db37d53c8bdb0..4baef5373709082bba832783ffd39dc6b8013970 100644 (file)
@@ -152,8 +152,9 @@ struct nv50_ir_prog_info
 
    struct {
       uint8_t clipDistance;      /* index of first clip distance output */
-      uint8_t clipDistanceCount;
+      uint8_t clipDistanceMask;  /* mask of clip distances defined */
       uint8_t cullDistanceMask;  /* clip distance mode (1 bit per output) */
+      int8_t genUserClip;        /* request user clip planes for ClipVertex */
       uint8_t pointSize;         /* output index for PointSize */
       uint8_t edgeFlagIn;
       uint8_t edgeFlagOut;
index 7ed00e336c6e40497c1a918e2a62b1b2655c194c..11720d2db67693f492903f54bf0a5cdb19e82710 100644 (file)
@@ -899,10 +899,10 @@ Converter::inspectDeclaration(const sm4_dcl& dcl)
          assert(prog->getType() != Program::TYPE_FRAGMENT);
          break;
       case SM4_SV_CULL_DISTANCE: // XXX: order ?
-         info.io.cullDistanceMask |= 1 << info.io.clipDistanceCount;
-        // fall through
+         info.io.cullDistanceMask |= 1 << info.io.clipDistanceMask;
+      // fall through
       case SM4_SV_CLIP_DISTANCE:
-         info.io.clipDistanceCount++;
+         info.io.clipDistanceMask++; // abuse as count
          break;
       default:
          break;
@@ -2257,6 +2257,9 @@ Converter::run()
    for (unsigned int pos = 0; pos < sm4.dcls.size(); ++pos)
       handleDeclaration(*sm4.dcls[pos]);
 
+   info.io.genUserClip = -1; // no UCPs permitted with SM4 shaders
+   info.io.clipDistanceMask = (1 << info.io.clipDistanceMask) - 1;
+
    info.assignSlots(&info);
 
    if (sm4.dcls.size() == 0 && sm4.insns.size() == 0)
index 6cb61b87766058ee8fb445b67b2f059e033e81ef..050f2516b99bf591c4e44942ea9970d7aaec1c86 100644 (file)
@@ -593,6 +593,8 @@ public:
 
    bool mainTempsInLMem;
 
+   int clipVertexOutput;
+
    uint8_t *resourceTargets; // TGSI_TEXTURE_*
    unsigned resourceCount;
 
@@ -651,6 +653,8 @@ bool Source::scanSource()
    if (!insns)
       return false;
 
+   clipVertexOutput = -1;
+
    resourceCount = scan.file_max[TGSI_FILE_RESOURCE] + 1;
    resourceTargets = new uint8_t[resourceCount];
 
@@ -707,6 +711,9 @@ bool Source::scanSource()
    if (mainTempsInLMem)
       info->bin.tlsSpace += (scan.file_max[TGSI_FILE_TEMPORARY] + 1) * 16;
 
+   if (info->io.genUserClip > 0)
+      info->io.clipDistanceMask = (1 << info->io.genUserClip) - 1;
+
    return info->assignSlots(info) == 0;
 }
 
@@ -734,6 +741,9 @@ void Source::scanProperty(const struct tgsi_full_property *prop)
    case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
       // we don't care
       break;
+   case TGSI_PROPERTY_VS_PROHIBIT_UCPS:
+      info->io.genUserClip = -1;
+      break;
    default:
       INFO("unhandled TGSI property %d\n", prop->Property.PropertyName);
       break;
@@ -820,6 +830,9 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl)
          case TGSI_SEMANTIC_POSITION:
             if (info->type == PIPE_SHADER_FRAGMENT)
                info->io.fragDepth = i;
+            else
+            if (clipVertexOutput < 0)
+               clipVertexOutput = i;
             break;
          case TGSI_SEMANTIC_COLOR:
             if (info->type == PIPE_SHADER_FRAGMENT)
@@ -828,6 +841,14 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl)
          case TGSI_SEMANTIC_EDGEFLAG:
             info->io.edgeFlagOut = i;
             break;
+         case TGSI_SEMANTIC_CLIPVERTEX:
+            clipVertexOutput = i;
+            break;
+         case TGSI_SEMANTIC_CLIPDIST:
+            info->io.clipDistanceMask |=
+               decl->Declaration.UsageMask << (si * 4);
+            info->io.genUserClip = -1;
+            break;
          default:
             break;
          }
@@ -1324,9 +1345,9 @@ Converter::storeDst(int d, int c, Value *val)
    Value *ptr = dst.isIndirect(0) ?
       fetchSrc(dst.getIndirect(0), 0, NULL) : NULL;
 
-   if (info->io.clipDistanceCount &&
+   if (info->io.genUserClip > 0 &&
        dst.getFile() == TGSI_FILE_OUTPUT &&
-       info->out[dst.getIndex(0)].sn == TGSI_SEMANTIC_POSITION) {
+       !dst.isIndirect(0) && dst.getIndex(0) == code->clipVertexOutput) {
       mkMov(clipVtx[c], val);
       val = clipVtx[c];
    }
@@ -2136,7 +2157,7 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
       setPosition(epilogue, true);
       if (prog->getType() == Program::TYPE_FRAGMENT)
          exportOutputs();
-      if (info->io.clipDistanceCount)
+      if (info->io.genUserClip > 0)
          handleUserClipPlanes();
       mkOp(OP_EXIT, TYPE_NONE, NULL)->terminator = 1;
    }
@@ -2173,7 +2194,7 @@ Converter::handleUserClipPlanes()
    int i, c;
 
    for (c = 0; c < 4; ++c) {
-      for (i = 0; i < info->io.clipDistanceCount; ++i) {
+      for (i = 0; i < info->io.genUserClip; ++i) {
          Value *ucp;
          ucp = mkLoad(TYPE_F32, mkSymbol(FILE_MEMORY_CONST, 15, TYPE_F32,
                                          i * 16 + c * 4), NULL);
@@ -2184,7 +2205,7 @@ Converter::handleUserClipPlanes()
       }
    }
 
-   for (i = 0; i < info->io.clipDistanceCount; ++i)
+   for (i = 0; i < info->io.genUserClip; ++i)
       mkOp2(OP_WRSV, TYPE_F32, NULL, mkSysVal(SV_CLIP_DISTANCE, i), res[i]);
 }
 
@@ -2275,7 +2296,7 @@ Converter::run()
    entryBBs.push(entry);
    leaveBBs.push(leave);
 
-   if (info->io.clipDistanceCount) {
+   if (info->io.genUserClip > 0) {
       for (int c = 0; c < 4; ++c)
          clipVtx[c] = getScratch();
    }
index 605bca5e6ba7328c3c596fbcd6cd0b1591f997de..5eee895fea70d2c7facbce14ed18f08357f8b931 100644 (file)
@@ -59,7 +59,9 @@ nvc0_shader_input_address(unsigned sn, unsigned si, unsigned ubase)
    case TGSI_SEMANTIC_FOG:          return 0x270;
    case TGSI_SEMANTIC_COLOR:        return 0x280 + si * 0x10;
    case TGSI_SEMANTIC_BCOLOR:       return 0x2a0 + si * 0x10;
-   case NV50_SEMANTIC_CLIPDISTANCE: return 0x2c0 + si * 0x10;
+   case NV50_SEMANTIC_CLIPDISTANCE: return 0x2c0 + si * 0x4;
+   case TGSI_SEMANTIC_CLIPDIST:     return 0x2c0 + si * 0x10;
+   case TGSI_SEMANTIC_CLIPVERTEX:   return 0x260;
    case NV50_SEMANTIC_POINTCOORD:   return 0x2e0;
    case NV50_SEMANTIC_TESSCOORD:    return 0x2f0;
    case TGSI_SEMANTIC_INSTANCEID:   return 0x2f8;
@@ -87,7 +89,9 @@ nvc0_shader_output_address(unsigned sn, unsigned si, unsigned ubase)
    case TGSI_SEMANTIC_FOG:           return 0x270;
    case TGSI_SEMANTIC_COLOR:         return 0x280 + si * 0x10;
    case TGSI_SEMANTIC_BCOLOR:        return 0x2a0 + si * 0x10;
-   case NV50_SEMANTIC_CLIPDISTANCE:  return 0x2c0 + si * 0x10;
+   case NV50_SEMANTIC_CLIPDISTANCE:  return 0x2c0 + si * 0x4;
+   case TGSI_SEMANTIC_CLIPDIST:      return 0x2c0 + si * 0x10;
+   case TGSI_SEMANTIC_CLIPVERTEX:    return 0x260;
    case NV50_SEMANTIC_TEXCOORD:      return 0x300 + si * 0x10;
    case TGSI_SEMANTIC_EDGEFLAG:      return ~0;
    default:
@@ -268,11 +272,14 @@ nvc0_vtgp_gen_header(struct nvc0_program *vp, struct nv50_ir_prog_info *info)
       }
    }
 
-   vp->vp.clip_enable = (1 << info->io.clipDistanceCount) - 1;
+   vp->vp.clip_enable = info->io.clipDistanceMask;
    for (i = 0; i < 8; ++i)
       if (info->io.cullDistanceMask & (1 << i))
          vp->vp.clip_mode |= 1 << (i * 4);
 
+   if (info->io.genUserClip < 0)
+      vp->vp.num_ucps = PIPE_MAX_CLIP_PLANES; /* prevent rebuilding */
+
    return 0;
 }
 
@@ -282,7 +289,7 @@ nvc0_vp_gen_header(struct nvc0_program *vp, struct nv50_ir_prog_info *info)
    vp->hdr[0] = 0x20061 | (1 << 10);
    vp->hdr[4] = 0xff000;
 
-   vp->hdr[18] = (1 << info->io.clipDistanceCount) - 1;
+   vp->hdr[18] = info->io.clipDistanceMask;
 
    return nvc0_vtgp_gen_header(vp, info);
 }
@@ -549,7 +556,7 @@ nvc0_program_translate(struct nvc0_program *prog)
    info->bin.sourceRep = NV50_PROGRAM_IR_TGSI;
    info->bin.source = (void *)prog->pipe.tokens;
 
-   info->io.clipDistanceCount = prog->vp.num_ucps;
+   info->io.genUserClip = prog->vp.num_ucps;
 
    info->assignSlots = nvc0_program_assign_varying_slots;
 
index 10eb9f724d569b078e71bfd403e72caf7b1bad9c..c384ef534d512566ff2e9c24965803d4766728dc 100644 (file)
@@ -36,9 +36,9 @@ struct nvc0_program {
 
    struct {
       uint32_t clip_mode; /* clip/cull selection */
-      uint8_t clip_enable; /* only applies if num_ucps == 0 */
+      uint8_t clip_enable; /* mask of defined clip planes */
       uint8_t edgeflag;
-      uint8_t num_ucps;
+      uint8_t num_ucps; /* also set to max if ClipDistance is used */
    } vp;
    struct {
       uint8_t early_z;
index 472ddee52164da46fe94776bdc0a3069614c8b6c..6307b3a3de68de9bfe6a21a2f4f39e9d1915db9c 100644 (file)
@@ -301,7 +301,7 @@ nvc0_validate_clip(struct nvc0_context *nvc0)
 {
    struct nouveau_channel *chan = nvc0->screen->base.channel;
    struct nvc0_program *vp;
-   uint8_t clip_enable;
+   uint8_t clip_enable = nvc0->rast->pipe.clip_plane_enable;
 
    if (nvc0->dirty & NVC0_NEW_CLIP)
       nvc0_upload_uclip_planes(nvc0);
@@ -312,13 +312,11 @@ nvc0_validate_clip(struct nvc0_context *nvc0)
       if (!vp)
          vp = nvc0->vertprog;
    }
-   clip_enable = vp->vp.clip_enable;
 
-   if (!clip_enable) {
-      clip_enable = nvc0->rast->pipe.clip_plane_enable;
-      if (unlikely(clip_enable))
-         nvc0_check_program_ucps(nvc0, vp, clip_enable);
-   }
+   if (clip_enable && vp->vp.num_ucps < PIPE_MAX_CLIP_PLANES)
+      nvc0_check_program_ucps(nvc0, vp, clip_enable);
+
+   clip_enable &= vp->vp.clip_enable;
 
    if (nvc0->state.clip_enable != clip_enable) {
       nvc0->state.clip_enable = clip_enable;