Skip to content

NVIDIA: wave64 pixel program reads lane 63 (v_readlane_b32) on a 32-lane host, NHL 26 (PPSA26785) stops at start-up #5398

Closed

Description

@milchgeldkassierer

NHL 26 (PPSA26785 v01.060.000, retail dump, owned) on Linux/NVIDIA gets past import resolution and module loading, creates the Vulkan device and registers shaders, and then terminates on one wave64 pixel program that reads lane 63. This looks like the pixel-stage counterpart of #2783 / #3546.

Stop

terminate called after throwing an instance of 'std::runtime_error'
  what():  shader 0x1173ae1000 stage 5: ShaderRecompiler::Recompile: SPIR-V emission failed: hash=0x74955231232 stage=2 opcode=ReadLane reason=v_readlane_b32 of lane 63 is outside the 32-lane host subgroup that runs this wave64 program at one lane per invocation

stage=2 is IrShaderStage::Pixel in ShaderStage.hpp (Unknown, Vertex, Pixel, Fetch, ...). #2783 has the same message with stage=1 (a vertex program), and #3546 narrows s3 only for wave64 vertex programs on exactly 32 host lanes. As far as I can tell there is nothing equivalent for pixel programs, but I have not tried to write it. I do not know what the stage 5 in the prefix refers to.

The RecompileRequest: dump that follows the error (10 KB) is below, so the shader can be reproduced without the game.

RecompileRequest dump for shader 0x1173ae1000
RecompileRequest:
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QiBLEEwQTRBOEG9geRB6EIUQAABuAABkDyAhECRAAABkDyAhECIgJEAAAFkAAEQkQAAAQYJRAAEgAD2AoEPAQQBqEWBAAEWl52DhQdJJWDrdQqPJeDIPkS5iykxWl5cZW2fz8AsNHUUAlAImlgAAAV75gYAAJaABBVulASWpAQEgrAEIILABB1ACoAEApQEQuAEBkAEAqQEQvwEAgAESrAEQyAEAcBCsARDRAQBgBqwBENkBAEARsAEQ4QEAIAW0ARDpAQAAALQBG7QB8QGwAUcbAKABG/kBgAIIRIUCKosCAYUCAQ74VeIDAWM9kIugQCCIhJ53AAAAAAAAAAAAAGJhcmVmb290+9NBOAAAAAABAAAAMAoAAAAAAAAmAQAAAaMk7QiC5w4AAAAAAAAAAAAQplARAAAAmAEAAAAAAAAxMjM0GAAAABARplARAAAAABCucxEAAADIEKZQEQAAAJgQplARAAAAYBCmUBEAAACQEKZQEQAAAAAAAAAAAAAAmAEAAJALAAAAAAAADgAAAAEAAAAAAAAAMAABCQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAEAAAAAAAAgAAAAQrnMRCQAAAAAAAAAGAAAAYAsAIQYAAAD700E4CgAAAE8BLAILAAAABAAAAMQBAAAAAAAAxQEAAEQAAACzAQAAAgMAALQBAAACAwAAtgEAAAEAAAC4AQAAAAAAAQMCAAAQAAAAjwAAAP8AAAAQAwAAAAAAAEgRplARAAAAYBGmUBEAAACIEaZQEQAAAIgRplARAAAAkBGmUBEAAAAsAAAACwATAAAAAQABAAAA/////////////wAA/////////////wAAIAD//////////ygAOID///////////////////////88gDAAQIAAAESAAAAAAAAASIAAAAAAAAABwAAAAAEAAAAQQAAABAEAIAAAAAEAAAAjAAAAAAAAAAEAAAACAAAAAwAAAAkAAAAKAAAACwAAAAwAAAAZAAAAGwAAAB0AAAAfAAAAIAAAACEAAAAqAAAAMAAAADcAAAA4AAAAPQAAAD8AAABAAAAAQQAAAGARAABwEQAAchEAAHMRAACYEwAAvxMAAIYUAACjFAAApBQAALUUAAC7FAAAvRQAAOMUAAACFQAACgAAAAAAAAAbAAAAAAAAAFNQVl9FWFRfZGVzY3JpcHRvcl9pbmRleGluZyEAAAAAAAAAU1BWX0VYVF9mcmFnbWVudF9zaGFkZXJfaW50ZXJsb2NrEwAAAAAAAABTUFZfRVhUX21lc2hfc2hhZGVyGgAAAAAAAABTUFZfRVhUX3NoYWRlcl9pbWFnZV9pbnQ2NCMAAAAAAAAAU1BWX0VYVF9zaGFkZXJfdmlld3BvcnRfaW5kZXhfbGF5ZXIUAAAAAAAAAFNQVl9LSFJfOGJpdF9zdG9yYWdlFgAAAAAAAABTUFZfS0hSX2Zsb2F0X2NvbnRyb2xzIwAAAAAAAABTUFZfS0hSX2ZyYWdtZW50X3NoYWRlcl9iYXJ5Y2VudHJpYx8AAAAAAAAAU1BWX0tIUl9waHlzaWNhbF9zdG9yYWdlX2J1ZmZlchQAAAAAAAAAU1BWX0tIUl9zaGFkZXJfY2xvY2sBAAQAAAAEAABAAAAAAAQAAADAAAABgAAAAIAAAACAAAAAgAAAAABwAAAAAQAAAAEAAIAAAAAAgAAAIAAAACAAAAABIAAAAIAAAACAAAAAeAAAAHgQAACAAAAAgAAAAAAAAAAAAAAAgAAAAIAAAAAAAQECAAAAAAABQA0DAAEB

Host and build

  • Linux Mint 22.3, kernel 7.0.0-38, GCC 13.3.0
  • GeForce RTX 3070, NVIDIA 595.99.02 (proprietary), Vulkan 1.4.329, subgroup size 32
  • Intel Core i9-14900KF, so the title was converted with relinker --to-intel
  • main 18c438b (includes fix(recompiler): give wave64 vertex programs on 32-lane hosts a 32-lane s3 #3546), plus the two local changes listed below
  • Title converted from the dump's eboot.bin and .prx files. They are unencrypted SELF files that I unpacked to ELF with a small script of my own, because the relinker rejects SELF input.
  • Launch: ANYPS5_SHADER_CACHE_DIR=<dir> ANYPS5_LANGUAGE=4 ./app.elf with a cold shader cache. The stop came within about 90 seconds.

What was reached before the stop

Import audit (tools/import_audit.py): 1777 unique imports, 0 absent, 29 stubs. The title then opens its game files, loads Engine.Render.Core2.PlatformPs5.prx through sceKernelLoadStartModule, creates the Vulkan device and swapchain, and registers shaders. No frame was presented.

Local changes that were needed to get this far

I mention them because the stop is only reachable with them. I can open PRs for both if wanted.

  1. libSceVdecsw had no sceVdecswSyncDecodeInput, sceVdecswSyncDecodeOutput or sceVdecswGetHevcPictureInfo (the import audit listed them as absent). I added the two Sync variants as bounded polling wrappers around the Try variants, and a HEVC picture info that throws.
  2. On Linux, GuestAllocationsRegisterMainImage registers only the first object dl_iterate_phdr reports, so mprotect inside a relinked title module (*.guest.prx) ended in guest protection or unmap range is not registered. Windows registers modules through RegisterImage. I made the Linux path register *.guest.prx modules as well.

Setup detail: the title opens its render module with sceKernelLoadStartModule("/app0/Engine.Render.Core2.PlatformPs5.prx"), so the relinked file has to be reachable as app0/Engine.Render.Core2.PlatformPs5.prx.guest.prx. The relinker puts it under app0/sce_module/ when the input module sat in sce_module/, and I linked it into app0/ by hand.

Earlier behaviour on the same hardware

On main 44ab0c3 (the day before) the same title did not stop here. It ran on to repeated SubmissionManagerPs5::waitForFrame ... 0x8002003C with all cores busy in ShaderRecompiler::PrepareResourceProgram and RAM growing by about 4 GB per minute. I have not checked whether the new stop is a failure that used to be deferred or one that a commit in between introduced.

Question

Would the #3546 approach (give wave64 programs on 32-lane hosts a 32-lane wave) be the right model for pixel programs, or does a pixel v_readlane_b32 of lane 63 need a different treatment (helper lanes, quad layout)?

AI-assisted: yes (Claude Code)

Activity

  1. MarcZX10 commented on Oct 13, 2026

    @MarcZX10
    Contributor

    I checked the two existing approaches. #3546 handles a recognized vertex half-wave reduction pattern and keeps refusing other lane-63 reads; it is not a general wave64-on-wave32 mapping. The new compute approach in #5405 spans two 32-lane subgroups with a 64-entry Workgroup exchange buffer and barriers. That exchange mechanism is not available to a fragment shader, and fragment execution also has quad/helper-lane semantics to preserve. So the compute mapping cannot be copied directly to pixel stage. I would keep this read rejected until a fragment-specific lowering preserves those semantics; replacing lane 63 with lane 31 or zero would silently change the shader. I have not run NHL 26 or validated this on GPU hardware.

  2. milchgeldkassierer commented on Oct 13, 2026

    @milchgeldkassierer
    ContributorAuthor

    @MarcZX100 thanks for checking this. Agreed: replacing lane 63 with zero or lane 31 silently changes the shader, and I am not proposing it as a fix.

    For context, I tried exactly that locally as a diagnostic only. In EmitReadLane, for a non-compute stage with an immediate lane index at or above the host subgroup size, I returned a constant 0 instead of failing, behind an environment variable that is off by default. Nothing of this is meant for main.

    What it showed on NHL 26 (PPSA26785 v01.060.000, RTX 3070, NVIDIA 595.99.02, Linux, main dacd785):

    • With that change the wave64 pixel stop disappears and the title renders frames. The first presented frame was the intro, and the engine's breadcrumb output names real passes (DeferredGpuProbes, DeferredShadows, TAAPostSharpen, FSR2PassAccumulate). The picture is certainly wrong wherever a shader reads a lane of 32 or above.
    • I did not count how many shaders hit this path. If it helps I can log the shader hash and lane index for each refusal on a run with the stop disabled, so the number and the kind of pixel programs are known before anyone designs a fragment-specific lowering.

    Other stops further on (not caused by the above, but only reachable with it), in case they are useful:

    1. AGC graphics: 32-bit integer read of the depth-layout texture 0x11c10f0000, which is no depth surface drawn with, is not implemented (compute shader 0x1150101000). I have not found an issue or PR for it.
    2. sce::Json::Value::setNullAccessCallBack is a stub that aborts the title; I am sending a small PR for it.
    3. Host memory use grows by about 0.5 GB per second while shaders are built and reaches 60 to 72 GB within two minutes (about 37 GB of it anonymous host allocations, 4.4 GB the guest's direct memory). I run the title in a cgroup with a hard memory limit because of this.

    AI-assisted: yes (Claude Code)

  3. MarcZX10 commented on Oct 13, 2026

    @MarcZX10
    Contributor

    Thanks, that confirms lane-63 substitution only gets past the stop by producing visibly incorrect shader output, so I agree it should stay diagnostic-only. Per your offer, logging the affected shader hashes and lane indices with the stop disabled would be useful to establish whether the reads share a recognizable pattern before designing fragment lowering. The depth-layout integer-read stop looks like a separate concrete AGC gap; I will check whether it has an existing issue/PR before suggesting a follow-up.

  4. MarcZX10 commented on Oct 13, 2026

    @MarcZX10
    Contributor

    I checked this secondary stop against the current code and existing issue/PR inventory. It reaches cachedTexture: the descriptor decodes as a 32-bit depth layout, but DepthSurfaceTexture did not match it to a tracked depth target, so the fallback is intentionally rejected. I found no existing report or PR for this exact case.

    Could you attach the RecompileRequest for compute shader 0x1150101000 plus the guest texture descriptor words for address 0x11c10f0000 (and, if available, its depth/HTILE metadata addresses and format/tile mode)? Also, do you know whether that memory range was previously drawn as a depth target? That will distinguish a legitimate integer view of depth-layout storage from a malformed/untracked descriptor; the right behavior differs.

  5. nikowolf123 commented on Oct 14, 2026

    @nikowolf123
    Contributor

    I replayed the RecompileRequest from the issue body with agc_shader_replay on main a453108, which includes #5189 (a97649f). It still stops with v_readlane_b32 of lane 63 is outside the 32-lane host subgroup. The helper-lane key proof, EntryLaneWalk, runs out of its step budget; it does not reach a shape it rejects:

    • The shader reads lanes 31 and 63, and each read tries a wide and a 32-lane match, so there are four walks. With a local step counter (diagnostic only), all four stop at the 512-step budget after 78 Phi expansions and 98 Phi revisits, having looked at only 32 distinct nodes (value, proof kind and mask half).
    • With only the budget raised, the wide walk for each read proves the keys in 1,369 steps over 34 distinct nodes. The step count was the same at all six budgets I tried from 4,096 to 2^32-1; 1,024 still fails. The capture then compiles and passes SPIR-V validation at 69,230 words, the same count @cookie42073-cmd gave for his follow-up.
    • That is about 40 visits per node. EntryLaneWalk keeps no results and Incoming only stops cycles, so the same Phis are expanded again from every use (206 expansions in the finished walk). This matches his description of the walk "rechecking the same loop-carried mask".

    @cookie42073-cmd, are you opening 9456e863e as a PR? #5189 is merged now, so it can go straight onto main. Once it is up I can rerun this capture on your branch.

    Side note for anyone replaying: with ANYPS5_ENABLE_SPIRV_TOOLS=ON, agc_shader_replay does not compile on main. ShaderReplay.cpp:150 passes result.spirv to SpirvTools::Disassemble, and #4806 removed SharedSpirv's implicit conversion to std::vector. The target is EXCLUDE_FROM_ALL, so CI does not build it. Locally I passed result.spirv.data(), result.spirv.size() instead.

    The request carries the reporter's subgroup size (32), so the replay does not depend on the local GPU. Linux (WSL, GCC 15.2) and native Windows (WinLibs GCC 15.2) builds gave the same results, including the step counts.

    AI-assisted: written with Claude Code; I checked EntryLaneWalk, MatchHalfWaveScan and EmitHalfWaveReduction on a453108, the #5189 thread and #4806's change to SharedSpirv. I ran agc_shader_replay on the issue's request on a453108 in Linux (WSL) and native Windows builds with SPIRV-Tools, plus instrumented builds at budgets from 512 to 2^32-1 (Linux) and at 512 and 4,096 (Windows), and a separate Linux build with only the EntryLaneWalk budget constant changed (512 and 1,024 fail, 4,096 compiles). I did not run NHL 26.

  6. milchgeldkassierer commented on Oct 14, 2026

    @milchgeldkassierer
    ContributorAuthor

    Thanks all, and thanks @adriadam10 for finishing #5438.

    Fresh NHL 26 run, as requested by @cookie42073-cmd and @nikowolf123 (PPSA26785 v01.060.000, GeForce RTX 3070, NVIDIA 595.99.02 proprietary, Linux Mint 22.3, kernel 7.0.0-38, GCC 13.3, subgroup 32, converted with --to-intel):

    Tested tree: main e6ef803 (includes #5189 and #4883) plus these local changes: #5181 applied; the EntryLaneWalk budget raised from 512 to 4096 (nothing else changed in the proof); libSceVdecsw Sync* and GetHevcPictureInfo and the Linux registration of *.guest.prx for mprotect (both still missing on main, I can open PRs if wanted); and two diagnostic switches, off by default, described below.

    • The lane-63 stop is gone without any substitution. My earlier "lane 63 reads 0" switch was off in this run (it logged nothing), and no SPIR-V emission failed appears in either log: a cold-cache run of 7 minutes and a warm-cache run of 10 minutes. The warm run reached 8 distinct render passes (DeferredGpuProbes, forwardSimpleOpaque, hairResolve, mainOpaque, TAAPostSharpen, ...) and the title then showed its license screen. That supports the budget diagnosis from @nikowolf123 on real hardware. I did not run the unmodified 512 budget on this tree, and I did not compare image output with a 64-lane GPU.
    • I can rerun on @cookie42073-cmd's branch as soon as it is public.

    For @MarcZX100 (depth-layout integer read). With a local switch that lets cachedTexture read such a texture from guest memory like any other texture instead of throwing, the title gets past that stop. The switch prints the descriptor when it is taken. Both lines below were taken in the warm run (resource.format is the decoded format field of the driver, dcc is the DCC address):

    address=0x11c10f0000 width=1920 height=1080 format=20 dcc=0x0 words=0x11c10f00,0xc1400000,0x010dc1df,0x91800fac,0x00000000,0x00700000,0x00000000,0x00000000
    address=0x11c0000000 width=1176 height=664 format=20 dcc=0x0 words=0x11c00000,0xc1400000,0x00a5c125,0x91800fac,0x00000000,0x00700000,0x00000000,0x00000000
    

    I do not know whether either range was drawn as a depth target before, and I have not looked at HTILE or the tile mode beyond the words above. I also have not checked that the image read this way is correct. I have not captured the RecompileRequest of compute shader 0x1150101000 yet; if you want it, I will dump it on the next run.

    Host memory. Earlier I reported 60 to 72 GB. A heap profile on main dacd785 after 140 s attributed about 34 GB nearly entirely to the AGC driver: 9.4 GB DecodeRdnaProgram (via PlanRegistered), 13.1 GB ResourceMaterializer::ownPlanValues, 3.7 GB ShaderDiskCache::decodeArtifact, 1.8 GB IrValue::AddArgument. With dacd785 plus #5181 the process plateaued around 73 GB after about 17 minutes. On the tree above (main e6ef803, which has #4883, plus #5181), the warm run peaked at 31 GB and stayed at 29 to 30 GB for the 10 minutes. The numbers are the memory of the game's cgroup, so they include page cache. I did not measure #4883 or #5181 separately on identical bases, so I cannot say which one accounts for how much.

    AI-assisted: yes (Claude Code)

  7. MarcZX10 commented on Oct 15, 2026

    @MarcZX10
    Contributor

    I opened #6180 with a bounded EntryLaneWalk budget increase (512 → 2048) and a regression test for the captured request. On Linux, the exact request failed at the old budget and now emits SPIR-V; the focused CTest passes. This confirms the emission stop is fixed for the capture. I have not run NHL 26 or validated pixel output on GPU hardware, so I am not claiming gameplay/image correctness.

  8. milchgeldkassierer commented on Oct 15, 2026

    @milchgeldkassierer
    ContributorAuthor

    Status update on NHL 26 (PPSA26785 v01.060.000), RTX 3070 (8 GB), NVIDIA 595.99.02, Linux, main 0029e62 plus #6180 and #5405 applied locally. Everything below was seen in one cold-cache run.

    Where it gets to now: intro, main menu, licence screen, with the pixel v_readlane_b32 lane 63 stop gone (translated with the larger EntryLaneWalk budget). Memory is much better: the process plateaus around 50 to 59 GB host RAM instead of 70+.

    Stops met on the way, each with the workaround that got past it

    1. GPU hang: Xid 109 CTX SWITCH TIMEOUT in a wave64 compute program (ShaderProgram_WarpCloth..., for example shader 0x1173536000). Gone with APS5_SPANNED_WAVE=1 (feat(recompiler): run single-wave wave64 compute programs at one lane per invocation on 32-lane hosts #5405) on a fresh shader cache. A cache built before the switch serves the old shaders, so the first attempt looked like it did not help.
    2. sampling the stencil plane of depth surface ... guest format 1 (vk 9) ... not implemented: I accept R8_UNORM for the stencil plane locally and it continues.
    3. guest snapshot differs from registered memory in compute TextureCompress_CS_BC1_HiQ: only worked around locally by skipping the check, so the cause is still open.
    4. sceAjmBatchJobInitialize (Opus mapping family ...) not implemented: already fixed upstream by the family 255 change.

    New stop, not yet fixed: VRAM runs out
    After about 940 s and roughly 17,000 StorageTexture upload messages the process ends with

    [gpu] device buffer: device-local heap 0 uses 6366 of its 6403 MiB budget, 54525952 bytes placed in host memory type 0; 1 such allocations, 52 MiB
    [bufferpool] vkAllocateMemory device buffer recovered: allocation=1048576 reclaimed=734752512 initialResult=-2 attempts=2
    [gpu] driver failure: AGC graphics: vkAllocateMemory device buffer: allocation=4718592 memoryType=1 reclaimed=0 initialResult=-2 attempts=1: Vulkan result -2
    [videoout] presentation failed: ...
    terminate called after throwing an instance of 'std::runtime_error'
    

    The sampled texture cache budget had been lowered step by step from 3595 MiB to 2231 MiB, and at that point the heap was at 3100 MiB, 668 MiB of it sampled textures and 1053 MiB cached storage images. So roughly half of what the heap held at the failure was neither sampled texture nor cached storage image. The second allocation found nothing left to reclaim (reclaimed=0) and the title is terminated rather than falling back to host memory.

    The game is also very slow during this phase: the GPU sits at about 19 % and 540 MHz while one thread uploads storage textures. I did not get to the test game.

    Questions: is a fallback to host memory for device buffers (as already done for the 52 MiB case) planned for the case when reclaiming finds nothing, and is there something I can log that shows what fills the rest of the heap? Happy to test patches.

    AI-assisted: yes (Claude Code)

  9. milchgeldkassierer commented on Oct 15, 2026

    @milchgeldkassierer
    ContributorAuthor

    Follow-up on NHL 26 (PPSA26785 v01.060.000), RTX 3070 8 GB, NVIDIA 595.99.02, main 0029e62 with #6180 and #5405 applied locally. This replaces my guess in the previous comment about the GPU hang.

    The GPU hang is in the title's cloth compute programs, and it is not a missing barrier

    The hang (Xid 109 CTX SWITCH TIMEOUT, then vkWaitForFences ... Vulkan result -4) always shows the same breadcrumb: pass snowProjectionClearPass, last bound pipeline ShaderProgram_WarpClothComputeMeshGeometryNormals, last opcode Dispatch 50 x 1 x 1. The error line names a compute shader each time. I ran with a wait for the GPU after every dispatch (local debug switch) so that the name is exact, and with a wait before and after the dispatch. The hang still happens, so I now think the program itself does not finish, not that a barrier is missing. APS5_FULL_BARRIERS=1 did not remove it either (it once ran past it, once not). The programs that stopped the GPU so far: 0x1170d0fc00, 0x1173536000, 0x1170460000, 0x1170853800, 0x1173d45000, 0x1173256000, plus 0x1173094800 and 0x1173234800 from the same 50-group family. I do not know how many variants there are. With APS5_SPANNED_WAVE=1 the earlier hang in a different cloth program went away, so this may be a second problem, but I have not read these programs.

    I skip these dispatches locally (a debug switch of mine, not for main). With the eight skipped, the title runs for minutes with no hang and reaches the title screen, the main menu and the versus screen (Oilers against Islanders). I did not reach the faceoff. The versus picture shows the players broken: head, gloves and pants float apart. I cannot tell whether that comes from the skipped programs or from something else.

    VRAM on 8 GB

    The title reached the 8 GB limit three ways: a device buffer, a render target, a depth target (vkAllocateMemory ... Vulkan result -2, after about 6.3 of 6.4 GiB). What helped locally: APS5_TEXTURE_CACHE_MIB=1024 (so no stop of this kind in a run of over ten minutes), placing a device buffer in host memory when the device-local allocation fails, and releasing the buffer pool before retrying an image allocation. The heap use that the title's own counters add up (sampled textures, cached storage images) was about 3.7 GiB when the failure came, so roughly 2.6 GiB are something else (I assume the driver's memory for the 27,000 pipelines, not checked).

    Speed

    About 23 fps on the title screen, 4 to 7 fps in the menu and on the versus screen. Per frame the GPU is busy about 43 ms and idle about 110 ms, with about 60 batches recorded per flip, so the CPU side (resource builds: guest memory upload, image preparation) is the limit, not the GPU. A larger dispatch cache removes all evictions (65,000 to 0) but changes the speed very little.

    If a capture of the cloth dispatch (resources and the program) would help to see why it does not finish, tell me what to dump and I will send it.

    AI-assisted: yes (Claude Code)

  10. cookie42073-cmd commented on Oct 15, 2026

    @cookie42073-cmd
    Contributor

    Hey @milchgeldkassierer, thanks for narrowing this down. Yes, a capture of one failing cloth dispatch would help. Let's start with one of the ShaderProgram_WarpClothComputeMeshGeometryNormals variants at snowProjectionClearPass, with the reported Dispatch 50 x 1 x 1.

    Could you share:

    • The exact base and PR commit hashes, any other local patches, relevant switches (especially APS5_SPANNED_WAVE), cache state, and steps to reach that dispatch. Please identify which bypasses were active; the captured cloth dispatch itself needs to be the one that fails, not a skipped replacement.
    • Its complete dispatch-time RecompileRequest, shader address/hash, and the matching log through the Xid/device-loss error. Please distinguish this from a registration-time preparation request, which may lack the dispatch's user data.
    • For an execution replay, the resource descriptors/bindings and bounded input buffer ranges as they were immediately before that dispatch, plus the entry point, local workgroup size, dispatch dimensions, constants/push constants, and indirect arguments if used. Include any input images it actually reads, with their formats/layouts. A request that recompiles alone may not contain everything needed to reproduce a GPU hang.

    @Pipodi, since #5405 changes this compute path, is there an existing capture/replay format you'd prefer before anyone dumps large resources? I'd like to coordinate the investigation with you and keep the original capture alongside any reduced test. One known failing variant is enough to begin with; no need to repeatedly trigger device loss to collect all eight.

    The waits and barrier experiments narrow things down, but I wouldn't rule out synchronization or bad input state until we can inspect the capture. The skipped-dispatch run is useful diagnostic evidence, with its rendering limitations noted.

    For the separate VRAM failures, #5987 already covers allocation fallback and #6174 adds cache reclaim on top of it. Those look worth coordinating with their authors rather than duplicating; neither is validated for this NHL26 run yet.

    AI-assisted investigation and write-up, independently reviewed.

  11. frankea commented on Oct 17, 2026

    @frankea
    Contributor

    Windows / NVIDIA data point on current main, in case it helps with the depth-layout read @MarcZX100 asked about: NHL 26 (PPSA26785, 01.060.000), Windows 11 (26200), RTX 4090 (NVIDIA 616.92, subgroup 32), Ryzen 7 5800X, MinGW-w64 GCC 15.2.0 r7, main 922dc89 (includes #6180 and #5405), no local changes, relinked with --windows --registry --module-dir ., cold and warm shader cache, three runs.

    • The lane-63 pixel stop is gone on this plain main build (no SPIR-V emission failed in any run, 27,297 shaders compiled on the cold run).
    • All three runs then stop on the same line as your second stop, same shader hash and same address:
    [gpu] driver failure: compute shader 0x1150101000: AGC graphics: 32-bit integer read of the depth-layout texture 0x11c10f0000, which is no depth surface drawn with, is not implemented
    terminate called after throwing an instance of 'std::runtime_error'
    FATAL: abort() (SIGABRT) on thread 22204
    

    Launch to exit 12 min 25 s cold, 4 min 59 s and 4 min 50 s warm; the window shows black frames with the counter running (504 frames in run 1, 272 in run 3) and never a frame with content. Device-local memory at the stop: 242 to 375 MiB of a 23,370 MiB budget.

    • Where it is: the failing dispatch is not in the kept part of the ring dump (16 graphics submissions cut at 512 dwords, two compute-queue submissions that dispatch neighbouring programs such as 0x1150100100). The title's own breadcrumb dump after its waitForFrame fails (0x8002003C) puts the graphics queue at render pass VelocityVectorFromDepth, pipeline ShaderProgram_GTAODenoisePass, Dispatch 60 x 45 x 1 (first incomplete), after preIntegratedFG, planarShadowDL, planarShadowsBlur and mainForegroundGBuffer completed. The log does not record what 0x11c10f0000 was drawn as; the only 1920x1080 registrations it prints are a storage image at 0x11c0000000 (format 36) and a texture at 0x11c0870000 (format 56). No RecompileRequest is dumped for this failure; if the request of 0x1150101000 or the descriptor words would help, say what to print and I will rerun.

    Nothing from libSceVdecsw or sce::Json is hit on this tree. Full trimmed stderr and the breadcrumb dump are in the title's bring-up thread: #7304.

    AI-assisted: yes (Claude Code).

  12. MarcZX10 commented on Oct 17, 2026

    @MarcZX10
    Contributor

    Thanks, this narrows the later stop to runtime resolution of the texture at 0x11c10f0000; the earlier wave64 lane issue is already gone on current main. I checked the refusal site: cachedTexture() has already failed to match a drawn depth surface, then DepthBitsTextureWidth(words[1], words[3]) classifies the descriptor as 32-bit depth-layout. Could you capture, for shader 0x1150101000, the eight raw T# descriptor dwords passed into cachedTexture() and the resolved GuestTextureResource fields (base, dimensions, format, tile mode, mip/layer range), plus whether that exact address was ever bound as a depth target earlier in the run? That should tell us whether the descriptor is malformed/misclassified or the depth-surface ownership lookup is missing a valid surface. The full RecompileRequest may help with shader provenance, but those runtime descriptor and ownership details are the key for this specific error.

  13. frankea commented on Oct 18, 2026

    @frankea
    Contributor

    Data as asked, same box and tree as above (main 922dc89 + a local print at the refusal site, libs only rebuilt), three warm runs, identical values each time:

    Raw T# dwords passed into cachedTexture() for compute shader 0x1150101000:

    11c10f00 c1400000 010dc1df 91800fac 00000000 00700000 00000000 00000000
    

    Decoded: base 0x11c10f0000 (pipeBankXor 0), format 20 (Format32UInt), 1920x1080, type 9 (2D), sw_mode 24 (SW_64KB_Z_X -> kZ64KBX), dst_sel XYZW = 4567, base/last level 0/0, max_mip 0, depth 0, base_array 0, min_lod 0, bc_swizzle 0, word6/word7 zero (no DCC/meta, iterate_256 0). Resolved GuestTextureResource: base 0x11c10f0000, 1920x1080x1, k2D, format 20, tile kZ64KBX, mips 0..0 of 1, layers 0..0, no DCC, samples 1; DescribeSurface = 0x870000 bytes, depthCompare false. So the 32-bit depth-layout classification is literal: Z swizzle + R32_UINT, nothing malformed.

    Depth-target ownership: 0x11c10f0000 was never bound as a depth target, and neither was anything else. I kept a bounded history of every DepthSurfaceView() entry (the Draw.cpp fresh and replay paths) and at the refusal it was empty: 0 depth-target bases, 0 binds, 0 surfaces() entries, 223, 224 and 298 frames in by the title's own breadcrumb frameIndex in the three runs. No pending or live StorageTexture covers the 0x870000-byte range either, so no compute storage write to it is known to the driver. In other words the ownership lookup is not missing a valid surface; on this port nothing ever drew depth before VelocityVectorFromDepth reads it as uint. The passes the breadcrumbs mark completed (preIntegratedFG, planarShadowDL, planarShadowsBlur, mainForegroundGBuffer) reached the driver without a Z/stencil plane in DB_Z_INFO/DB_STENCIL_INFO as State.cpp reads them (no always-pass depth/stencil state line in the log either), which looks like the next thing to understand: what writes 0x11c10f0000 on the console if not a depth draw. Full lines below.

    diagnostic lines (diag-1) and the local print
    [5398-diag] refusing a 32-bit integer read of depth-layout texture 0x11c10f0000: T# dwords 11c10f00 c1400000 010dc1df 91800fac 00000000 00700000 00000000 00000000 (8 words), caller guestBytes 8847360, depthCompare 0
    [5398-diag]   GuestTextureResource: baseAddress 0x11c10f0000 width 1920 height 1080 depthOrLastArray 0 baseArray 0 mipCount 1 allocatedMipCount 1 baseLevel 0 lastLevel 0 minLod 0 tileMode 4 (T# sw_mode 24) dimension 1 (T# type 9) format 20 dstSel 4567 pipeBankXor 0x0 bcSwizzle 0 dccAddress 0x0 dccAlphaOnMsb 0 dccPipeAligned 0 iterate256 0 samples 1
    [5398-diag]   surface bytes 0x870000: no pending or live storage image covers the range
    [5398-diag] depth-target history for 0x11c10f0000: 0 of 0 distinct depth-target bases bound so far (0 binds in all) are this address, its stencil plane or contain it; 0 of 0 depth surface list entries match
    [gpu] driver failure: compute shader 0x1150101000: AGC graphics: 32-bit integer read of the depth-layout texture 0x11c10f0000, which is no depth surface drawn with, is not implemented
    
    diff --git a/core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp b/core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
    index 2f54bee30..e5f41c679 100644
    --- a/core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
    +++ b/core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
    @@ -8,6 +8,7 @@
     #include <memory>
     #include <optional>
     #include <span>
    +#include <string>
     
     namespace AgcDriver::Graphics {
     
    @@ -26,6 +27,7 @@ void RequireNoNativeDepthFeedback_nid_no_patch(const Context& context, const Dep
     void ClearDepthSurfaces(VkDevice device);
     void RetireDepthSurfaces(VkDevice device, std::uint64_t address, std::uint64_t bytes);
     bool DepthSurfaceAt(std::uint64_t address);
    +std::string DepthTargetHistory(const Context& context, std::uint64_t address);
     bool DepthSurfaceAt(const Context& context, std::span<const std::uint32_t> words, const GuestTextureResource& resource);
     std::uint64_t HtileDepthClearAddress(std::span<const std::uint32_t> code, std::span<const std::uint32_t> userData, const std::array<std::uint32_t, 3>& numThreads);
     std::size_t HtileDepthClearBytes_nid_no_patch(std::span<const std::uint32_t> code, std::span<const std::uint32_t> userData, const ShaderRecompiler::ShaderComputeStageInfo& compute, std::span<const std::uint32_t> packet, std::uint64_t indirectArguments);
    diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
    index 4db10e6b7..4615d3c9a 100644
    --- a/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
    +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
    @@ -933,6 +933,41 @@ struct PlaneOwner {
         std::uint64_t serial = 0;
     };
     
    +struct DepthBindNote {
    +    std::uint64_t stencilAddress;
    +    std::uint64_t htileAddress;
    +    std::uint64_t bytes;
    +    std::uint32_t width;
    +    std::uint32_t height;
    +    std::uint32_t samples;
    +    VkFormat format;
    +    std::uint64_t firstBind;
    +    std::uint64_t lastBind;
    +    std::uint64_t binds;
    +};
    +
    +std::uint64_t depthBindSerial = 0;
    +
    +std::map<std::uint64_t, DepthBindNote>& depthBindHistory() {
    +    static auto* history = new std::map<std::uint64_t, DepthBindNote>();
    +    return *history;
    +}
    +
    +void noteDepthBind(const DepthTarget& target) {
    +    const auto serial = ++depthBindSerial;
    +    auto& history = depthBindHistory();
    +    const auto found = history.find(target.address);
    +    if (found != history.end()) {
    +        found->second.lastBind = serial;
    +        ++found->second.binds;
    +        return;
    +    }
    +    if (history.size() >= 4096u) return;
    +    const bool d16 = target.format == VK_FORMAT_D16_UNORM || target.format == VK_FORMAT_D16_UNORM_S8_UINT;
    +    const auto bytes = target.samples == 1u ? DepthSliceBytes(target.extent, d16 ? 2u : 4u) : MultisampledDepthBytes_nid_no_patch(target.extent, d16 ? 2u : 4u, target.samples);
    +    history.emplace(target.address, DepthBindNote{target.stencilAddress, target.htileAddress, bytes, target.extent.width, target.extent.height, target.samples, target.format, serial, serial, 1u});
    +}
    +
     using PlaneOwners = std::map<std::pair<VkDevice, std::uint64_t>, PlaneOwner>;
     
     std::uint64_t planeBinds = 0;
    @@ -1214,6 +1249,7 @@ VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target)
             surface = surfaces().back().get();
         }
         surface->retired = false;
    +    noteDepthBind(target);
         const auto owner = depthOwners().find({context.device, target.address});
         const bool inherits = owner != depthOwners().end() && owner->second.surface->active->load(std::memory_order_acquire) && !owner->second.surface->retired;
         surface->clearDepth = target.clearDepth;
    @@ -1519,6 +1555,47 @@ bool DepthSurfaceAt(std::uint64_t address) {
         return std::any_of(surfaces().begin(), surfaces().end(), [&](const auto& surface) { return surface->active->load(std::memory_order_acquire) && !surface->retired && (surface->target.address == address || surface->target.stencilAddress == address); });
     }
     
    +std::string DepthTargetHistory(const Context& context, std::uint64_t address) {
    +    std::lock_guard lock(surfacesMutex());
    +    std::string out;
    +    char line[512];
    +    const auto& history = depthBindHistory();
    +    std::size_t matches = 0;
    +    std::uint64_t binds = 0;
    +    for (const auto& [base, note] : history) {
    +        binds += note.binds;
    +        const bool exact = base == address;
    +        const bool stencil = note.stencilAddress != 0 && note.stencilAddress == address;
    +        const bool inside = address > base && address < base + note.bytes;
    +        if (!exact && !stencil && !inside) continue;
    +        ++matches;
    +        std::snprintf(line, sizeof(line), "[5398-diag]   bound depth target base 0x%llx (%s): stencil 0x%llx htile 0x%llx %ux%u samples %u vk format %d depth bytes 0x%llx, bound %llu times (bind serial %llu..%llu)\n", static_cast<unsigned long long>(base), exact ? "same base" : stencil ? "its stencil plane" : "address inside its depth plane", static_cast<unsigned long long>(note.stencilAddress), static_cast<unsigned long long>(note.htileAddress), note.width, note.height, note.samples, static_cast<int>(note.format), static_cast<unsigned long long>(note.bytes), static_cast<unsigned long long>(note.binds), static_cast<unsigned long long>(note.firstBind), static_cast<unsigned long long>(note.lastBind));
    +        out += line;
    +    }
    +    std::size_t listed = 0;
    +    for (const auto& surface : surfaces()) {
    +        const auto& target = surface->target;
    +        if (target.address != address && target.stencilAddress != address && !surface->Overlaps(address, 1u)) continue;
    +        ++listed;
    +        std::snprintf(line, sizeof(line), "[5398-diag]   surface list entry: base 0x%llx stencil 0x%llx %ux%u samples %u vk format %d host format %d active %d retired %d same device %d written %llu pendingClear %u\n", static_cast<unsigned long long>(target.address), static_cast<unsigned long long>(target.stencilAddress), target.extent.width, target.extent.height, target.samples, static_cast<int>(target.format), static_cast<int>(surface->hostFormat), surface->active->load(std::memory_order_acquire) ? 1 : 0, surface->retired ? 1 : 0, surface->context.device == context.device ? 1 : 0, static_cast<unsigned long long>(surface->written), static_cast<unsigned>(surface->pendingClear));
    +        out += line;
    +    }
    +    std::snprintf(line, sizeof(line), "[5398-diag] depth-target history for 0x%llx: %zu of %zu distinct depth-target bases bound so far (%llu binds in all) are this address, its stencil plane or contain it; %zu of %zu depth surface list entries match\n", static_cast<unsigned long long>(address), matches, history.size(), static_cast<unsigned long long>(binds), listed, surfaces().size());
    +    out.insert(0, line);
    +    if (matches == 0) {
    +        std::size_t printed = 0;
    +        for (const auto& [base, note] : history) {
    +            if (printed++ >= 64u) {
    +                out += "[5398-diag]   ... (list cut at 64)\n";
    +                break;
    +            }
    +            std::snprintf(line, sizeof(line), "[5398-diag]   seen depth base 0x%llx +0x%llx stencil 0x%llx %ux%u samples %u vk format %d bound %llu times (serial %llu..%llu)\n", static_cast<unsigned long long>(base), static_cast<unsigned long long>(note.bytes), static_cast<unsigned long long>(note.stencilAddress), note.width, note.height, note.samples, static_cast<int>(note.format), static_cast<unsigned long long>(note.binds), static_cast<unsigned long long>(note.firstBind), static_cast<unsigned long long>(note.lastBind));
    +            out += line;
    +        }
    +    }
    +    return out;
    +}
    +
     void RetireDepthSurfaces(VkDevice device, std::uint64_t address, std::uint64_t bytes) {
         std::lock_guard lock(surfacesMutex());
         for (const auto& surface : surfaces()) {
    diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
    index ab7d9b47c..5039551e4 100644
    --- a/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
    +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
    @@ -580,6 +580,21 @@ std::shared_ptr<Texture> cachedTexture(const Context& context, std::span<const s
         }
         const auto depthBitsWidth = words.size() >= 4 ? ShaderRecompiler::DepthBitsTextureWidth(words[1], words[3]) : 0u;
         if (depthBitsWidth == 32u) {
    +        std::array<std::uint32_t, 8> raw{};
    +        for (std::size_t i = 0; i < raw.size() && i < words.size(); ++i) raw[i] = words[i];
    +        std::fprintf(stderr, "[5398-diag] refusing a 32-bit integer read of depth-layout texture 0x%llx: T# dwords %08x %08x %08x %08x %08x %08x %08x %08x (%zu words), caller guestBytes %llu, depthCompare %d\n", static_cast<unsigned long long>(resource.baseAddress), raw[0], raw[1], raw[2], raw[3], raw[4], raw[5], raw[6], raw[7], words.size(), static_cast<unsigned long long>(guestBytes), depthCompare ? 1 : 0);
    +        std::fprintf(stderr, "[5398-diag]   GuestTextureResource: baseAddress 0x%llx width %u height %u depthOrLastArray %u baseArray %u mipCount %u allocatedMipCount %u baseLevel %u lastLevel %u minLod %u tileMode %d (T# sw_mode %u) dimension %d (T# type %u) format %u dstSel %u%u%u%u pipeBankXor 0x%x bcSwizzle %u dccAddress 0x%llx dccAlphaOnMsb %d dccPipeAligned %d iterate256 %d samples %u\n", static_cast<unsigned long long>(resource.baseAddress), resource.width, resource.height, resource.depthOrLastArray, resource.baseArray, resource.mipCount, resource.allocatedMipCount, resource.baseLevel, resource.lastLevel, resource.minLod, static_cast<int>(resource.tileMode), (raw[3] >> 20u) & 0x1fu, static_cast<int>(resource.dimension), (raw[3] >> 28u) & 0xfu, resource.format, resource.dstSelX, resource.dstSelY, resource.dstSelZ, resource.dstSelW, resource.pipeBankXor, resource.bcSwizzle, static_cast<unsigned long long>(resource.dccAddress), resource.dccAlphaOnMsb ? 1 : 0, resource.dccPipeAligned ? 1 : 0, resource.iterate256 ? 1 : 0, resource.samples);
    +        const auto describedBytes = guestBytes != 0 ? guestBytes : DescribeSurface(resource).guestBytes;
    +        const auto pendingStorage = StorageTexture::FindPending(resource.baseAddress, describedBytes);
    +        const auto liveStorage = pendingStorage != nullptr ? nullptr : StorageTexture::FindLive(resource.baseAddress, describedBytes);
    +        const auto* storage = pendingStorage != nullptr ? pendingStorage.get() : liveStorage.get();
    +        if (storage == nullptr) std::fprintf(stderr, "[5398-diag]   surface bytes 0x%llx: no pending or live storage image covers the range\n", static_cast<unsigned long long>(describedBytes));
    +        else {
    +            const auto& written = storage->Descriptor();
    +            std::fprintf(stderr, "[5398-diag]   surface bytes 0x%llx: %s storage image covers it: base 0x%llx %ux%u depthOrLastArray %u mipCount %u tileMode %d dimension %d format %u\n", static_cast<unsigned long long>(describedBytes), pendingStorage != nullptr ? "a pending" : "a live", static_cast<unsigned long long>(written.baseAddress), written.width, written.height, written.depthOrLastArray, written.mipCount, static_cast<int>(written.tileMode), static_cast<int>(written.dimension), written.format);
    +        }
    +        std::fputs(DepthTargetHistory(context, resource.baseAddress).c_str(), stderr);
    +        std::fflush(stderr);
             char text[160];
             std::snprintf(text, sizeof(text), "AGC graphics: 32-bit integer read of the depth-layout texture 0x%llx, which is no depth surface drawn with, is not implemented", static_cast<unsigned long long>(resource.baseAddress));
             throw std::runtime_error(text);

    AI-assisted: yes (Claude Code).

  14. MarcZX10 commented on Oct 18, 2026

    @MarcZX10
    Contributor

    Thanks, this answers the descriptor and ownership questions. The exact T# is Format32UInt with SW_64KB_Z_X, and your bounded history shows no depth target or storage image ever owned that range. That rules out a missed live-depth lookup in these runs and supports reading the guest bytes for this descriptor. Open PR #7346 implements that 32-bit depth-bits guest-memory fallback and adds a matching 32_UINT/Z-swizzle regression. The title-specific result is still pending; if the PR author sends a test build, a rerun on this same setup would validate that the reported NHL stop is cleared.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions