Skip to content

fix(shader): print memory instructions' pc and offset in the IR dump - #9907

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
EagleBearerYS:fix/ir-dump-memory-offsets
Oct 24, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
EagleBearerYS:fix/ir-dump-memory-offsets

Conversation

@EagleBearerYS

@EagleBearerYS EagleBearerYS commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

What

APS5_DUMP_IR printed every scalar load's immediate offset as 0. On #9633 that hid the difference between the two words of a pointer chase (0x54 against 0x6c), and the dump couldn't show what decided the refusal (oneandonlydean's comment).

Why:

  • An SMEM load keeps its immediate in the instruction's memory metadata. MemoryFlags indexes Resources().memoryInfo, whose offset holds the immediate plus 4 per component (sLoad, ScalarBufferInstructions.cpp).
  • The load's soffset argument is the constant 0 when the instruction has none.
  • Buffer, address and shared memory instructions keep their offsets in the same metadata.
  • ProgramToString printed each instruction's arguments, type and use count, but not its flags or metadata.

The change:

  • ProgramToString now appends [pc=0x… off=0x…] to every instruction that carries memory metadata. It prints values, not the metadata index.
  • It appends [pc=0x… mem=?] when the index is past memoryInfo, since dumps run before validation.
  • Every other line is unchanged.
  • The opcode set is one predicate, carriesMemoryInfo. ValidateProgram now uses it for its memory-info index check, which each of its five memory blocks used to repeat. The validator accepts and rejects the same programs with the same messages.
  • No off2: translation splits the DS pair forms into two shared ops, each with its own offset. So the second offset shows as a second line, and no IR opcode uses secondaryOffset.

For s_load_dword s4, s[0:1], 0x54 and s_buffer_load_dwordx4 s[12:15], s[8:11], 0x60, before:

  %4 = LoadAddressU32 %3, 0x00000000, 0x00000000, true (U32; uses=1)
  %13 = ReadConstBuffer %12, 0x00000000 (U32; uses=1)
  %16 = ReadConstBuffer %12, 0x00000000 (U32; uses=1)

After:

  %4 = LoadAddressU32 %3, 0x00000000, 0x00000000, true (U32; uses=1) [pc=0x00012de0 off=0x54]
  %13 = ReadConstBuffer %12, 0x00000000 (U32; uses=1) [pc=0x00012de8 off=0x60]
  %16 = ReadConstBuffer %12, 0x00000000 (U32; uses=1) [pc=0x00012de8 off=0x6c]

Users of the dump text:

  • Nothing parses it. git grep over the tree, tools/ included, finds only:
    • APS5_DUMP_IR's own printer;
    • ENVIRONMENT.md's entry for the variable;
    • the tests below.
  • ShaderMemory.cpp's frontend-pair check (reused == fresh) already compares every instruction's flags and the programs' memoryInfo, so the printed values can't newly differ there.

Overlap: git merge-tree is clean against #8939, #9457, #9633, #9749 and #9790, and against #9198, #6612, #7410 and #8881, which touch IrProgram.cpp or IrOpcode.hpp. Of the 47 PRs the overlap bot couldn't compare in core/libs/prx/libSceAgcDriver/CMakeLists.txt, git merge-tree with this head shows a conflict at this PR's ir_dump_memory registration only for #6044 (TaymKal), which converts the file's registrations to add_library_test. The order is proposed in its thread, as for our other PRs there (comment): this PR first; if #6044 lands first, ir_dump_memory is registered with add_library_test at this PR's next merge of main.

Tested

  • New test ir_dump_memory (core/libs/tests/IrDumpMemory.cpp):
    • It translates s_load_dword … 0x54, s_buffer_load_dwordx4 … 0x60 and ds_read2_b32 … offset0:3 offset1:9. Each line must end with its pc and offset: 0x54; 0x60 to 0x6c; 0xc and 0x24. A non-memory line must be unchanged.
    • With memoryInfo cleared, the dump shows mem=? and ValidateProgram throws its usual LoadAddressU32 has an invalid memory-info index.
    • Red: with IrProgram.cpp at main, it fails 10/10 (expected "… true (U32; uses=1)" to end with " [pc=0x00012de0 off=0x54]"). Green: passes 10/10.
  • The dump's other users: agc_shader_frontend_pair, agc_shader_frontend_pair_off, agc_shader_memory, scalar_call, scalar_swappc and agc_validate_program pass.
  • GitHub's runners (run):
    • On both Linux and Windows, ir_dump_memory fails with main's IrProgram.cpp in all 3 runs and passes 10 times with the change.
    • The six tests above pass with the change.
    • The libc and libkernel suites pass on both arms. They ran with APS5_SKIP_TIMING_TESTS=1, which relaxes precise_wait's median bounds on GitHub's hosted runners.
  • Validation layer (run):
    • Setup: VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1 on llvmpipe (LLVM 20.1.2), GitHub's Linux runner. The run includes two real-device tests, agc_driver_image_table_vouched_lookups and agc_driver_msaa_dcc_clear_4.
    • The layer: it loaded 3 times on each arm.
    • The messages: both logs report only VUID-VkDeviceCreateInfo-pNext-pNext, so the change adds no VUID- message. It changes no generated SPIR-V.
  • CI's Linux job mirrored on a cloud Linux machine: 1848/1851. The three failures are that machine's IPv6 tests.
  • APS5_DUMP_IR=all on agc_shader_memory_tests: 18,655 instructions carry [pc=… off=…], and none shows mem=?.
  • FormatVersion: unchanged. The dump isn't serialized.
  • check_conventions.py: passes, with no comment lines added.

Checklist

The APS5_DUMP_IR dump showed every scalar load's immediate offset as 0.
An SMEM load keeps its immediate in the instruction's memory metadata:
MemoryFlags indexes Resources().memoryInfo, whose offset holds the
immediate plus 4 per component, while the soffset argument is the
constant 0 when the instruction has none. Buffer, address and shared
memory instructions keep their offsets there too. ProgramToString
printed the arguments, the type and the use count, but not the flags or
the metadata, so a dump could not tell 0x54 from 0x6c.

ProgramToString now appends " [pc=0x... off=0x...]" to every
instruction that carries memory metadata, and " [pc=0x... mem=?]" when
its index is past memoryInfo, since dumps run before validation. The
opcode set is one predicate, carriesMemoryInfo, which ValidateProgram
now also uses for its memory-info index check; the validator accepts and
rejects the same programs with the same messages.

boykopovar#9633 (comment)
Related: boykopovar#9749.
@MarcZX10

Copy link
Copy Markdown
Contributor

Reviewed the diff and test case. The new carriesMemoryInfo predicate matches the five index-validation families it consolidates (ReadConstBuffer, address, buffer, shared, and image opcodes), and the test checks both representative offsets and the malformed-index path. The focused behavior appears covered by the reported ir_dump_memory red/green runs and the frontend/validator regressions. Current hosted checks show conventions, eligibility, intake, labels and report passing; Linux, Windows, relinker, register-context, write-watch and ASAN jobs are skipped, so I have not counted those as build/test coverage. I did not run this locally in the present environment.

@EagleBearerYS
EagleBearerYS marked this pull request as ready for review October 22, 2026 21:15
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1896 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 2434 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6044 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6186 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6412 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6481 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7048 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7201 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7223 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7275 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7677 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8014 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8246 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8365 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8484 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8542 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8592 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9348 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9508 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9521 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9748 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9892 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9897 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9898 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10193 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10194 core/libs/prx/libSceAgcDriver/CMakeLists.txt

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 2cbaa96390ccba25e16a17efdf4e5b49ffdea59e. The formatter adds metadata only to memory-bearing instructions and preserves other lines; tests cover SMEM, vector buffer offsets, split DS offsets, invalid metadata and non-memory text. The refactored predicate is also used by validation. Current-main whitespace and conventions pass, and the branch merges cleanly; only the AGC CMake registration file changed on both sides. Author-reported Windows/Linux tests, validation-layer logs and the full dump exercise are useful; product jobs remain skipped by workflow policy. I did not rerun C++ tests locally. One description correction: because carriesMemoryInfo includes image operations, malformed image instructions with an out-of-range metadata index now receive the generic bounds error before the former image-kind lookup (which previously indexed without a bounds check). That is a safer invalid-input diagnostic, but is a narrow validation behavior change, so please qualify the claim that validation messages are unchanged and consider adding an image-op missing-metadata case.

@oneandonlydean oneandonlydean self-assigned this Oct 23, 2026
@oneandonlydean
oneandonlydean merged commit c077c7a into boykopovar:main Oct 24, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants