From b85e93c0ca5ce881a59412b3ae617b5ac2c3aeb6 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Sat, 7 Jan 2012 17:26:58 +0100 Subject: [PATCH] nv50/ir,nvc0: make ClipDistance and ClipVertex work --- .../drivers/nv50/codegen/nv50_ir_driver.h | 3 +- .../drivers/nv50/codegen/nv50_ir_from_sm4.cpp | 9 +++-- .../nv50/codegen/nv50_ir_from_tgsi.cpp | 33 +++++++++++++++---- src/gallium/drivers/nvc0/nvc0_program.c | 17 +++++++--- src/gallium/drivers/nvc0/nvc0_program.h | 4 +-- .../drivers/nvc0/nvc0_state_validate.c | 12 +++---- 6 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h b/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h index a6a5e93f58c..4baef537370 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h @@ -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; diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_from_sm4.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_from_sm4.cpp index 7ed00e336c6..11720d2db67 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_from_sm4.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_from_sm4.cpp @@ -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) diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp index 6cb61b87766..050f2516b99 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp @@ -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(); } diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c index 605bca5e6ba..5eee895fea7 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nvc0/nvc0_program.c @@ -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; diff --git a/src/gallium/drivers/nvc0/nvc0_program.h b/src/gallium/drivers/nvc0/nvc0_program.h index 10eb9f724d5..c384ef534d5 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.h +++ b/src/gallium/drivers/nvc0/nvc0_program.h @@ -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; diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c index 472ddee5216..6307b3a3de6 100644 --- a/src/gallium/drivers/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c @@ -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; -- 2.30.2