Skip to content

Ampere instructions checked against an Ampere GPU: a Jetson Orin test suite - #2041

Open
Know-It-All-Brother wants to merge 3 commits into
seedds:mainfrom
Know-It-All-Brother:ampere-orin-tests
Open

Know-It-All-Brother wants to merge 3 commits into
seedds:mainfrom
Know-It-All-Brother:ampere-orin-tests

Conversation

@Know-It-All-Brother

@Know-It-All-Brother Know-It-All-Brother commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Part 1 of the Ampere accuracy series (#2040). Every fix in the series builds on this test.

What and why

Our translator tests check the MSL that a few encodings give, not the values a shader computes, so a meaning read wrong from an encoding, or lost on the way through spirv-cross and Metal, only showed up when a game looked wrong. This adds a test that compares values with real hardware.

test_dmsh_ampere_orin.py takes 203 operations, each the GPU compiler's own machine code for one PTX operation, recorded on a Jetson Orin (sm_87, CUDA 12.6 driver) with 1,024 input rows and the Orin's outputs. It runs each program through the whole chain: the translator with the build's options, spirv-cross with the chain's arguments, every MSL rewrite dmsh_build.py's finish() makes (read from its source, so a new rewrite is picked up), and the chain's Metal flags. Then it compares every output word with the Orin's, bit for bit.

  • Allowed on every op: what Metal's f32 arithmetic itself does, which is flushing denormals and writing a different NaN.
  • KNOWN lists the ops that still differ, each with its reason, and APPROX the ones that run Metal's own approximation (MUFU and the divisions built on it). The test fails when an op outside both lists differs, and when a KNOWN op matches, so each fix in the series takes its entry out.
  • dm/gfx/tools/ampere_orin/capture.py re-records the fixture on any Linux machine with an Ampere GPU and NVIDIA's driver. The driver compiles the PTX itself, so neither side needs a CUDA toolkit or a compiler. It rewrites the same machine code for the translator (global loads and stores become shared memory ones, and the CUDA parameter reads become NOPs), and the device's nvdisasm checks every rewritten program. ampere_orin/ampere_orin.sass lists each program as the translator gets it.

Reference entry: "Ampere instructions checked against an Ampere GPU" in docs/reference/shaders.md.

Two commits came after the first:

How to verify

DMSH_TEST_XLATE=dm/gfx/tools/dmsh_xlate_bin/dmsh_xlate python3 dm/gfx/tests/test_dmsh_ampere_orin.py

It takes about 5 seconds on an M5 Max and prints each op's differing lanes by cause. AMPERE_ORIN_ONLY=fsetp,shfl_idx runs a few, and AMPERE_ORIN_REPORT=out.json writes everything as JSON. To see that it catches a change both ways, drop an entry from KNOWN (the op fails as a mismatch) or add a matching op to it (it fails with "take it out of KNOWN"). I checked both.

Checked

  • Tests: test_dmsh_ampere_orin.py passes on main's translator, with all 203 ops. The other test_dmsh_* tests are unchanged; test_dmsh_ampere_mem.py (3 Pokopia MSL patterns), test_dmsh_meshstage.py (6 integer pass-through errors) and test_dmsh_pairs.py (1 error) fail on main the same way, with or without this PR. test_docs.py and lint_python.py --against origin/main pass with no new findings.
  • Devices and OS: MacBook Pro M5 Max, macOS 27; Jetson Orin (sm_87, CUDA 12.6 driver) for the recording.
  • regress.py: not run. This PR changes no chain tool and no shader output.
  • Not checked: recording on an RTX 30 card (sm_86). The tool takes --arch sm_86, but I only had the Orin.

Docs

  • docs/reference/shaders.md has the entry, and python3 dm/tools/docs_symptoms.py was run
  • A chain tool changed (no)
  • No game files, keys or data extracted from a game. The fixture is NVIDIA's compiler output for our own PTX.

…re_orin.py runs about 190 operations, each the GPU compiler's own machine code for one PTX operation, through the translator, spirv-cross, the chain's MSL rewrites and Metal on this Mac's GPU, and compares every output word with what a Jetson Orin (sm_87) computed from the same 1,024 input rows. The translator tests checked the MSL a few encodings give, not the values; this one finds the FSETP.NE, SHFL lane, F2FP, rounding-mode and signed-zero differences the tracking issue lists, which KNOWN names until each fix takes its entry out. dm/gfx/tools/ampere_orin/capture.py records the fixture on any Linux machine with an Ampere GPU and NVIDIA's driver, with no toolkit or compiler on either side
…ules with its functions, so a rewrite that uses one (struct in PR seedds#1902's hfma_msl) runs as it does in a build instead of raising NameError
…I2F to F16 with .RZ / .RM / .RP (signed and unsigned), F2F.F16.F32 with each directed rounding, F2FP.PACK_AB.RZ, and SHFL.UP with a non-zero clamp and with a segment mask, so PR seedds#1800's fixes of those can be checked on the GPU. On main six of them differ (I2F to F16 in 261 to 751 of 2,048 halves, the .RZ pack in 905, SHFL.UP's clamp in 783 of 2,048 lanes) and KNOWN names seedds#1800 for them; with seedds#1800's translator all ten match apart from NaN bits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant