diff options
author | Rob Clark <[email protected]> | 2017-04-17 11:04:00 -0400 |
---|---|---|
committer | Rob Clark <[email protected]> | 2017-05-04 13:48:06 -0400 |
commit | edde00f5f1a1a6b3f9827af0475f6ff097705c1f (patch) | |
tree | 5be67722c705b872b2e0f2df33f4d748d754a518 /src/gallium/drivers/freedreno/ir3/ir3.c | |
parent | 4d841fbaae3eac04f33f6a52f3dd829cfb1913b5 (diff) |
freedreno/ir3: SSBO/atomic support
TODO cwabbott pointed out a write-after-read hazzard, which effects both
this and arrays. A write needs to depend on *all* reads since the last
write, not just the last read.
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/ir3/ir3.c')
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3.c | 74 |
1 files changed, 66 insertions, 8 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.c b/src/gallium/drivers/freedreno/ir3/ir3.c index ff2c342c357..d703f4e7f38 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.c +++ b/src/gallium/drivers/freedreno/ir3/ir3.c @@ -475,6 +475,13 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, struct ir3_register *dst, *src1, *src2; instr_cat6_t *cat6 = ptr; + cat6->type = instr->cat6.type; + cat6->opc = instr->opc; + cat6->jmp_tgt = !!(instr->flags & IR3_INSTR_JP); + cat6->sync = !!(instr->flags & IR3_INSTR_SY); + cat6->g = !!(instr->flags & IR3_INSTR_G); + cat6->opc_cat = 6; + /* the "dst" for a store instruction is (from the perspective * of data flow in the shader, ie. register use/def, etc) in * fact a register that is read by the instruction, rather @@ -500,7 +507,65 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, * indicate to use the src_off encoding even if offset is zero * (but then what to do about dst_off?) */ - if (instr->cat6.src_offset || (instr->opc == OPC_LDG)) { + if ((instr->opc == OPC_LDGB) || is_atomic(instr->opc)) { + struct ir3_register *src3 = instr->regs[3]; + instr_cat6ldgb_t *ldgb = ptr; + + /* maybe these two bits both determine the instruction encoding? */ + cat6->src_off = false; + + ldgb->d = 4 - 1; /* always .4d ? */ + ldgb->typed = false; /* TODO true for images */ + ldgb->type_size = instr->cat6.iim_val - 1; + + ldgb->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF); + + /* first src is src_ssbo: */ + iassert(src1->flags & IR3_REG_IMMED); + ldgb->src_ssbo = src1->uim_val; + + /* then next two are src1/src2: */ + ldgb->src1 = reg(src2, info, instr->repeat, IR3_REG_IMMED); + ldgb->src1_im = !!(src2->flags & IR3_REG_IMMED); + ldgb->src2 = reg(src3, info, instr->repeat, IR3_REG_IMMED); + ldgb->src2_im = !!(src3->flags & IR3_REG_IMMED); + + if (is_atomic(instr->opc)) { + struct ir3_register *src4 = instr->regs[4]; + ldgb->src3 = reg(src4, info, instr->repeat, 0); + ldgb->pad0 = 0x1; + ldgb->pad3 = 0x3; + } else { + ldgb->pad0 = 0x0; + ldgb->pad3 = 0x2; + } + + return 0; + } else if (instr->opc == OPC_STGB) { + struct ir3_register *src3 = instr->regs[4]; + instr_cat6stgb_t *stgb = ptr; + + /* maybe these two bits both determine the instruction encoding? */ + cat6->src_off = true; + stgb->pad3 = 0x2; + + stgb->d = 4 - 1; /* always .4d ? */ + stgb->typed = false; + stgb->type_size = instr->cat6.iim_val - 1; + + /* first src is dst_ssbo: */ + iassert(dst->flags & IR3_REG_IMMED); + stgb->dst_ssbo = dst->uim_val; + + /* then src1/src2/src3: */ + stgb->src1 = reg(src1, info, instr->repeat, 0); + stgb->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED); + stgb->src2_im = !!(src2->flags & IR3_REG_IMMED); + stgb->src3 = reg(src3, info, instr->repeat, IR3_REG_IMMED); + stgb->src3_im = !!(src3->flags & IR3_REG_IMMED); + + return 0; + } else if (instr->cat6.src_offset || (instr->opc == OPC_LDG)) { instr_cat6a_t *cat6a = ptr; cat6->src_off = true; @@ -536,13 +601,6 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, cat6d->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF); } - cat6->type = instr->cat6.type; - cat6->opc = instr->opc; - cat6->jmp_tgt = !!(instr->flags & IR3_INSTR_JP); - cat6->sync = !!(instr->flags & IR3_INSTR_SY); - cat6->g = !!(instr->flags & IR3_INSTR_G); - cat6->opc_cat = 6; - return 0; } |