diff options
Diffstat (limited to 'src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp')
-rw-r--r-- | src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp | 158 |
1 files changed, 155 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(); |