Viewing Issue Advanced Details
ID Category [?] Severity [?] Reproducibility Date Submitted Last Update
09311 Graphics Minor Always Nov 28, 2025, 18:44 1 day ago
Tester cuavas View Status Public Platform MAME (Official Binary)
Assigned To Resolution Open OS Windows (Arm)
Status [?] Acknowledged Driver
Version 0.283 Fixed in Version Build Arm64
Fixed in Git Commit Github Pull Request #
Summary 09311: ridgerac: Missing polygons on the stands
Description Although the severe glitches affecting Ridge Racer and other System 22 games in 09276 were fixed by seleuco, there are still some missing polygons on the stands in Ridge Racer, and possibly other places in System 22 games.

As with 09276, this seems to be an ARM-specific issue. It happens every time in clang/AArch64 builds, but doesn't happen in GCC/x86-64 builds.
Steps To Reproduce
Additional Information
Github Commit
Flags
Regression Version
Affected Sets / Systems ridgerac
Attached Files
png file icon 0000.png (142,936 bytes) Nov 28, 2025, 18:44 Uploaded by cuavas
cuavas
png file icon 0001.png (142,722 bytes) Nov 28, 2025, 18:45 Uploaded by cuavas
cuavas
png file icon 0002.png (142,755 bytes) Nov 28, 2025, 18:45 Uploaded by cuavas
cuavas
png file icon 0003.png (143,049 bytes) Nov 28, 2025, 18:45 Uploaded by cuavas
cuavas
png file icon 0004.png (143,622 bytes) Nov 28, 2025, 18:46 Uploaded by cuavas
cuavas
Relationships
There are no relationship linked to this issue.
Notes
7
User avatar
No.23850
cuavas
Administrator
Nov 28, 2025, 18:47
As shown in the screenshots, polygons appear and disappear, giving a kind of shimmering effect.
User avatar
No.23856
Robbbert
Moderator
Nov 28, 2025, 22:41
edited on: Nov 28, 2025, 22:41
Like last time, there probably won't be anyone running ARM to be able to confirm this. So, it's acknowledged.
User avatar
No.24818
gm_matthew
Tester
1 day ago
This issue also occurs on my clang/x86-64 build, so perhaps it's a clang-specific issue rather than an ARM-specific issue?
User avatar
No.24819
gm_matthew
Tester
1 day ago
It turns out the issue is due to Clang generating fused multiply-add instructions which mess up the backface culling calculation for quads that have two identical vertices (effectively making them triangles).

Code in question: https://github.com/mamedev/mame/blob/master/src/mame/namco/namcos22_v.cpp#L982

When vertices 0 and 1 are identical, the result of c1 should always be zero, and similarly when vertices 2 and 3 are identical, c2 should always be zero. However, the fused multiply-add operations are introducing errors that result in c1 or c2 not being zero when they should be; if the flawed result is positive, the quad is rendered even if it is facing away from the camera.

When using the compiler option -ffp-contract=off, the issue does not occur.
User avatar
No.24822
cuavas
Administrator
1 day ago
It doesn’t happen for me with clang x86-64. Are you using weird optimisation options or something? But how does an FMA introduce errors? An FMA involves one less rounding step, so it should reduce errors.
User avatar
No.24823
cuavas
Administrator
1 day ago
Also, if it’s relying on the intermediate results not being rounded, it should have never worked on x87, as x87 keeps intermediate results at 80-bit precision.

There’s #pragma STDC FP_CONTRACT OFF to disable contraction, but it’s still dangerous to rely on exact results for floating point maths.
User avatar
No.24824
gm_matthew
Tester
1 day ago
I was building with the flag -march=znver3 which must have been telling Clang that it's okay to generate fused operations. I thought I had tested without the flag but I guess I forgot to modify namcos22_v.cpp to force it to actually recompile. Anyway, the issue does not occur after recompiling without the -march=znver3 flag, though the issue still exists for ARM systems.

The use of fused operations can introduce errors because when it performs (v[0].z*v[1].y)-(v[0].y*v[1].z) it calculates one side first, rounds the result, and then subtracts that from the result of the other side which has not yet been rounded. For example, if we have v[0].y = v[1].y = 114127.75 and v[0].z = v[1].z = -919.915771, then v[0].y*v[1].z = v[1].y*v[0].z = -104987917.189 but one side is rounded to -104987920 before being subtracted from the unrounded side, so the result is approximately 2.811 and not 0.0 as it should be.

If it's dangerous to rely on floating point math to produce exact results, then perhaps it might be worth switching to integer/fixed-point math to perform the backface culling calculation.