diff --git a/src/nouveau/codegen/nv50_ir.cpp b/src/nouveau/codegen/nv50_ir.cpp index 942f3a91e77..f7e8bcbeecf 100644 --- a/src/nouveau/codegen/nv50_ir.cpp +++ b/src/nouveau/codegen/nv50_ir.cpp @@ -1258,7 +1258,6 @@ nv50_ir_init_prog_info(struct nv50_ir_prog_info *info, info->prop.cp.numThreads[2] = 1; } info_out->bin.smemSize = info->bin.smemSize; - info_out->io.genUserClip = info->io.genUserClip; info_out->io.instanceId = 0xff; info_out->io.vertexId = 0xff; info_out->io.edgeFlagIn = 0xff; diff --git a/src/nouveau/codegen/nv50_ir_from_common.cpp b/src/nouveau/codegen/nv50_ir_from_common.cpp index 3156eeeca8c..5b22bd167c6 100644 --- a/src/nouveau/codegen/nv50_ir_from_common.cpp +++ b/src/nouveau/codegen/nv50_ir_from_common.cpp @@ -53,33 +53,4 @@ ConverterCommon::translateInterpMode(const struct nv50_ir_varying *var, operatio return mode; } -void -ConverterCommon::handleUserClipPlanes() -{ - Value *res[8]; - int n, i, c; - - for (c = 0; c < 4; ++c) { - for (i = 0; i < info_out->io.genUserClip; ++i) { - Symbol *sym = mkSymbol(FILE_MEMORY_CONST, info->io.auxCBSlot, - TYPE_F32, info->io.ucpBase + i * 16 + c * 4); - Value *ucp = mkLoadv(TYPE_F32, sym, NULL); - if (c == 0) - res[i] = mkOp2v(OP_MUL, TYPE_F32, getScratch(), clipVtx[c], ucp); - else - mkOp3(OP_MAD, TYPE_F32, res[i], clipVtx[c], ucp, res[i]); - } - } - - const int first = info_out->numOutputs - (info_out->io.genUserClip + 3) / 4; - - for (i = 0; i < info_out->io.genUserClip; ++i) { - n = i / 4 + first; - c = i % 4; - Symbol *sym = - mkSymbol(FILE_SHADER_OUTPUT, 0, TYPE_F32, info_out->out[n].slot[c] * 4); - mkStore(OP_EXPORT, TYPE_F32, sym, NULL, res[i]); - } -} - } // namespace nv50_ir diff --git a/src/nouveau/codegen/nv50_ir_from_common.h b/src/nouveau/codegen/nv50_ir_from_common.h index 03177ac1f7b..d3e216c5d10 100644 --- a/src/nouveau/codegen/nv50_ir_from_common.h +++ b/src/nouveau/codegen/nv50_ir_from_common.h @@ -32,12 +32,9 @@ public: protected: uint8_t translateInterpMode(const struct nv50_ir_varying *var, operation& op); - void handleUserClipPlanes(); - struct nv50_ir_prog_info *info; struct nv50_ir_prog_info_out *info_out; Value *fragCoord[4]; - Value *clipVtx[4]; Value *outBase; // base address of vertex out patch (for TCP) }; diff --git a/src/nouveau/codegen/nv50_ir_from_nir.cpp b/src/nouveau/codegen/nv50_ir_from_nir.cpp index e9ccf05417b..d704728cd02 100644 --- a/src/nouveau/codegen/nv50_ir_from_nir.cpp +++ b/src/nouveau/codegen/nv50_ir_from_nir.cpp @@ -23,6 +23,7 @@ */ #include "compiler/nir/nir.h" +#include "compiler/nir/nir_builder.h" #include "util/u_debug.h" #include "util/u_prim.h" @@ -65,6 +66,34 @@ function_temp_type_info(const struct glsl_type *type, unsigned *size, unsigned * } } +bool +nv50_nir_lower_load_user_clip_plane_cb(nir_builder *b, nir_intrinsic_instr *intrin, void *params) +{ + struct nv50_ir_prog_info *info = (struct nv50_ir_prog_info *)params; + + if (intrin->intrinsic != nir_intrinsic_load_user_clip_plane) + return false; + + uint16_t offset = info->io.ucpBase + nir_intrinsic_ucp_id(intrin) * 16; + + b->cursor = nir_before_instr(&intrin->instr); + nir_def *replacement = + nir_load_ubo(b, 4, 32, nir_imm_int(b, info->io.auxCBSlot), + nir_imm_int(b, offset), .range = ~0u); + + nir_def_rewrite_uses(&intrin->def, replacement); + nir_instr_remove(&intrin->instr); + + return true; +} + +bool +nv50_nir_lower_load_user_clip_plane(nir_shader *nir, struct nv50_ir_prog_info *info) { + return nir_shader_intrinsics_pass(nir, nv50_nir_lower_load_user_clip_plane_cb, + nir_metadata_block_index | nir_metadata_dominance, + info); +} + class Converter : public ConverterCommon { public: @@ -1044,9 +1073,6 @@ bool Converter::assignSlots() { info_out->numPatchConstants = MAX2(info_out->numPatchConstants, index + slots); switch (name) { - case TGSI_SEMANTIC_CLIPDIST: - info_out->io.genUserClip = -1; - break; case TGSI_SEMANTIC_CLIPVERTEX: clipVertexOutput = vary; break; @@ -1115,20 +1141,6 @@ bool Converter::assignSlots() { } } - if (info_out->io.genUserClip > 0) { - info_out->io.clipDistances = info_out->io.genUserClip; - - const unsigned int nOut = (info_out->io.genUserClip + 3) / 4; - - for (unsigned int n = 0; n < nOut; ++n) { - unsigned int i = info_out->numOutputs++; - info_out->out[i].id = i; - info_out->out[i].sn = TGSI_SEMANTIC_CLIPDIST; - info_out->out[i].si = n; - info_out->out[i].mask = ((1 << info_out->io.clipDistances) - 1) >> (n * 4); - } - } - return info->assignSlots(info_out) == 0; } @@ -1336,11 +1348,6 @@ Converter::visit(nir_function *function) setPosition(entry, true); - if (info_out->io.genUserClip > 0) { - for (int c = 0; c < 4; ++c) - clipVtx[c] = getScratch(); - } - switch (prog->getType()) { case Program::TYPE_TESSELLATION_CONTROL: outBase = mkOp2v( @@ -1367,11 +1374,6 @@ Converter::visit(nir_function *function) bb->cfg.attach(&exit->cfg, Graph::Edge::TREE); setPosition(exit, true); - if ((prog->getType() == Program::TYPE_VERTEX || - prog->getType() == Program::TYPE_TESSELLATION_EVAL) - && info_out->io.genUserClip > 0) - handleUserClipPlanes(); - // TODO: for non main function this needs to be a OP_RETURN mkOp(OP_EXIT, TYPE_NONE, NULL)->terminator = 1; return true; @@ -1683,15 +1685,6 @@ Converter::visit(nir_intrinsic_instr *insn) } break; } - case Program::TYPE_GEOMETRY: - case Program::TYPE_TESSELLATION_EVAL: - case Program::TYPE_VERTEX: { - if (info_out->io.genUserClip > 0 && idx == (uint32_t)clipVertexOutput) { - mkMov(clipVtx[i], src); - src = clipVtx[i]; - } - break; - } default: break; } @@ -2001,8 +1994,6 @@ Converter::visit(nir_intrinsic_instr *insn) break; } case nir_intrinsic_emit_vertex: { - if (info_out->io.genUserClip > 0) - handleUserClipPlanes(); uint32_t idx = nir_intrinsic_stream_id(insn); mkOp1(getOperation(op), TYPE_U32, NULL, mkImm(idx))->fixed = 1; break; @@ -3239,6 +3230,28 @@ Converter::run() (nir->options->lower_flrp64 ? 64 : 0); assert(lower_flrp); + info_out->io.genUserClip = info->io.genUserClip; + if (info->io.genUserClip > 0) { + bool lowered = false; + + if (nir->info.stage == MESA_SHADER_VERTEX || + nir->info.stage == MESA_SHADER_TESS_EVAL) + NIR_PASS(lowered, nir, nir_lower_clip_vs, + (1 << info->io.genUserClip) - 1, true, false, NULL); + else if (nir->info.stage == MESA_SHADER_GEOMETRY) + NIR_PASS(lowered, nir, nir_lower_clip_gs, + (1 << info->io.genUserClip) - 1, false, NULL); + + if (lowered) { + nir_function_impl *impl = nir_shader_get_entrypoint(nir); + NIR_PASS_V(nir, nir_lower_io_to_temporaries, impl, true, false); + NIR_PASS_V(nir, nir_lower_global_vars_to_local); + NIR_PASS_V(nir, nv50_nir_lower_load_user_clip_plane, info); + } else { + info_out->io.genUserClip = -1; + } + } + /* prepare for IO lowering */ NIR_PASS_V(nir, nir_lower_flrp, lower_flrp, false); NIR_PASS_V(nir, nir_opt_deref);