diff options
Diffstat (limited to 'src/gallium/drivers/nouveau/codegen')
-rw-r--r-- | src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp | 158 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp | 162 |
2 files changed, 317 insertions, 3 deletions
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp index b2e22195ec5..241061ab837 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp @@ -192,6 +192,7 @@ private: void emitTEXs(int); void emitTEX(); + void emitTEXS(); void emitTLD(); void emitTLD4(); void emitTXD(); @@ -2718,6 +2719,103 @@ CodeEmitterGM107::emitTEXs(int pos) emitGPR(pos); } +static uint8_t +getTEXSMask(uint8_t mask) +{ + switch (mask) { + case 0x1: return 0x0; + case 0x2: return 0x1; + case 0x3: return 0x4; + case 0x4: return 0x2; + case 0x7: return 0x0; + case 0x8: return 0x3; + case 0x9: return 0x5; + case 0xa: return 0x6; + case 0xb: return 0x1; + case 0xc: return 0x7; + case 0xd: return 0x2; + case 0xe: return 0x3; + case 0xf: return 0x4; + default: + assert(!"invalid mask"); + } +} + +static uint8_t +getTEXSTarget(const TexInstruction *tex) +{ + assert(tex->op == OP_TEX || tex->op == OP_TXL); + + switch (tex->tex.target.getEnum()) { + case TEX_TARGET_1D: + assert(tex->tex.levelZero); + return 0x0; + case TEX_TARGET_2D: + case TEX_TARGET_RECT: + if (tex->tex.levelZero) + return 0x2; + if (tex->op == OP_TXL) + return 0x3; + return 0x1; + case TEX_TARGET_2D_SHADOW: + case TEX_TARGET_RECT_SHADOW: + if (tex->tex.levelZero) + return 0x6; + if (tex->op == OP_TXL) + return 0x5; + return 0x4; + case TEX_TARGET_2D_ARRAY: + if (tex->tex.levelZero) + return 0x8; + return 0x7; + case TEX_TARGET_2D_ARRAY_SHADOW: + assert(tex->tex.levelZero); + return 0x9; + case TEX_TARGET_3D: + if (tex->tex.levelZero) + return 0xb; + assert(tex->op != OP_TXL); + return 0xa; + case TEX_TARGET_CUBE: + assert(!tex->tex.levelZero); + if (tex->op == OP_TXL) + return 0xd; + return 0xc; + default: + assert(false); + return 0x0; + } +} + +static uint8_t +getTLDSTarget(const TexInstruction *tex) +{ + switch (tex->tex.target.getEnum()) { + case TEX_TARGET_1D: + if (tex->tex.levelZero) + return 0x0; + return 0x1; + case TEX_TARGET_2D: + case TEX_TARGET_RECT: + if (tex->tex.levelZero) + return tex->tex.useOffsets ? 0x4 : 0x2; + return tex->tex.useOffsets ? 0xc : 0x5; + case TEX_TARGET_2D_MS: + assert(tex->tex.levelZero); + return 0x6; + case TEX_TARGET_3D: + assert(tex->tex.levelZero); + return 0x7; + case TEX_TARGET_2D_ARRAY: + assert(tex->tex.levelZero); + return 0x8; + + default: + assert(false); + return 0x0; + } +} + void CodeEmitterGM107::emitTEX() { @@ -2761,6 +2859,49 @@ CodeEmitterGM107::emitTEX() } void +CodeEmitterGM107::emitTEXS() +{ + const TexInstruction *insn = this->insn->asTex(); + + switch (insn->op) { + case OP_TEX: + case OP_TXL: + emitInsn (0xd8000000); + emitField(0x35, 4, getTEXSTarget(insn)); + emitField(0x32, 3, getTEXSMask(insn->tex.mask)); + break; + case OP_TXF: + emitInsn (0xda000000); + emitField(0x35, 4, getTLDSTarget(insn)); + emitField(0x32, 3, getTEXSMask(insn->tex.mask)); + break; + case OP_TXG: + assert(insn->tex.useOffsets != 4); + emitInsn (0xdf000000); + emitField(0x34, 2, insn->tex.gatherComp); + emitField(0x33, 1, insn->tex.useOffsets == 1); + emitField(0x32, 1, insn->tex.target.isShadow()); + break; + default: + unreachable("unknown op in emitTEXS()"); + break; + } + + emitField(0x31, 1, insn->tex.liveOnly); + emitField(0x24, 13, insn->tex.r); + if (insn->defExists(1)) + emitGPR(0x1c, insn->def(1)); + else + emitGPR(0x1c); + if (insn->srcExists(1)) + emitGPR(0x14, insn->getSrc(1)); + else + emitGPR(0x14); + emitGPR (0x08, insn->src(0)); + emitGPR (0x00, insn->def(0)); +} + +void CodeEmitterGM107::emitTLD() { const TexInstruction *insn = this->insn->asTex(); @@ -3474,15 +3615,26 @@ CodeEmitterGM107::emitInstruction(Instruction *i) emitPIXLD(); break; case OP_TEX: - case OP_TXB: case OP_TXL: + if (insn->asTex()->tex.scalar) + emitTEXS(); + else + emitTEX(); + break; + case OP_TXB: emitTEX(); break; case OP_TXF: - emitTLD(); + if (insn->asTex()->tex.scalar) + emitTEXS(); + else + emitTLD(); break; case OP_TXG: - emitTLD4(); + if (insn->asTex()->tex.scalar) + emitTEXS(); + else + emitTLD4(); break; case OP_TXD: emitTXD(); diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp index 0059ecaeb6c..87a39de99d6 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp @@ -275,6 +275,9 @@ private: void texConstraintNVE0(TexInstruction *); void texConstraintGM107(TexInstruction *); + bool isScalarTexGM107(TexInstruction *); + void handleScalarTexGM107(TexInstruction *); + std::list<Instruction *> constrList; const Target *targ; @@ -2119,6 +2122,158 @@ RegAlloc::InsertConstraintsPass::condenseSrcs(Instruction *insn, constrList.push_back(merge); } +bool +RegAlloc::InsertConstraintsPass::isScalarTexGM107(TexInstruction *tex) +{ + if (tex->tex.sIndirectSrc >= 0 || + tex->tex.rIndirectSrc >= 0) + return false; + + if (tex->tex.mask == 5 || tex->tex.mask == 6) + return false; + + switch (tex->op) { + case OP_TEX: + case OP_TXF: + case OP_TXG: + case OP_TXL: + break; + default: + return false; + } + + // legal variants: + // TEXS.1D.LZ + // TEXS.2D + // TEXS.2D.LZ + // TEXS.2D.LL + // TEXS.2D.DC + // TEXS.2D.LL.DC + // TEXS.2D.LZ.DC + // TEXS.A2D + // TEXS.A2D.LZ + // TEXS.A2D.LZ.DC + // TEXS.3D + // TEXS.3D.LZ + // TEXS.CUBE + // TEXS.CUBE.LL + + // TLDS.1D.LZ + // TLDS.1D.LL + // TLDS.2D.LZ + // TLSD.2D.LZ.AOFFI + // TLDS.2D.LZ.MZ + // TLDS.2D.LL + // TLDS.2D.LL.AOFFI + // TLDS.A2D.LZ + // TLDS.3D.LZ + + // TLD4S: all 2D/RECT variants and only offset + + switch (tex->op) { + case OP_TEX: + if (tex->tex.useOffsets) + return false; + + switch (tex->tex.target.getEnum()) { + case TEX_TARGET_1D: + case TEX_TARGET_2D_ARRAY_SHADOW: + return tex->tex.levelZero; + case TEX_TARGET_CUBE: + return !tex->tex.levelZero; + case TEX_TARGET_2D: + case TEX_TARGET_2D_ARRAY: + case TEX_TARGET_2D_SHADOW: + case TEX_TARGET_3D: + case TEX_TARGET_RECT: + case TEX_TARGET_RECT_SHADOW: + return true; + default: + return false; + } + + case OP_TXL: + if (tex->tex.useOffsets) + return false; + + switch (tex->tex.target.getEnum()) { + case TEX_TARGET_2D: + case TEX_TARGET_2D_SHADOW: + case TEX_TARGET_RECT: + case TEX_TARGET_RECT_SHADOW: + case TEX_TARGET_CUBE: + return true; + default: + return false; + } + + case OP_TXF: + switch (tex->tex.target.getEnum()) { + case TEX_TARGET_1D: + return !tex->tex.useOffsets; + case TEX_TARGET_2D: + case TEX_TARGET_RECT: + return true; + case TEX_TARGET_2D_ARRAY: + case TEX_TARGET_2D_MS: + case TEX_TARGET_3D: + return !tex->tex.useOffsets && tex->tex.levelZero; + default: + return false; + } + + case OP_TXG: + if (tex->tex.useOffsets > 1) + return false; + if (tex->tex.mask != 0x3 && tex->tex.mask != 0xf) + return false; + + switch (tex->tex.target.getEnum()) { + case TEX_TARGET_2D: + case TEX_TARGET_2D_MS: + case TEX_TARGET_2D_SHADOW: + case TEX_TARGET_RECT: + case TEX_TARGET_RECT_SHADOW: + return true; + default: + return false; + } + + default: + return false; + } +} + +void +RegAlloc::InsertConstraintsPass::handleScalarTexGM107(TexInstruction *tex) +{ + int defCount = tex->defCount(0xff); + int srcCount = tex->srcCount(0xff); + + tex->tex.scalar = true; + + // 1. handle defs + if (defCount > 3) + condenseDefs(tex, 2, 3); + if (defCount > 1) + condenseDefs(tex, 0, 1); + + // 2. handle srcs + // special case for TXF.A2D + if (tex->op == OP_TXF && tex->tex.target == TEX_TARGET_2D_ARRAY) { + assert(srcCount >= 3); + condenseSrcs(tex, 1, 2); + } else { + if (srcCount > 3) + condenseSrcs(tex, 2, 3); + // only if we have more than 2 sources + if (srcCount > 2) + condenseSrcs(tex, 0, 1); + } + + assert(!tex->defExists(2) && !tex->srcExists(2)); +} + void RegAlloc::InsertConstraintsPass::texConstraintGM107(TexInstruction *tex) { @@ -2126,6 +2281,13 @@ RegAlloc::InsertConstraintsPass::texConstraintGM107(TexInstruction *tex) if (isTextureOp(tex->op)) textureMask(tex); + + if (isScalarTexGM107(tex)) { + handleScalarTexGM107(tex); + return; + } + + assert(!tex->tex.scalar); condenseDefs(tex); if (isSurfaceOp(tex->op)) { |