https://bugs.winehq.org/show_bug.cgi?id=46304
Bug ID: 46304 Summary: Fog handling seems to be off in Prince of Persia Product: Wine Version: 3.21 Hardware: x86 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: directx-d3d Assignee: wine-bugs@winehq.org Reporter: gw.fossdev@gmail.com Distribution: ---
Created attachment 63028 --> https://bugs.winehq.org/attachment.cgi?id=63028 apitrace dump of frame that contains shader:
Hello, I came across this by trying out Prince of Persia with virgl ad a driver and comparing it to the host. Initially I thought it was a virgl bug, but it seems to be proper wine where things go wrong:
Here are my findings:
When I run "wine PrinceOfPersia.exe" on the host (r600) the game is playable but when run with the virgl driver there is not contrast in the images. However, a apitrace created with virgl as driver and replayed on host also renders wrong, where a apitrace recorded on the host and run via virgl renders correctly (only op-side down, because virgl doesn't support GL_ARB_clip_control, but disabling this extension when recording the apitrace makes it possible to get exactly the same output like when run on the r600 host.
The difference between the two runs in the apitrace is that when run on r600 I get a vertex shader that does:
R6.w = (R6.w * vs_c[20].z); R6.w = (vs_c[20].z + -R6.w); vs_out[11].x = (vs_c[16].y + -R6.w); vs_out[10].xyzw = (R8.xyzw); setup_vs_output(vs_out);
The same shader created via virgl does:
R6.w = (vs_c[16].y + -R6.w); vs_out[11].x = (R6.w * vs_c[20].z); vs_out[10].xyzw = (R8.xyzw); setup_vs_output(vs_out); ffp_varying_fogcoord = gl_Position.z; gl_Position.y = gl_Position.y * pos_fixup.y;
The value ffp_varying_fogcoord is not assigned a value with the r600 version. However, the following fragment shader uses this value in both cases:
float fog = (ffp_fog.end - ffp_varying_fogcoord) * ffp_fog.scale; ps_out[0].xyz = mix(ffp_fog.color.xyz, ps_out[0].xyz, clamp(fog, 0.0, 1.0));
In the r600 version ffp_fog.end=0 and ffp_fog.scale=-1, and I assume that this results in clamp(fog, 0.0, 1.0) returning 1.0, and in the scene the fog effect seems to be generated differently. In the virgl version the values are ffp_fog.end=1 and ffp_fog.scale=1, and I can only assume that gl_Position too large so that clamp(fog, 0.0, 1.0) returns very small values (or even 0) and the scene gets rendered in the fog colour overlayed by some post processing effects.
I have not yet investigated why wine creates different code path for the two drivers, I guess that it depends on some extension(s) that may or may not be available.
The initial but report for virglrenderer can be found here: https://gitlab.freedesktop.org/virgl/virglrenderer/issues/62