Lowering: a renamed register's marker avoids every high number the instruction names (glowing flowers and stems) #922

Merged
duck-paradise merged 2 commits from fix/regmap-marker-named-fields into main 2026-11-09 03:51:31 +00:00
duck-paradise commented 2026-11-09 01:31:11 +00:00 (Migrated from github.com)

Summary

Some flowers, stems and small branches glow in flat bright colours (red or cyan by day, white at night) instead of being lit and textured. This is the symptom in #875, #874, #866, #757, #674 and #667 (also cross-linked there: #812, #811, #696). It is not vendor-specific: the reports cover RTX 4070 Ti / 5080 / 5090 and RX 7800 XT / 9060 XT / 9070 XT.

The cause is in the Ampere -> Maxwell lowering (lower_to_maxwell.h), not in the GPU back end.

Cause

When an instruction names a high GPR (R216 and up), the lowering renames it through a prefix that maps the register to a "marker" number. The marker was checked only against the fields already seen in that instruction. So a destination renamed before its own source could take that source's number as its marker.

Castle Town's flower beds and hanging baskets (mesh code e3fc8fcf540f7a48, native word 864, and others) have:

FMUL R252, R216, c[..]

R252 took 216 as its marker, so one prefix mapped R216 to 252 and to 216. The later run won: the product went to R216 and R252 stayed undefined. That broke the 4th vertex per thread in the colour pass, while the depth pre-pass was fine. So the EQUAL depth test failed against the pre-pass, and the sky/fog colour left behind showed through: red by day, white by night.

Change

  • lower_to_maxwell.h: before choosing markers, collect every high number the instruction's fields name, in any order. Use the exact field span where it is known. A marker must be none of them.
  • gpu/vk/tests/regmap_marker_test.cpp: lowers the flower's instruction and checks that no prefix maps a number twice. It fails without the change ("8 register numbers mapped to two registers in one prefix") and passes with it.
  • tests/run_all.py: runs the test with the other gpu/vk/tests C++ checks.

Testing

  • Program set: of 13,773 programs in the seed, 43 had such prefixes (12 mesh, 31 vertex). With the change they have none, and every other program lowers to the same words.
  • In game (RX 9070 XT, Windows 11, Castle Town): the flower beds and hanging baskets draw with their textures and lighting, no glow. Tested on my branch, which carries this same change on an earlier main.
  • Tests: tests/run_all.py regmap, test_lower_atomg_cas.py and test_lower_depbar.py pass.

Translated shaders are rebuilt on the next start, since the lowering header is part of the shader stamp.

🤖 Generated with Claude Code

## Summary Some flowers, stems and small branches glow in flat bright colours (red or cyan by day, white at night) instead of being lit and textured. This is the symptom in #875, #874, #866, #757, #674 and #667 (also cross-linked there: #812, #811, #696). It is not vendor-specific: the reports cover RTX 4070 Ti / 5080 / 5090 and RX 7800 XT / 9060 XT / 9070 XT. The cause is in the Ampere -> Maxwell lowering (`lower_to_maxwell.h`), not in the GPU back end. ## Cause When an instruction names a high GPR (R216 and up), the lowering renames it through a prefix that maps the register to a "marker" number. The marker was checked only against the fields **already seen** in that instruction. So a destination renamed before its own source could take that source's number as its marker. Castle Town's flower beds and hanging baskets (mesh code `e3fc8fcf540f7a48`, native word 864, and others) have: ``` FMUL R252, R216, c[..] ``` R252 took 216 as its marker, so one prefix mapped R216 to 252 **and** to 216. The later run won: the product went to R216 and R252 stayed undefined. That broke the 4th vertex per thread in the colour pass, while the depth pre-pass was fine. So the EQUAL depth test failed against the pre-pass, and the sky/fog colour left behind showed through: red by day, white by night. ## Change - **`lower_to_maxwell.h`:** before choosing markers, collect every high number the instruction's fields name, in any order. Use the exact field span where it is known. A marker must be none of them. - **`gpu/vk/tests/regmap_marker_test.cpp`:** lowers the flower's instruction and checks that no prefix maps a number twice. It fails without the change ("8 register numbers mapped to two registers in one prefix") and passes with it. - **`tests/run_all.py`:** runs the test with the other `gpu/vk/tests` C++ checks. ## Testing - **Program set:** of 13,773 programs in the seed, 43 had such prefixes (12 mesh, 31 vertex). With the change they have none, and every other program lowers to the same words. - **In game (RX 9070 XT, Windows 11, Castle Town):** the flower beds and hanging baskets draw with their textures and lighting, no glow. Tested on my branch, which carries this same change on an earlier main. - **Tests:** `tests/run_all.py regmap`, `test_lower_atomg_cas.py` and `test_lower_depbar.py` pass. Translated shaders are rebuilt on the next start, since the lowering header is part of the shader stamp. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
KrysGG commented 2026-11-09 02:52:36 +00:00 (Migrated from github.com)

Tested this on an RTX 5080 (driver 621.14), i9-13900K, Windows 11: v2.0.5 (cd9cebb6) + this PR's lower_to_maxwell.h change, shaders prepared again, port off (default). Hyrule Field by the rocks with the lupines and daisies, same save and spot before and after.

Fixed here. The lupine spikes near Link are purple again (they were flat white), the daisies and small flowers stay right, and the white specks in the near grass are gone. Screenshot below.

It matches what I measured on that spot before finding this PR: the near foliage pair is depth 3bde059fb051af1f, colour d4abbcb4c2140609 (lupine spikes and daisies), and an RX_VK_VDUMP-style dump of the mesh positions showed every 4th vertex of the lupine cards zero in the colour pass (3, 7, 11, ... in the last workgroups) while the depth pass had them. With this change:

RX_VK_DRAW_STATS at that spot before with this PR
primitives after clipping, depth / colour 4093 / 4189 (always different) 4277 / 4277
colour pass fragments ~3 000 to 5 000 24 537

Thanks for tracking this down.

image
Tested this on an RTX 5080 (driver 621.14), i9-13900K, Windows 11: v2.0.5 (cd9cebb6) + this PR's `lower_to_maxwell.h` change, shaders prepared again, port off (default). Hyrule Field by the rocks with the lupines and daisies, same save and spot before and after. **Fixed here.** The lupine spikes near Link are purple again (they were flat white), the daisies and small flowers stay right, and the white specks in the near grass are gone. Screenshot below. It matches what I measured on that spot before finding this PR: the near foliage pair is depth 3bde059fb051af1f, colour d4abbcb4c2140609 (lupine spikes and daisies), and an `RX_VK_VDUMP`-style dump of the mesh positions showed every 4th vertex of the lupine cards zero in the colour pass (3, 7, 11, ... in the last workgroups) while the depth pass had them. With this change: | `RX_VK_DRAW_STATS` at that spot | before | with this PR | |---|---|---| | primitives after clipping, depth / colour | 4093 / 4189 (always different) | 4277 / 4277 | | colour pass fragments | ~3 000 to 5 000 | 24 537 | Thanks for tracking this down. <img width="1280" height="720" alt="image" src="https://github.com/user-attachments/assets/d44a14cb-9e39-49bc-94fb-06716c554d14" />
duck-paradise commented 2026-11-09 03:03:37 +00:00 (Migrated from github.com)

Thanks for testing it on NVIDIA, and for the measurements. Good to see it confirmed on a second vendor, and that your vertex dump found the same every-4th-vertex pattern I traced on my side.

Thanks for testing it on NVIDIA, and for the measurements. Good to see it confirmed on a second vendor, and that your vertex dump found the same every-4th-vertex pattern I traced on my side.
shayderrr commented 2026-11-09 03:51:27 +00:00 (Migrated from github.com)

Thank you!

Thank you!
Commenting is not possible because the repository is archived.
No description provided.