r600/sb: add gcm support to avoid clause between lds read/queue read
authorDave Airlie <airlied@redhat.com>
Wed, 10 Jan 2018 04:30:23 +0000 (04:30 +0000)
committerDave Airlie <airlied@redhat.com>
Thu, 18 Jan 2018 03:37:42 +0000 (03:37 +0000)
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 <sroland@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/sb/sb_gcm.cpp
src/gallium/drivers/r600/sb/sb_pass.h

index fbebe3427d4489559eea3f4df8d09b3e41a369b1..7776a10fc860dbb5467135afd446c63b7a558075 100644 (file)
@@ -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);
 
index e878f8c70ca63b4000ec26b8c163ab98477637a0..b5818039c2e339691cd3cd4e55835ea5f5bd702d 100644 (file)
@@ -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() {}