summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r600/sb
diff options
context:
space:
mode:
authorGlenn Kennard <[email protected]>2015-04-07 03:00:20 +0200
committerDave Airlie <[email protected]>2015-04-08 08:18:35 +1000
commitf2947807c8c7eae4b98eb37263b8a1d9ebbcafb5 (patch)
treebd7e67b69ab05894656392738586c8383b72ce8a /src/gallium/drivers/r600/sb
parent06bb68da4a58403e678b51511e40a7f752dfc046 (diff)
r600g/sb: Enable SB for geometry shaders
Add SV_GEOMETRY_EMIT special variable type to track the implicit dependencies between CUT/EMIT_VERTEX/MEM_RING instructions so GCM/scheduler doesn't reorder them. Mark emit instructions as unkillable so DCE doesn't eat them. Enable only for evergreen/cayman as there are a few unexplained GS piglit regressions on R6xx/R7xx with SB enabled otherwise. Signed-off-by: Glenn Kennard <[email protected]> Reviewed-by: Dave Airlie <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium/drivers/r600/sb')
-rw-r--r--src/gallium/drivers/r600/sb/sb_bc_dump.cpp2
-rw-r--r--src/gallium/drivers/r600/sb/sb_bc_finalize.cpp2
-rw-r--r--src/gallium/drivers/r600/sb/sb_bc_parser.cpp25
-rw-r--r--src/gallium/drivers/r600/sb/sb_core.cpp5
-rw-r--r--src/gallium/drivers/r600/sb/sb_dump.cpp4
-rw-r--r--src/gallium/drivers/r600/sb/sb_ir.h6
-rw-r--r--src/gallium/drivers/r600/sb/sb_ra_init.cpp4
-rw-r--r--src/gallium/drivers/r600/sb/sb_sched.cpp2
-rw-r--r--src/gallium/drivers/r600/sb/sb_valtable.cpp1
9 files changed, 43 insertions, 8 deletions
diff --git a/src/gallium/drivers/r600/sb/sb_bc_dump.cpp b/src/gallium/drivers/r600/sb/sb_bc_dump.cpp
index 6f6a57e2647..5232782791d 100644
--- a/src/gallium/drivers/r600/sb/sb_bc_dump.cpp
+++ b/src/gallium/drivers/r600/sb/sb_bc_dump.cpp
@@ -448,7 +448,7 @@ void bc_dump::dump(fetch_node& n) {
s << " FWQ";
if (ctx.is_egcm() && n.bc.resource_index_mode)
s << " RIM:SQ_CF_INDEX_" << n.bc.resource_index_mode;
- if (ctx.is_egcm() && n.bc.resource_index_mode)
+ if (ctx.is_egcm() && n.bc.sampler_index_mode)
s << " SID:SQ_CF_INDEX_" << n.bc.sampler_index_mode;
s << " UCF:" << n.bc.use_const_fields
diff --git a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp
index 08b7d77f1a4..8c2cd1460e5 100644
--- a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp
+++ b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp
@@ -290,7 +290,7 @@ void bc_finalizer::finalize_alu_group(alu_group_node* g, node *prev_node) {
value *d = n->dst.empty() ? NULL : n->dst[0];
if (d && d->is_special_reg()) {
- assert(n->bc.op_ptr->flags & AF_MOVA);
+ assert((n->bc.op_ptr->flags & AF_MOVA) || d->is_geometry_emit());
d = NULL;
}
diff --git a/src/gallium/drivers/r600/sb/sb_bc_parser.cpp b/src/gallium/drivers/r600/sb/sb_bc_parser.cpp
index 08e7f5c36c3..4879c036f9f 100644
--- a/src/gallium/drivers/r600/sb/sb_bc_parser.cpp
+++ b/src/gallium/drivers/r600/sb/sb_bc_parser.cpp
@@ -135,6 +135,16 @@ int bc_parser::parse_decls() {
}
}
+ // GS inputs can add indirect addressing
+ if (sh->target == TARGET_GS) {
+ if (pshader->num_arrays) {
+ for (unsigned i = 0; i < pshader->num_arrays; ++i) {
+ r600_shader_array &a = pshader->arrays[i];
+ sh->add_gpr_array(a.gpr_start, a.gpr_count, a.comp_mask);
+ }
+ }
+ }
+
if (sh->target == TARGET_VS || sh->target == TARGET_ES)
sh->add_input(0, 1, 0x0F);
else if (sh->target == TARGET_GS) {
@@ -720,6 +730,16 @@ int bc_parser::prepare_ir() {
c->flags |= NF_DONT_HOIST | NF_DONT_MOVE;
}
+ if (flags & CF_EMIT) {
+ // Instruction implicitly depends on prior [EMIT_][CUT]_VERTEX
+ c->src.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
+ c->dst.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
+ if (sh->target == TARGET_ES) {
+ // For ES shaders this is an export
+ c->flags |= NF_DONT_KILL;
+ }
+ }
+
if (!burst_count--)
break;
@@ -736,6 +756,11 @@ int bc_parser::prepare_ir() {
c->bc.end_of_program = eop;
+ } else if (flags & CF_EMIT) {
+ c->flags |= NF_DONT_KILL | NF_DONT_HOIST | NF_DONT_MOVE;
+
+ c->src.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
+ c->dst.push_back(sh->get_special_value(SV_GEOMETRY_EMIT));
}
}
diff --git a/src/gallium/drivers/r600/sb/sb_core.cpp b/src/gallium/drivers/r600/sb/sb_core.cpp
index 7db80082b60..afea8188f1c 100644
--- a/src/gallium/drivers/r600/sb/sb_core.cpp
+++ b/src/gallium/drivers/r600/sb/sb_core.cpp
@@ -189,7 +189,10 @@ int r600_sb_bytecode_process(struct r600_context *rctx,
sh->set_undef(sh->root->live_before);
- SB_RUN_PASS(if_conversion, 1);
+ // if conversion breaks the dependency tracking between CF_EMIT ops when it removes
+ // the phi nodes for SV_GEOMETRY_EMIT. Just disable it for GS
+ if (sh->target != TARGET_GS)
+ SB_RUN_PASS(if_conversion, 1);
// if_conversion breaks info about uses, but next pass (peephole)
// doesn't need it, so we can skip def/use update here
diff --git a/src/gallium/drivers/r600/sb/sb_dump.cpp b/src/gallium/drivers/r600/sb/sb_dump.cpp
index b2130a48fa6..d6051704c15 100644
--- a/src/gallium/drivers/r600/sb/sb_dump.cpp
+++ b/src/gallium/drivers/r600/sb/sb_dump.cpp
@@ -354,7 +354,9 @@ void dump::dump_op(node &n, const char *name) {
"WRITE_IND_ACK"};
sblog << " " << exp_type[c->bc.type] << " " << c->bc.array_base
<< " ES:" << c->bc.elem_size;
- has_dst = false;
+ if (!(c->bc.op_ptr->flags & CF_EMIT)) {
+ has_dst = false;
+ }
}
}
diff --git a/src/gallium/drivers/r600/sb/sb_ir.h b/src/gallium/drivers/r600/sb/sb_ir.h
index 711c2eb9e35..560a4a9b284 100644
--- a/src/gallium/drivers/r600/sb/sb_ir.h
+++ b/src/gallium/drivers/r600/sb/sb_ir.h
@@ -41,7 +41,8 @@ enum special_regs {
SV_ALU_PRED = 128,
SV_EXEC_MASK,
SV_AR_INDEX,
- SV_VALID_MASK
+ SV_VALID_MASK,
+ SV_GEOMETRY_EMIT
};
class node;
@@ -506,6 +507,9 @@ public:
bool is_AR() {
return is_special_reg() && select == sel_chan(SV_AR_INDEX, 0);
}
+ bool is_geometry_emit() {
+ return is_special_reg() && select == sel_chan(SV_GEOMETRY_EMIT, 0);
+ }
node* any_def() {
assert(!(def && adef));
diff --git a/src/gallium/drivers/r600/sb/sb_ra_init.cpp b/src/gallium/drivers/r600/sb/sb_ra_init.cpp
index e53aba540de..95b92905f59 100644
--- a/src/gallium/drivers/r600/sb/sb_ra_init.cpp
+++ b/src/gallium/drivers/r600/sb/sb_ra_init.cpp
@@ -707,7 +707,7 @@ void ra_split::split_vec(vvec &vv, vvec &v1, vvec &v2, bool allow_swz) {
assert(!o->is_dead());
- if (o->is_undef())
+ if (o->is_undef() || o->is_geometry_emit())
continue;
if (allow_swz && o->is_float_0_or_1())
@@ -751,7 +751,7 @@ void ra_split::split_vector_inst(node* n) {
// src vectors 1 (src[4-7] and 2 (src[8-11])
unsigned nvec = n->src.size() >> 2;
- assert(nvec << 2 == n->src.size());
+ assert(nvec << 2 <= n->src.size());
for (unsigned nv = 0; nv < nvec; ++nv) {
vvec sv, tv, nsrc(4);
diff --git a/src/gallium/drivers/r600/sb/sb_sched.cpp b/src/gallium/drivers/r600/sb/sb_sched.cpp
index 63e74640687..4248a3fd30a 100644
--- a/src/gallium/drivers/r600/sb/sb_sched.cpp
+++ b/src/gallium/drivers/r600/sb/sb_sched.cpp
@@ -1463,7 +1463,7 @@ unsigned post_scheduler::try_add_instruction(node *n) {
value *d = a->dst.empty() ? NULL : a->dst[0];
if (d && d->is_special_reg()) {
- assert(a->bc.op_ptr->flags & AF_MOVA);
+ assert((a->bc.op_ptr->flags & AF_MOVA) || d->is_geometry_emit());
d = NULL;
}
diff --git a/src/gallium/drivers/r600/sb/sb_valtable.cpp b/src/gallium/drivers/r600/sb/sb_valtable.cpp
index 0d39e9c3f03..eb242b1c26f 100644
--- a/src/gallium/drivers/r600/sb/sb_valtable.cpp
+++ b/src/gallium/drivers/r600/sb/sb_valtable.cpp
@@ -55,6 +55,7 @@ sb_ostream& operator << (sb_ostream &o, value &v) {
case SV_ALU_PRED: o << "PR"; break;
case SV_EXEC_MASK: o << "EM"; break;
case SV_VALID_MASK: o << "VM"; break;
+ case SV_GEOMETRY_EMIT: o << "GEOMETRY_EMIT"; break;
default: o << "???specialreg"; break;
}
break;