amonakov / primus

Low-overhead client-side GPU offloading
ISC License
216 stars 20 forks source link

Trackmania United Forever: Flickering on large parts of the screen [Regression] #97

Closed RalfJung closed 11 years ago

RalfJung commented 11 years ago

When starting Trackmania United Forever, large parts of the screen flicker, not showing anything useful. Only the bottom-left part of the screen (around 3/4 of the size for each axis) is displayed correctly.

Trackmania has worked all right in earlier versions. I did a regression test, with the following commit being identified as introducing this regression:

commit ef73dd1976125bdf108bef3226d87c21035c67a6 Author: Alexander Monakov amonakov@ispras.ru Date: Tue May 7 00:32:15 2013 +0400 Detect resizes in the background display thread

Interesting enough, this only happens if I use the native screen resolution

amonakov commented 11 years ago

That's under Wine, correct? Is it an OpenGL or a D3D application? Does it flicker with PRIMUS_SYNC={1,2} as well? If yes, it sounds like #92, in which case can you check if the workaround suggested there removes flickering?

I will also appreciate if you can provide an apitrace trace.

RalfJung commented 11 years ago

This is wine 1.5.30, correct. Trackmania uses D3D. Changing PRIMUS_SYNC does not help at all. The work-around does not change behaviour.

I will try to get apitrace running.

amonakov commented 11 years ago

Could you also check if enabling StrictDrawOrdering in Wine affects it (see http://wiki.winehq.org/UsefulRegistryKeys )?

RalfJung commented 11 years ago

StrictDrawOrdering does not change anything.

Should apitrace be nested inside optirun, or the other way around?

RalfJung commented 11 years ago

I added the following line in readback_work immediately after "width = di.width; height = di.height;":

primus_perf("Reiniting readback as %dx%d\n", width, height);

Running with PRIMUS_ERVBOSE=2, I get the following output:

primus: profiling: Reiniting readback as 1280x960
primus: profiling: readback: 39.6 fps, 38.7% app, 25.9% map, 35.4% wait
primus: profiling: display: 39.3 fps, 39.0% wait, 10.1% upload, 50.9% draw+swap
primus: profiling: Reiniting readback as 1280x960

My screen has size 1920x1200, so primus gets the size wrong. 1280x960 is pretty precisely the size of the part of the screen which still shows a correct image.

Btw, there's a free version of Trackmania called "Trackmania Nations Forever" - it will probably show the same problem.

amonakov commented 11 years ago

I see. display_work should call XGetGeometry after subscribing for events, otherwise a resize might be missed. Or, primus should call XSelectInput early enough

RalfJung commented 11 years ago

That seems to be the right track - the following patch fixes the issue: https://github.com/ralfjung-e/primus/commit/c1fe413abf57ea657b7e05d3cb253152c0d0e192 Probably there are more elegant ways to this^^

amonakov commented 11 years ago

Just note_geometry(ddpy, di.window, &di.width, &di.height); after XSelectInput should be sufficient. Also, please move note_geometry earlier instead of adding a declaration.

amonakov commented 11 years ago

TODO for myself: move uses of note_geometry into lookup_pbuffer.

RalfJung commented 11 years ago

Just note_geometry(ddpy, di.window, &di.width, &di.height); after XSelectInput should be sufficient. No, it's not. Instead of flickering, I now get a constant black background outside the 1280x960 area. I also wouldn't understand how it should help, as it does not propagate to the readback thread.

RalfJung commented 11 years ago

This patch fixes the problem as well: https://github.com/ralfjung-e/primus/commit/f3e10e1c17b96facbbff87253b00fc40806eeb56 However, I have no idea if this is safe multithreading-wise, as it's just writing these global di.width/height variables without any synchronisation.

amonakov commented 11 years ago

Just note_geometry(ddpy, di.window, &di.width, &di.height); (note di. everywhere) should be sufficient because readback_work waits for display_work to complete reinit before reading di.width.

edit: ... but not on the first iteration. Dammit :)