You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Recompiler: a deferred compute shader is dispatched and aborts: s_swappc_b64 through a per-lane function table (Ratchet & Clank: Rift Apart) #3274
This is the follow-up @EdouardSence mentioned in #1817: a shader deferred by #1836 that a title actually dispatches. In Ratchet & Clank: Rift Apart, 98 shaders are deferred with "calls a computed target". Once the title gets far enough (frame ~437, see #3272), one of them is dispatched and the run aborts:
compute shader 0x116bb5d700: ShaderRecompiler::Recompile: computed/data-dependent s_swappc_b64 call target at program counter 0x00001ac4 is not statically resolvable
The call is not a user-data target like #1817 or #2302. It is a function table: each lane reads a 16-byte record from a buffer, takes the 64-bit code address in it, and calls it in a waterfall loop, one group of lanes per distinct entry. This works like a ray-tracing shader binding table or a material function table: the code that runs is chosen per lane at run time. That is the "arbitrary indirect calls" entry in TechnicalDebt.md, so I am filing it as data for that design rather than proposing a patch.
Details
Title: Ratchet & Clank: Rift Apart (PPSA01474, content 01.005.003) Where it stops: frame ~437, 1 of 1 runs with APS5_EAGER_WRITEBACK=1. Without it the title instead freezes at frame 456 (#3272) and never dispatches this shader. AnyPS5 f1ae427b plus local patches (listed in #3272). CachyOS, RTX 4090, driver 615.78.
The call site (described, not the game's code)
The shader is 0x5980 bytes and has one computed call. The block before it does this:
index = v13 + v11 ; per-lane table index
loop:
id = readfirstlane(index)
exec = lanes where index == id
desc = s_load_dwordx4 user_data[12:13] + 0x270 ; buffer descriptor
rec = s_buffer_load_dwordx4 desc, id * 16 ; {target_lo, target_hi, arg0, arg1}
s[14:15] = rec.target ; s[16:17] = rec.args
s_swappc_b64 s[14:15], s[14:15] ; link pair == target pair
restore exec; repeat while lanes remain
The target comes from guest memory through a descriptor read from user data, per lane. It is not s_getpc plus a constant, not a user-data pair, and not a code-resident jump table.
The link pair is the target pair (s[14:15]), and the call returns with the callee's s_setpc_b64.
The same shader also has three bounded s_call_b64 at 0x8ec, 0x4168 and 0x416c that share the link pair s[64:65]. Those may hit the one-call-per-link-pair limit once this one is handled.
What I don't know
The table contents. I didn't capture the dispatch's user data, so I don't know how many distinct callees there are, or whether they are other registered shaders.
I can dump APS5_TRACE_DISPATCH_IO/user data for this dispatch if that helps choose between a per-dispatch callee set and a registered-callee switch.
Related: #1817, #1836, #2062, #2749 (Stray, same message at many PCs), #2302 (closed: per-dispatch inlining).
Tested and written by Claude (AI assistant) on a contributor's machine.
The dispatch trace would be useful for deciding whether this can be implemented and tested safely. Could you share the APS5_TRACE_DISPATCH_IO output or equivalent user-data dump for the failing dispatch, especially the function-table entries (target addresses) and which callees are registered or reached? That should clarify the call targets and give us a concrete regression case.
This blocker now has a merged fix: PR #4706 implements linking for table-loaded s_swappc_b64 targets, including the per-dispatch table callee set. The in-game follow-up on that PR reports Ratchet & Clank no longer aborts with this issue’s computed/data-dependent s_swappc_b64 error and reaches a later descriptor-materialization stop. That later stop is separate from the function-table call covered here. Based on that mainline run, #3274 appears resolved by #4706.
Activity
MarcZX10 commentedon Oct 12, 2026
The dispatch trace would be useful for deciding whether this can be implemented and tested safely. Could you share the
APS5_TRACE_DISPATCH_IOoutput or equivalent user-data dump for the failing dispatch, especially the function-table entries (target addresses) and which callees are registered or reached? That should clarify the call targets and give us a concrete regression case.MarcZX10 commentedon Oct 14, 2026
This blocker now has a merged fix: PR #4706 implements linking for table-loaded
s_swappc_b64targets, including the per-dispatch table callee set. The in-game follow-up on that PR reports Ratchet & Clank no longer aborts with this issue’scomputed/data-dependent s_swappc_b64error and reaches a later descriptor-materialization stop. That later stop is separate from the function-table call covered here. Based on that mainline run, #3274 appears resolved by #4706.fix(agc): store pending storage-image results when a queue has no mor…