xemu-project / xemu

Original Xbox Emulator for Windows, macOS, and Linux (Active Development)
https://xemu.app
Other
2.73k stars 275 forks source link

Counter Terrorist Special Forces: loading animation corrupts title screen #665

Open abaire opened 2 years ago

abaire commented 2 years ago

Title

https://xemu.app/titles/48500002/#Counter-Terrorist-Special-Forces-Fire-for-Effect

Bug Description

Just after the initial splash screen, a green rotating indicator is displayed in the lower left corner. In xemu, this explodes to cover the entire screen:

Screenshot_20220119_134719

Expected Behavior

The animation should not cover the screen: loading_indicator

and should fade into the entry screen:

loaded_screen

xemu Version

Latest master:

Version: 0.6.2-52-gb3f56db428 Branch: master Commit: b3f56db428f7796345fb39907a6a87ccf82336c2 Date: Wed Jan 19 09:52:45 PM UTC 2022

System Information

OS: Kubuntu 21.04 - 5.11.0-38-generic CPU: Core i7-6700K @ 4GHz GPU: NVIDIA GeForce GTX 1070 GPU Driver: 4.6.0 NVIDIA 470.74

Additional Context

No response

abaire commented 2 years ago

The vertex shader seems to be interesting, it appears to "misuse" the input registers (v1 looks like it's used as diffuse instead of weight, v2 is used as tex0 instead of normal (lighting is disabled))

It also sets the z coordinate with MUL(oPos,z, R12.z, c[58].z); but it looks like constant[58] is never loaded (I see a block of loads at 0xC and 0x21 but I think the last load would be at c[34]).

abaire commented 2 years ago

It looks like it gets set to 0x4B7FFFFF (16777215.0) which is interesting as it's also the max clip depth. The game is using z24s8 at this point in the rendering.

abaire commented 2 years ago

Stepping through the draw commands it actually looks like it's rendering the spiral loader into the backbuffer properly, but then it's obliterated, possibly by stale info in the framebuffer?

Screenshot_20220119_154440

abaire commented 2 years ago

Looking into the actual vertex data, the program sets z to 0 for all vertices (so the c[58].z is meaningless) and interestingly sets a mix of infinity, 0.0, and various reasonable values for w.

(Drawn as a triangle strip)

pos[0]: 99.059753 421.075928 0.000000 inf
pos[1]: 97.377518 427.886261 0.000000 inf
pos[2]: 88.875854 420.005554 0.000000 inf
pos[3]: 87.866516 424.091766 0.000000 inf
pos[4]: 87.866516 424.091766 0.000000 0.000000
pos[5]: 86.329880 417.062042 0.000000 0.000000
pos[6]: 86.329880 417.062042 0.000000 inf
pos[7]: 85.488762 413.656860 0.000000 inf
pos[8]: 81.237930 417.597229 0.000000 inf
pos[9]: 80.733253 415.554108 0.000000 inf
pos[10]: 80.733253 415.554108 0.000000 0.000000
pos[11]: 79.964935 419.068970 0.000000 0.000000
pos[12]: 79.964935 419.068970 0.000000 inf
pos[13]: 79.544380 420.771576 0.000000 inf
pos[14]: 77.418961 418.801392 0.000000 inf
pos[15]: 77.166626 419.822937 0.000000 inf
pos[16]: 77.166626 419.822937 0.000000 0.980578
pos[17]: 96.097717 430.615265 0.000000 0.000000
pos[18]: 96.097717 430.615265 0.000000 inf
pos[19]: 91.937325 436.263428 0.000000 inf
...

This appears to trigger the break, if I change the shader code to blindly force oPos.w to 1.0 it renders something that looks more correct, though there's no loading text and the game appears to crash before reaching the point where the loading text would be hidden and the 3d scene would be rendered.

abaire commented 2 years ago

Setting up a trivial test case, it's not the inf or 0 or even positive w values that are the problem, it's the negative w's. On hardware these render correctly, on xemu they create geometry off screen (in this particular data set).

Test case HW results

abaire commented 2 years ago

Note, this may be due to the same underlying cause as #174

(It was not, 174 is due to lack of special casing of stride=0 vertex attributes)

Triticum0 commented 2 years ago

When i tested this game back in April on my AMD GPU there was an issue with some of the text causing artifacts in menu and Fmv. Is is this still the case? 3 2

Triticum0 commented 2 years ago

Also this corruption also affect the in-game HUD 1

abaire commented 2 years ago

At the moment I can't seem to get that far, for me the game never gets past the loading indicator (it never even shows the "Loading in progress" text). I can hack around the graphical corruption (in a way that breaks other games) but never see anything more than the green spinner.

If you can re-test with the latest xemu and get past the loading screen it might indicate that the dump I made is bad and needs to be re-dumped (though it seems to work fine running off the HDD on hardware) .

abaire commented 2 years ago

This only seems to affect vertices rendered as triangle strips; if I send the same vertices as discrete triangles they render as expected.

abaire commented 2 years ago

And digging some more, it looks like the hardware actually does render the vertices, it just discards them in the pixel shader.

Test Results

abaire commented 2 years ago

So far I can only replicate this in cases where the negative w vertex is stacked top of the previous vertex (e.g., intentionally degenerate triangles).

If I perturb it slightly in any direction other than the camera view axis, both xemu and the xbox will fill the resultant clipped surface (that runs up to the camera position).

If I perturb it in the camera view axis, xemu will fill a sliver of the triangle, xbox does not seem to.

abaire commented 2 years ago

At this point I suspect some precision/rounding issue.

I've checked with RenderDoc and implemented the (relevant part of the) vertex shader in Python and the output vertices look correct. In particular, the last non-negative vertex is projected to (0, 0.666..., -1, 1) and the negative vertex to (0, -0.0666..., 0.1, -0.1). Doing the perspective divide, these should both map to (0.0, 0.666..., -1.0, 1.0), creating a degenerate triangle that should not result in any fragment filling.

Interestingly, in RenderDoc's mesh view, the output matches the xbox hardware until the camera is slightly tweaked, at which point the broken red triangle is displayed.

abaire commented 2 years ago

Maybe not, setting the test vertex's w to -1.0 still results in incorrect behavior.

Triticum0 commented 2 years ago

FYI: This issue properly related as it cause exploding geometry in menus. #537

Triticum0 commented 2 years ago

@abaire I retested and got this disc is dirty or damage so it's probably a regression.

Triticum0 commented 2 years ago

Test it before the render scale was implemented that probably what broke the game

Triticum0 commented 2 years ago

@abaire this game now goes in-game xemu-2022-06-03-00-47-04

abaire commented 2 years ago

@Triticum0 confirmed that I can get in game with the latest release as well. The vertex explosion on the loading screen still happens and the pgraph tests I wrote while diagnosing this still fail in the same way.