From 704bc0f0e98f3bbdef33cad12646d4e1bf01e8aa Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sun, 29 May 2016 12:42:49 -0400 Subject: [PATCH] nvc0: add support for VOTE tgsi opcodes Signed-off-by: Ilia Mirkin Reviewed-by: Samuel Pitoiset --- docs/relnotes/12.1.0.html | 2 +- .../nouveau/codegen/nv50_ir_emit_gk110.cpp | 23 ++++++++++++--- .../nouveau/codegen/nv50_ir_emit_gm107.cpp | 29 ++++++++++--------- .../nouveau/codegen/nv50_ir_emit_nvc0.cpp | 23 ++++++++++++--- .../nouveau/codegen/nv50_ir_from_tgsi.cpp | 21 ++++++++++++++ .../drivers/nouveau/nvc0/nvc0_screen.c | 5 ++-- 6 files changed, 78 insertions(+), 25 deletions(-) diff --git a/docs/relnotes/12.1.0.html b/docs/relnotes/12.1.0.html index 50eee17699d..3f7b1968066 100644 --- a/docs/relnotes/12.1.0.html +++ b/docs/relnotes/12.1.0.html @@ -44,7 +44,7 @@ Note: some of the new features are only available with certain drivers.

    -TBD +
  • GL_ARB_shader_group_vote on nvc0

Bug fixes

diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp index 80e09900bc6..501d4af7915 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp @@ -1481,16 +1481,31 @@ CodeEmitterGK110::emitFlow(const Instruction *i) void CodeEmitterGK110::emitVOTE(const Instruction *i) { - assert(i->src(0).getFile() == FILE_PREDICATE && - i->def(1).getFile() == FILE_PREDICATE); + assert(i->src(0).getFile() == FILE_PREDICATE); code[0] = 0x00000002; code[1] = 0x86c00000 | (i->subOp << 19); emitPredicate(i); - defId(i->def(0), 2); - defId(i->def(1), 48); + unsigned rp = 0; + for (int d = 0; i->defExists(d); d++) { + if (i->def(d).getFile() == FILE_PREDICATE) { + assert(!(rp & 2)); + rp |= 2; + defId(i->def(d), 48); + } else if (i->def(d).getFile() == FILE_GPR) { + assert(!(rp & 1)); + rp |= 1; + defId(i->def(d), 2); + } else { + assert(!"Unhandled def"); + } + } + if (!(rp & 1)) + code[0] |= 255 << 2; + if (!(rp & 2)) + code[1] |= 7 << 16; if (i->src(0).mod == Modifier(NV50_IR_MOD_NOT)) code[1] |= 1 << 13; srcId(i->src(0), 42); 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 a43d7b1296a..ef02dbb4c63 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp @@ -2788,23 +2788,26 @@ CodeEmitterGM107::emitMEMBAR() void CodeEmitterGM107::emitVOTE() { - int subOp; + assert(insn->src(0).getFile() == FILE_PREDICATE); - assert(insn->src(0).getFile() == FILE_PREDICATE && - insn->def(1).getFile() == FILE_PREDICATE); - - switch (insn->subOp) { - case NV50_IR_SUBOP_VOTE_ANY: subOp = 1; break; - default: - assert(insn->subOp == NV50_IR_SUBOP_VOTE_ALL); - subOp = 0; - break; + int r = -1, p = -1; + for (int i = 0; insn->defExists(i); i++) { + if (insn->def(i).getFile() == FILE_GPR) + r = i; + else if (insn->def(i).getFile() == FILE_PREDICATE) + p = i; } emitInsn (0x50d80000); - emitField(0x30, 2, subOp); - emitGPR (0x00, insn->def(0)); - emitPRED (0x2d, insn->def(1)); + emitField(0x30, 2, insn->subOp); + if (r >= 0) + emitGPR (0x00, insn->def(r)); + else + emitGPR (0x00); + if (p >= 0) + emitPRED (0x2d, insn->def(p)); + else + emitPRED (0x2d); emitField(0x2a, 1, insn->src(0).mod == Modifier(NV50_IR_MOD_NOT)); emitPRED (0x27, insn->src(0)); } diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp index bc94285120e..1c3e5198c96 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp @@ -2472,16 +2472,31 @@ CodeEmitterNVC0::emitPIXLD(const Instruction *i) void CodeEmitterNVC0::emitVOTE(const Instruction *i) { - assert(i->src(0).getFile() == FILE_PREDICATE && - i->def(1).getFile() == FILE_PREDICATE); + assert(i->src(0).getFile() == FILE_PREDICATE); code[0] = 0x00000004 | (i->subOp << 5); code[1] = 0x48000000; emitPredicate(i); - defId(i->def(0), 14); - defId(i->def(1), 32 + 22); + unsigned rp = 0; + for (int d = 0; i->defExists(d); d++) { + if (i->def(d).getFile() == FILE_PREDICATE) { + assert(!(rp & 2)); + rp |= 2; + defId(i->def(d), 32 + 22); + } else if (i->def(d).getFile() == FILE_GPR) { + assert(!(rp & 1)); + rp |= 1; + defId(i->def(d), 14); + } else { + assert(!"Unhandled def"); + } + } + if (!(rp & 1)) + code[0] |= 63 << 14; + if (!(rp & 2)) + code[1] |= 7 << 22; if (i->src(0).mod == Modifier(NV50_IR_MOD_NOT)) code[0] |= 1 << 23; srcId(i->src(0), 20); diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp index beb7b5310bf..ed3249e67b1 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp @@ -548,6 +548,9 @@ nv50_ir::DataType Instruction::inferSrcType() const case TGSI_OPCODE_UBFE: case TGSI_OPCODE_UMSB: case TGSI_OPCODE_UP2H: + case TGSI_OPCODE_VOTE_ALL: + case TGSI_OPCODE_VOTE_ANY: + case TGSI_OPCODE_VOTE_EQ: return nv50_ir::TYPE_U32; case TGSI_OPCODE_I2F: case TGSI_OPCODE_I2D: @@ -835,6 +838,10 @@ static nv50_ir::operation translateOpcode(uint opcode) NV50_IR_OPCODE_CASE(IMSB, BFIND); NV50_IR_OPCODE_CASE(UMSB, BFIND); + NV50_IR_OPCODE_CASE(VOTE_ALL, VOTE); + NV50_IR_OPCODE_CASE(VOTE_ANY, VOTE); + NV50_IR_OPCODE_CASE(VOTE_EQ, VOTE); + NV50_IR_OPCODE_CASE(END, EXIT); default: @@ -861,6 +868,9 @@ static uint16_t opcodeToSubOp(uint opcode) case TGSI_OPCODE_IMUL_HI: case TGSI_OPCODE_UMUL_HI: return NV50_IR_SUBOP_MUL_HIGH; + case TGSI_OPCODE_VOTE_ALL: return NV50_IR_SUBOP_VOTE_ALL; + case TGSI_OPCODE_VOTE_ANY: return NV50_IR_SUBOP_VOTE_ANY; + case TGSI_OPCODE_VOTE_EQ: return NV50_IR_SUBOP_VOTE_UNI; default: return 0; } @@ -3187,6 +3197,17 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn) mkCmp(op, tgsi.getSetCond(), dstTy, dst0[c], srcTy, src0, src1); } break; + case TGSI_OPCODE_VOTE_ALL: + case TGSI_OPCODE_VOTE_ANY: + case TGSI_OPCODE_VOTE_EQ: + val0 = new_LValue(func, FILE_PREDICATE); + FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) { + mkCmp(OP_SET, CC_NE, TYPE_U32, val0, TYPE_U32, fetchSrc(0, c), zero); + mkOp1(op, dstTy, val0, val0) + ->subOp = tgsi::opcodeToSubOp(tgsi.getOpcode()); + mkCvt(OP_CVT, TYPE_U32, dst0[c], TYPE_U8, val0); + } + break; case TGSI_OPCODE_KILL_IF: val0 = new_LValue(func, FILE_PREDICATE); mask = 0; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index 934998c9b14..b9437b2240c 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -230,11 +230,11 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_CULL_DISTANCE: case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES: case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR: + case PIPE_CAP_COMPUTE: + case PIPE_CAP_TGSI_VOTE: return 1; case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: return (class_3d >= NVE4_3D_CLASS) ? 1 : 0; - case PIPE_CAP_COMPUTE: - return 1; case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return nouveau_screen(pscreen)->vram_domain & NOUVEAU_BO_VRAM ? 1 : 0; @@ -261,7 +261,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_PCI_BUS: case PIPE_CAP_PCI_DEVICE: case PIPE_CAP_PCI_FUNCTION: - case PIPE_CAP_TGSI_VOTE: return 0; case PIPE_CAP_VENDOR_ID: -- 2.30.2