TODO: a lot of those fields are not valid for a lot of tex ops. Not quite sure if it's worth the effort to check for those or just keep it like that. It seems to kind of work.
Signed-off-by: Karol Herbst <kher...@redhat.com> --- .../drivers/nouveau/codegen/nv50_ir_from_nir.cpp | 192 +++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp index bf213bca51..384127aff5 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp @@ -52,6 +52,7 @@ public: Converter(Program *, nir_shader *, nv50_ir_prog_info *); + TexTarget convert(glsl_sampler_dim&, bool isArray, bool isShadow); LValues& convert(nir_alu_dest *); BasicBlock* convert(nir_block *); LValues& convert(nir_dest *); @@ -82,6 +83,7 @@ public: bool visit(nir_load_const_instr*); bool visit(nir_loop *); bool visit(nir_ssa_undef_instr *); + bool visit(nir_tex_instr *); bool run(); @@ -96,9 +98,13 @@ public: DataType getSType(nir_src&, bool isFloat, bool isSigned); operation getOperation(nir_op); + operation getOperation(nir_texop); operation preOperationNeeded(nir_op); int getSubOp(nir_op); CondCode getCondCode(nir_op); + + // tex stuff + Value* applyProjection(Value *src, Value *proj); private: nir_shader *nir; @@ -331,6 +337,36 @@ Converter::getOperation(nir_op op) #undef CASE_OP3 #undef CASE_OPIU +operation +Converter::getOperation(nir_texop op) +{ + switch (op) { + case nir_texop_tex: + return OP_TEX; + case nir_texop_lod: + return OP_TXLQ; + case nir_texop_txb: + return OP_TXB; + case nir_texop_txd: + return OP_TXD; + case nir_texop_txf: + case nir_texop_txf_ms: + return OP_TXF; + case nir_texop_tg4: + return OP_TXG; + case nir_texop_txl: + return OP_TXL; + case nir_texop_query_levels: + case nir_texop_texture_samples: + case nir_texop_txs: + return OP_TXQ; + default: + ERROR("couldn't get operation for nir_texop %u\n", op); + assert(false); + return OP_NOP; + } +} + operation Converter::preOperationNeeded(nir_op op) { @@ -1102,6 +1138,10 @@ Converter::visit(nir_instr *insn) if (!visit(nir_instr_as_alu(insn))) return false; break; + case nir_instr_type_tex: + if (!visit(nir_instr_as_tex(insn))) + return false; + break; case nir_instr_type_intrinsic: if (!visit(nir_instr_as_intrinsic(insn))) return false; @@ -1674,6 +1714,158 @@ Converter::visit(nir_ssa_undef_instr *insn) return true; } +#define CASE_SAMPLER(ty) \ + case GLSL_SAMPLER_DIM_ ## ty : \ + if (isArray && !isShadow) \ + return TEX_TARGET_ ## ty ## _ARRAY; \ + else if (!isArray && isShadow) \ + return TEX_TARGET_## ty ## _SHADOW; \ + else if (isArray && isShadow) \ + return TEX_TARGET_## ty ## _ARRAY_SHADOW; \ + else \ + return TEX_TARGET_ ## ty + +TexTarget +Converter::convert(glsl_sampler_dim &dim, bool isArray, bool isShadow) +{ + switch (dim) { + CASE_SAMPLER(1D); + CASE_SAMPLER(2D); + CASE_SAMPLER(CUBE); + case GLSL_SAMPLER_DIM_3D: + return TEX_TARGET_3D; + case GLSL_SAMPLER_DIM_MS: + if (isArray) + return TEX_TARGET_2D_MS_ARRAY; + return TEX_TARGET_2D_MS; + case GLSL_SAMPLER_DIM_RECT: + if (isShadow) + return TEX_TARGET_RECT_SHADOW; + return TEX_TARGET_RECT; + case GLSL_SAMPLER_DIM_BUF: + return TEX_TARGET_BUFFER; + default: + ERROR("unknown glsl_sampler_dim %u\n", dim); + assert(false); + return TEX_TARGET_COUNT; + } +} +#undef CASE_SAMPLER + + +Value* +Converter::applyProjection(Value *src, Value *proj) +{ + if (!proj) + return src; + return mkOp2v(OP_MUL, TYPE_F32, getScratch(), src, proj); +} + +bool +Converter::visit(nir_tex_instr *insn) +{ + switch (insn->op) { + case nir_texop_lod: + case nir_texop_query_levels: + case nir_texop_tex: + case nir_texop_texture_samples: + case nir_texop_tg4: + case nir_texop_txb: + case nir_texop_txd: + case nir_texop_txf: + case nir_texop_txf_ms: + case nir_texop_txl: + case nir_texop_txs: { + LValues &newDefs = convert(&insn->dest); + std::vector<Value *> srcs; + std::vector<Value *> defs; + uint8_t mask = 0; + Value *proj = nullptr; + TexInstruction::Target target = convert(insn->sampler_dim, insn->is_array, insn->is_shadow); + + int biasIdx = nir_tex_instr_src_index(insn, nir_tex_src_bias); + int compIdx = nir_tex_instr_src_index(insn, nir_tex_src_comparator); + int coordsIdx = nir_tex_instr_src_index(insn, nir_tex_src_coord); + int ddxIdx = nir_tex_instr_src_index(insn, nir_tex_src_ddx); + int ddyIdx = nir_tex_instr_src_index(insn, nir_tex_src_ddy); + int msIdx = nir_tex_instr_src_index(insn, nir_tex_src_ms_index); + int lodIdx = nir_tex_instr_src_index(insn, nir_tex_src_lod); + int offsetIdx = nir_tex_instr_src_index(insn, nir_tex_src_offset); + int projIdx = nir_tex_instr_src_index(insn, nir_tex_src_projector); + + if (projIdx != -1) + proj = mkOp1v(OP_RCP, TYPE_F32, getScratch(), getSrc(&insn->src[projIdx].src, 0)); + + srcs.resize(insn->coord_components); + for (auto i = 0u; i < insn->coord_components; ++i) + srcs[i] = applyProjection(getSrc(&insn->src[coordsIdx].src, i), proj); + + if (insn->op == nir_texop_texture_samples) + srcs.push_back(zero); + else if (!insn->num_srcs) + srcs.push_back(loadImm(nullptr, 0)); + if (biasIdx != -1) + srcs.push_back(getSrc(&insn->src[biasIdx].src, 0)); + if (lodIdx != -1) + srcs.push_back(getSrc(&insn->src[lodIdx].src, 0)); + if (msIdx != -1) + srcs.push_back(getSrc(&insn->src[msIdx].src, 0)); + if (compIdx != -1) + srcs.push_back(applyProjection(getSrc(&insn->src[compIdx].src, 0), proj)); + + defs.resize(newDefs.size()); + for (auto d = 0u; d < newDefs.size(); ++d) { + defs[d] = newDefs[d]; + mask |= 1 << d; + } + + TexInstruction *texi = mkTex(getOperation(insn->op), target.getEnum(), insn->texture_index, insn->sampler_index, defs, srcs); + texi->tex.levelZero = target.isMS() ? 1 : 0; + texi->tex.mask = mask; + + switch (insn->op) { + case nir_texop_txs: + texi->tex.query = TXQ_DIMS; + break; + case nir_texop_texture_samples: + texi->tex.mask = 0x4; // some odd hw thing + texi->tex.query = TXQ_TYPE; + break; + case nir_texop_query_levels: + texi->tex.mask = 0x8; // some odd hw thing + texi->tex.query = TXQ_DIMS; + break; + default: + break; + } + + if (offsetIdx != -1) { + texi->tex.useOffsets = 1; + for (auto s = 0u; s < target.getDim(); ++s) { + for (auto c = 0u; c < 3; ++c) { + auto s2 = std::min(c, target.getDim() - 1); + texi->offset[s][c].set(getSrc(&insn->src[offsetIdx].src, s2)); + texi->offset[s][c].setInsn(texi); + } + } + } + + if (ddxIdx != -1 && ddyIdx != -1) { + for (auto c = 0u; c < target.getDim() + target.isCube(); ++c) { + texi->dPdx[c].set(getSrc(&insn->src[ddxIdx].src, c)); + texi->dPdy[c].set(getSrc(&insn->src[ddyIdx].src, c)); + } + } + + break; + } + default: + ERROR("unknown nir_texop %u\n", insn->op); + return false; + } + return true; +} + bool Converter::run() { -- 2.14.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev