summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2018-01-10 04:30:23 +0000
committerDave Airlie <[email protected]>2018-01-18 03:37:42 +0000
commit5002dd40520deba025d81c824d41e292db344a7b (patch)
tree97c5e2468901973ed8b22d7e8b989c7af0007c70 /src/gallium/drivers
parent046cf68cadd04a1e1eb89476614c334ac702f0ce (diff)
r600/sb: add gcm support to avoid clause between lds read/queue read
You have to schedule LDS_READ_RET _, x and MOV reg, LDS_OQ_A_POP in the same basic block/clause. This makes sure once we've issues and MOV we don't add another block until we balance it with an LDS read. Acked-By: Roland Scheidegger <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/r600/sb/sb_gcm.cpp15
-rw-r--r--src/gallium/drivers/r600/sb/sb_pass.h4
2 files changed, 17 insertions, 2 deletions
diff --git a/src/gallium/drivers/r600/sb/sb_gcm.cpp b/src/gallium/drivers/r600/sb/sb_gcm.cpp
index fbebe3427d4..7776a10fc86 100644
--- a/src/gallium/drivers/r600/sb/sb_gcm.cpp
+++ b/src/gallium/drivers/r600/sb/sb_gcm.cpp
@@ -366,6 +366,9 @@ void gcm::bu_sched_bb(bb_node* bb) {
continue;
}
+ if (sq != SQ_ALU && outstanding_lds_oq)
+ continue;
+
if (!bu_ready_next[sq].empty())
bu_ready[sq].splice(bu_ready[sq].end(), bu_ready_next[sq]);
@@ -388,7 +391,7 @@ void gcm::bu_sched_bb(bb_node* bb) {
}
// simple heuristic to limit register pressure,
- if (sq == SQ_ALU && live_count > rp_threshold &&
+ if (sq == SQ_ALU && live_count > rp_threshold && !outstanding_lds_oq &&
(!bu_ready[SQ_TEX].empty() ||
!bu_ready[SQ_VTX].empty() ||
!bu_ready_next[SQ_TEX].empty() ||
@@ -423,6 +426,12 @@ void gcm::bu_sched_bb(bb_node* bb) {
check_alu_ready_count(24))
break;
+
+ if (sq == SQ_ALU && n->consumes_lds_oq() &&
+ (bu_ready[SQ_TEX].size() || bu_ready[SQ_VTX].size() || bu_ready[SQ_GDS].size())) {
+ GCM_DUMP( sblog << "switching scheduling due to lds op\n"; );
+ break;
+ }
bu_ready[sq].pop_front();
if (sq != SQ_CF) {
@@ -513,6 +522,10 @@ void gcm::bu_schedule(container_node* c, node* n) {
assert(op_map[n].bottom_bb == bu_bb);
+ if (n->produces_lds_oq())
+ outstanding_lds_oq--;
+ if (n->consumes_lds_oq())
+ outstanding_lds_oq++;
bu_release_defs(n->src, true);
bu_release_defs(n->dst, false);
diff --git a/src/gallium/drivers/r600/sb/sb_pass.h b/src/gallium/drivers/r600/sb/sb_pass.h
index e878f8c70ca..b5818039c2e 100644
--- a/src/gallium/drivers/r600/sb/sb_pass.h
+++ b/src/gallium/drivers/r600/sb/sb_pass.h
@@ -223,6 +223,7 @@ class gcm : public pass {
sched_queue ready;
sched_queue ready_above;
+ unsigned outstanding_lds_oq;
container_node pending;
struct op_info {
@@ -263,7 +264,8 @@ public:
gcm(shader &sh) : pass(sh),
bu_ready(), bu_ready_next(), bu_ready_early(),
- ready(), op_map(), uses(), nuc_stk(1), ucs_level(),
+ ready(), outstanding_lds_oq(),
+ op_map(), uses(), nuc_stk(1), ucs_level(),
bu_bb(), pending_defs(), pending_nodes(), cur_sq(),
live(), live_count(), pending_exec_mask_update() {}