@@ -4312,6 +4312,7 @@ SchedDataCalculatorGM107::insertBarriers(BasicBlock *bb)
43124312 Instruction *insn, *next;
43134313 BitSet bars (6 , 1 );
43144314 int bar_id;
4315+ int texBar = -1 ; // shared texture-pipe counter barrier
43154316
43164317 for (insn = bb->getEntry (); insn != NULL ; insn = next) {
43174318 Instruction *usei = NULL , *defi = NULL ;
@@ -4325,7 +4326,8 @@ SchedDataCalculatorGM107::insertBarriers(BasicBlock *bb)
43254326 if (insn->serial >= it->usei ->serial ) {
43264327 int wr = getWrDepBar (it->insn );
43274328 emitWtDepBar (insn, wr);
4328- bars.clr (wr); // free barrier
4329+ if (wr != texBar)
4330+ bars.clr (wr); // free barrier (texture counter stays reserved)
43294331 it = live_uses.erase (it);
43304332 continue ;
43314333 }
@@ -4355,11 +4357,23 @@ SchedDataCalculatorGM107::insertBarriers(BasicBlock *bb)
43554357 // completing before this insn.
43564358 usei = findFirstUse (insn);
43574359
4358- // Allocate and emit a new barrier.
4359- bar_id = bars.findFreeRange (1 );
4360- if (bar_id == -1 )
4361- bar_id = 5 ;
4362- bars.set (bar_id);
4360+ // Allocate and emit a new barrier. Textures share one counter barrier
4361+ // (consumers wait for it to drain) because a per-texture write barrier
4362+ // is unreliable when the texture is dual-issued.
4363+ if (targ->getOpClass (insn->op ) == OPCLASS_TEXTURE ) {
4364+ if (texBar == -1 ) {
4365+ texBar = bars.findFreeRange (1 );
4366+ if (texBar == -1 )
4367+ texBar = 5 ;
4368+ bars.set (texBar);
4369+ }
4370+ bar_id = texBar;
4371+ } else {
4372+ bar_id = bars.findFreeRange (1 );
4373+ if (bar_id == -1 )
4374+ bar_id = 5 ;
4375+ bars.set (bar_id);
4376+ }
43634377 emitWrDepBar (insn, bar_id);
43644378 if (usei)
43654379 live_uses.push_back (LiveBarUse (insn, usei));
@@ -4494,6 +4508,50 @@ SchedDataCalculatorGM107::visit(BasicBlock *bb)
44944508#endif
44954509 }
44964510
4511+ // A barrier issued from the second dual-issue slot is not honored by the
4512+ // texture unit, so a co-issued texture must set no barrier:
4513+ // - its write (result) barrier is offloaded to the shared texture counter,
4514+ // which a following texture keeps live (textures retire in order, so the
4515+ // counter wait covers this result too);
4516+ // - its read (coordinate) barrier cannot be offloaded, so a texture that
4517+ // needs one is un-dual-issued back into its own slot.
4518+ {
4519+ Instruction *prevInsn = NULL ;
4520+ for (Instruction *t = bb->getEntry (); t != NULL ; prevInsn = t, t = t->next ) {
4521+ if (targ->getOpClass (t->op ) != OPCLASS_TEXTURE )
4522+ continue ;
4523+ if (!prevInsn || getStall (prevInsn) != 0 )
4524+ continue ; // not the second slot of a dual-issue
4525+
4526+ // Coordinate WAR (read barrier) can't be covered from the second slot.
4527+ if (getRdDepBar (t) != 7 ) {
4528+ prevInsn->sched = (prevInsn->sched & ~0x1f ) | 0x1 ; // stall 1, no yield
4529+ continue ;
4530+ }
4531+
4532+ int wb = getWrDepBar (t);
4533+ if (wb == 7 )
4534+ continue ;
4535+ bool covered = false ;
4536+ Instruction *jprev = t;
4537+ for (Instruction *j = t->next ; j != NULL ; jprev = j, j = j->next ) {
4538+ if (getWtDepBar (j) & (1 << wb))
4539+ break ; // counter drained before a covering texture
4540+ // The covering texture must keep its barrier, i.e. not be co-issued
4541+ // itself (a co-issued texture's barrier is dropped below).
4542+ if (targ->getOpClass (j->op ) == OPCLASS_TEXTURE &&
4543+ getWrDepBar (j) != 7 && getStall (jprev) != 0 ) {
4544+ covered = true ;
4545+ break ;
4546+ }
4547+ }
4548+ if (covered)
4549+ t->sched |= 0xe0 ; // drop write dep barrier (counter covers it)
4550+ else
4551+ prevInsn->sched = (prevInsn->sched & ~0x1f ) | 0x1 ; // no cover: own slot
4552+ }
4553+ }
4554+
44974555 if (!insn)
44984556 return true ;
44994557 commitInsn (insn, cycle);
0 commit comments