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 /src/gallium/drivers/r600/sb | |
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]>
Diffstat (limited to 'src/gallium/drivers/r600/sb')
-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 |
3 files changed, 81 insertions, 54 deletions
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); }; |