diff options
author | Glenn Kennard <[email protected]> | 2014-08-17 22:26:19 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2014-08-19 16:30:13 +0200 |
commit | dfa10ed2640a350a84e6e31edd22560155cd5016 (patch) | |
tree | 1fe5c1378d50b757ab4446de2944239bd092e451 | |
parent | ef1cf69cd34701ea005a244909c71357a3dddb06 (diff) |
r600g: Fix missing SET_TEXTURE_OFFSETS
SB needs a bit of special handling to handle
instructions without obvious side effects, to
avoid it deleting them.
Fixes failing non-const ARB_gpu_shader5
textureOffsets piglits with sb enabled.
Signed-off-by: Glenn Kennard <[email protected]>
Signed-off-by: Marek Olšák <[email protected]>
-rw-r--r-- | src/gallium/drivers/r600/r600_isa.h | 9 | ||||
-rw-r--r-- | src/gallium/drivers/r600/sb/sb_bc_finalize.cpp | 119 | ||||
-rw-r--r-- | src/gallium/drivers/r600/sb/sb_bc_parser.cpp | 13 | ||||
-rw-r--r-- | src/gallium/drivers/r600/sb/sb_pass.h | 3 |
4 files changed, 87 insertions, 57 deletions
diff --git a/src/gallium/drivers/r600/r600_isa.h b/src/gallium/drivers/r600/r600_isa.h index c6bb869fd10..ec3f7028a98 100644 --- a/src/gallium/drivers/r600/r600_isa.h +++ b/src/gallium/drivers/r600/r600_isa.h @@ -123,6 +123,9 @@ enum fetch_op_flags FF_VTX = (1<<5), FF_MEM = (1<<6), + + FF_SET_TEXTURE_OFFSETS = (1<<7), + FF_USE_TEXTURE_OFFSETS = (1<<8), }; /* flags for CF instructions */ @@ -523,7 +526,7 @@ static const struct fetch_op_info fetch_op_table[] = { {"GET_GRADIENTS_H_FINE", { -1, -1, 0x000107, 0x000107 }, FF_GETGRAD }, {"GET_GRADIENTS_V_FINE", { -1, -1, 0x000108, 0x000108 }, FF_GETGRAD }, {"GET_LERP", { 0x000009, 0x000009, -1, -1 }, 0 }, - {"SET_TEXTURE_OFFSETS", { -1, -1, 0x000009, 0x000009 }, 0 }, + {"SET_TEXTURE_OFFSETS", { -1, -1, 0x000009, 0x000009 }, FF_SET_TEXTURE_OFFSETS }, {"KEEP_GRADIENTS", { -1, 0x00000A, 0x00000A, 0x00000A }, 0 }, {"SET_GRADIENTS_H", { 0x00000B, 0x00000B, 0x00000B, 0x00000B }, FF_SETGRAD }, {"SET_GRADIENTS_V", { 0x00000C, 0x00000C, 0x00000C, 0x00000C }, FF_SETGRAD }, @@ -550,7 +553,7 @@ static const struct fetch_op_info fetch_op_table[] = { {"GATHER4", { -1, -1, 0x000015, 0x000015 }, FF_TEX }, {"SAMPLE_G_LB", { 0x000016, 0x000016, 0x000016, 0x000016 }, FF_TEX | FF_USEGRAD}, {"SAMPLE_G_LZ", { 0x000017, 0x000017, -1, -1 }, FF_TEX | FF_USEGRAD}, - {"GATHER4_O", { -1, -1, 0x000017, 0x000017 }, FF_TEX }, + {"GATHER4_O", { -1, -1, 0x000017, 0x000017 }, FF_TEX | FF_USE_TEXTURE_OFFSETS}, {"SAMPLE_C", { 0x000018, 0x000018, 0x000018, 0x000018 }, FF_TEX }, {"SAMPLE_C_L", { 0x000019, 0x000019, 0x000019, 0x000019 }, FF_TEX }, {"SAMPLE_C_LB", { 0x00001A, 0x00001A, 0x00001A, 0x00001A }, FF_TEX }, @@ -560,7 +563,7 @@ static const struct fetch_op_info fetch_op_table[] = { {"GATHER4_C", { -1, -1, 0x00001D, 0x00001D }, FF_TEX }, {"SAMPLE_C_G_LB", { 0x00001E, 0x00001E, 0x00001E, 0x00001E }, FF_TEX | FF_USEGRAD}, {"SAMPLE_C_G_LZ", { 0x00001F, 0x00001F, -1, -1 }, FF_TEX | FF_USEGRAD}, - {"GATHER4_C_O", { -1, -1, 0x00001F, 0x00001F }, FF_TEX } + {"GATHER4_C_O", { -1, -1, 0x00001F, 0x00001F }, FF_TEX | FF_USE_TEXTURE_OFFSETS} }; static const struct cf_op_info cf_op_table[] = { diff --git a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp index 99a20eb00c8..5c22f964690 100644 --- a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp +++ b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp @@ -394,81 +394,96 @@ void bc_finalizer::finalize_alu_src(alu_group_node* g, alu_node* a) { } } -void bc_finalizer::emit_set_grad(fetch_node* f) { +void bc_finalizer::copy_fetch_src(fetch_node &dst, fetch_node &src, unsigned arg_start) +{ + int reg = -1; - assert(f->src.size() == 12); - unsigned ops[2] = { FETCH_OP_SET_GRADIENTS_V, FETCH_OP_SET_GRADIENTS_H }; + for (unsigned chan = 0; chan < 4; ++chan) { - unsigned arg_start = 0; + dst.bc.dst_sel[chan] = SEL_MASK; - for (unsigned op = 0; op < 2; ++op) { - fetch_node *n = sh.create_fetch(); - n->bc.set_op(ops[op]); + unsigned sel = SEL_MASK; - // FIXME extract this loop into a separate method and reuse it + value *v = src.src[arg_start + chan]; - int reg = -1; + if (!v || v->is_undef()) { + sel = SEL_MASK; + } else if (v->is_const()) { + literal l = v->literal_value; + if (l == literal(0)) + sel = SEL_0; + else if (l == literal(1.0f)) + sel = SEL_1; + else { + sblog << "invalid fetch constant operand " << chan << " "; + dump::dump_op(&src); + sblog << "\n"; + abort(); + } - arg_start += 4; + } else if (v->is_any_gpr()) { + unsigned vreg = v->gpr.sel(); + unsigned vchan = v->gpr.chan(); - for (unsigned chan = 0; chan < 4; ++chan) { + if (reg == -1) + reg = vreg; + else if ((unsigned)reg != vreg) { + sblog << "invalid fetch source operand " << chan << " "; + dump::dump_op(&src); + sblog << "\n"; + abort(); + } - n->bc.dst_sel[chan] = SEL_MASK; + sel = vchan; - unsigned sel = SEL_MASK; + } else { + sblog << "invalid fetch source operand " << chan << " "; + dump::dump_op(&src); + sblog << "\n"; + abort(); + } - value *v = f->src[arg_start + chan]; + dst.bc.src_sel[chan] = sel; + } - if (!v || v->is_undef()) { - sel = SEL_MASK; - } else if (v->is_const()) { - literal l = v->literal_value; - if (l == literal(0)) - sel = SEL_0; - else if (l == literal(1.0f)) - sel = SEL_1; - else { - sblog << "invalid fetch constant operand " << chan << " "; - dump::dump_op(f); - sblog << "\n"; - abort(); - } + if (reg >= 0) + update_ngpr(reg); - } else if (v->is_any_gpr()) { - unsigned vreg = v->gpr.sel(); - unsigned vchan = v->gpr.chan(); + dst.bc.src_gpr = reg >= 0 ? reg : 0; +} - if (reg == -1) - reg = vreg; - else if ((unsigned)reg != vreg) { - sblog << "invalid fetch source operand " << chan << " "; - dump::dump_op(f); - sblog << "\n"; - abort(); - } +void bc_finalizer::emit_set_grad(fetch_node* f) { - sel = vchan; + assert(f->src.size() == 12); + unsigned ops[2] = { FETCH_OP_SET_GRADIENTS_V, FETCH_OP_SET_GRADIENTS_H }; - } else { - sblog << "invalid fetch source operand " << chan << " "; - dump::dump_op(f); - sblog << "\n"; - abort(); - } + unsigned arg_start = 0; - n->bc.src_sel[chan] = sel; - } + for (unsigned op = 0; op < 2; ++op) { + fetch_node *n = sh.create_fetch(); + n->bc.set_op(ops[op]); - if (reg >= 0) - update_ngpr(reg); + arg_start += 4; - n->bc.src_gpr = reg >= 0 ? reg : 0; + copy_fetch_src(*n, *f, arg_start); f->insert_before(n); } } +void bc_finalizer::emit_set_texture_offsets(fetch_node &f) { + assert(f.src.size() == 8); + + fetch_node *n = sh.create_fetch(); + + n->bc.set_op(FETCH_OP_SET_TEXTURE_OFFSETS); + + copy_fetch_src(*n, f, 4); + + f.insert_before(n); +} + void bc_finalizer::finalize_fetch(fetch_node* f) { int reg = -1; @@ -483,6 +498,8 @@ void bc_finalizer::finalize_fetch(fetch_node* f) { src_count = 1; } else if (flags & FF_USEGRAD) { emit_set_grad(f); + } else if (flags & FF_USE_TEXTURE_OFFSETS) { + emit_set_texture_offsets(*f); } for (unsigned chan = 0; chan < src_count; ++chan) { diff --git a/src/gallium/drivers/r600/sb/sb_bc_parser.cpp b/src/gallium/drivers/r600/sb/sb_bc_parser.cpp index 7181e27acf0..346ccc9dbc5 100644 --- a/src/gallium/drivers/r600/sb/sb_bc_parser.cpp +++ b/src/gallium/drivers/r600/sb/sb_bc_parser.cpp @@ -520,7 +520,7 @@ int bc_parser::decode_fetch_clause(cf_node* cf) { int bc_parser::prepare_fetch_clause(cf_node *cf) { - vvec grad_v, grad_h; + vvec grad_v, grad_h, texture_offsets; for (node_iterator I = cf->begin(), E = cf->end(); I != E; ++I) { @@ -538,7 +538,7 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) { sh->uses_gradients = true; } - if (flags & FF_SETGRAD) { + if (flags & (FF_SETGRAD | FF_SET_TEXTURE_OFFSETS)) { vvec *grad = NULL; @@ -549,6 +549,9 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) { case FETCH_OP_SET_GRADIENTS_H: grad = &grad_h; break; + case FETCH_OP_SET_TEXTURE_OFFSETS: + grad = &texture_offsets; + break; default: assert(!"unexpected SET_GRAD instruction"); return -1; @@ -568,11 +571,15 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) { (*grad)[s] = sh->get_const_value(1.0f); } } else { - + // Fold source values for instructions with hidden target values in to the instructions + // using them. The set instructions are later re-emitted by bc_finalizer if (flags & FF_USEGRAD) { n->src.resize(12); std::copy(grad_v.begin(), grad_v.end(), n->src.begin() + 4); std::copy(grad_h.begin(), grad_h.end(), n->src.begin() + 8); + } else if (flags & FF_USE_TEXTURE_OFFSETS) { + n->src.resize(8); + std::copy(texture_offsets.begin(), texture_offsets.end(), n->src.begin() + 4); } else { n->src.resize(4); } diff --git a/src/gallium/drivers/r600/sb/sb_pass.h b/src/gallium/drivers/r600/sb/sb_pass.h index c955656449f..812d14a9d96 100644 --- a/src/gallium/drivers/r600/sb/sb_pass.h +++ b/src/gallium/drivers/r600/sb/sb_pass.h @@ -713,6 +713,9 @@ public: void cf_peephole(); +private: + void copy_fetch_src(fetch_node &dst, fetch_node &src, unsigned arg_start); + void emit_set_texture_offsets(fetch_node &f); }; |