aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
diff options
context:
space:
mode:
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.cpp158
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();