summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r600/sb
diff options
context:
space:
mode:
authorGlenn Kennard <[email protected]>2014-08-17 22:26:19 +0200
committerMarek Olšák <[email protected]>2014-08-19 16:30:13 +0200
commitdfa10ed2640a350a84e6e31edd22560155cd5016 (patch)
tree1fe5c1378d50b757ab4446de2944239bd092e451 /src/gallium/drivers/r600/sb
parentef1cf69cd34701ea005a244909c71357a3dddb06 (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.cpp119
-rw-r--r--src/gallium/drivers/r600/sb/sb_bc_parser.cpp13
-rw-r--r--src/gallium/drivers/r600/sb/sb_pass.h3
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);
};