Bug 91124

Summary: Civilization V (in Wine) has rendering issues: text missing, menu bar corrupted
Product: Mesa Reporter: Béla Gyebrószki <gyebro69>
Component: Drivers/DRI/nouveauAssignee: Nouveau Project <nouveau>
Status: RESOLVED FIXED QA Contact: Nouveau Project <nouveau>
Severity: normal    
Priority: medium    
Version: git   
Hardware: Other   
OS: All   
URL: http://store.steampowered.com/app/8930/
Whiteboard:
i915 platform: i915 features:
Attachments: shader that triggers bug

Description Béla Gyebrószki 2015-06-27 07:53:42 UTC
Civilization V when running in Wine has the following issues on my system with nouveau:
all text is missing from game (in the menus, on the loading screens and in mid-game)
when starting a game from the menu the upper menu bar that contains menu options and icons is corrupted (terrain and units are rendered properly though)

The problem is not present:
- with the Nvidia binary drivers (340.76)
- when using the software renderer (LIBGL_ALWAYS_SOFTWARE=1)
- when starting the game with NV50_PROG_OPTIMIZE=0 or NV50_PROG_OPTIMIZE=1

See this screenshot for comparison:
http://imgur.com/pzpPgNL

I created a trace with apitrace and the problem is reproducible with that on my system (uncompressed 366 MB):
https://drive.google.com/open?id=0B-tTbLKBl-tON09yaE14eEkwb28&authuser=0

Demo version is available on Steam (~4 GB download size):
http://store.steampowered.com/app/8930/

Fedora 22 32-bit
Mesa 10.6-branchpoint-684-g556dd4a
VGA compatible controller: NVIDIA Corporation G92 [GeForce GTS 250] (rev a2) (prog-if 00 [VGA controller])
Kernel 4.0.5-300.fc22.i686+PAE
xorg-x11-server-Xorg-1.17.2-1.fc22.i686
libdrm-2.4.61-3.fc22.i686
Comment 1 Ilia Mirkin 2015-06-30 08:19:01 UTC
Created attachment 116817 [details]
shader that triggers bug

The attached shader appears to trigger an issue in the FlatteningPass. Specifically the resulting code looks like

00000198: a0036003 00000000     joinat 0x1b0
000001a0: b00005fd 600187c8     set $c0 # ge f32 $r2 $r0
000001a8: 1000020d 0403c100     (e $c0) mov b32 $r3 $r1
000001b0: 10000801 2400c780   B ld $r0 b32 c0[0x10]

That joinat shouldn't be there at all. This is a bit tricky, since pre-RA, the code looks like

 60: joinat BB:5 (0)
 61: set u8 %c259 ge f32 %r215 %r255 (0)
 62: eq %c259 bra BB:4 (0)
BB:3 (1 instructions) - idom = BB:12, df = { BB:5 }
 -> BB:5 (forward)
 63: bra BB:5 (0)
BB:4 (1 instructions) - idom = BB:12, df = { BB:5 }
 -> BB:5 (forward)
 64: bra BB:5 (0)
BB:5 (14 instructions) - idom = BB:12, df = { BB:10 }
 -> BB:7 (tree)
 -> BB:6 (tree)
 65: phi u32 %r261 %r254 %r252 (0)
 66: join (0)

and the (e $c0) mov ... is actually generated from the phi node (since it creates constraint moves into BB:3/4. Post-RA but pre-FlatteningPass, this looks like

 64: joinat BB:5 (0)
 65: set u8 $c0 ge f32 $r2 $r0 (0)
 66: eq $c0 bra BB:4 (0)
BB:3 (1 instructions) - idom = BB:12, df = { BB:5 }
 -> BB:5 (forward)
 67: bra BB:5 (0)
BB:4 (2 instructions) - idom = BB:12, df = { BB:5 }
 -> BB:5 (forward)
 68: mov u32 $r3 $r1 (0)
 69: bra BB:5 (0)
BB:5 (13 instructions) - idom = BB:12, df = { BB:10 }
 -> BB:7 (tree)
 -> BB:6 (tree)
 70: join (0)

Will have to understand the FlatteningPass better before I can figure out what's wrong though.
Comment 2 Ilia Mirkin 2015-07-01 06:10:00 UTC
I believe the following patch resolves the issue:

diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
index 51b9225..fa8ee07 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
@@ -332,6 +332,9 @@ BasicBlock::splitBefore(Instruction *insn, bool attach)
    BasicBlock *bb = new BasicBlock(func);
    assert(!insn || insn->op != OP_PHI);
 
+   bb->joinAt = joinAt;
+   joinAt = NULL;
+
    splitCommon(insn, bb, attach);
    return bb;
 }
Comment 3 Béla Gyebrószki 2015-07-01 06:47:56 UTC
(In reply to Ilia Mirkin from comment #2)
> I believe the following patch resolves the issue:
> 
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
> b/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
> index 51b9225..fa8ee07 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
> @@ -332,6 +332,9 @@ BasicBlock::splitBefore(Instruction *insn, bool attach)
>     BasicBlock *bb = new BasicBlock(func);
>     assert(!insn || insn->op != OP_PHI);
>  
> +   bb->joinAt = joinAt;
> +   joinAt = NULL;
> +
>     splitCommon(insn, bb, attach);
>     return bb;
>  }

The patch works very well, it fixes the reported issues in the game, thank you.
Comment 4 Ilia Mirkin 2015-07-01 07:18:49 UTC
Pushed out as

commit 5dcb28c3d26828ed1b0e2bd5a0589c5baab04b85
Author: Ilia Mirkin <imirkin@alum.mit.edu>
Date:   Wed Jul 1 02:11:39 2015 -0400

    nv50/ir: copy joinAt when splitting both before and after

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.