Repository navigation
feat(shader): execute bounded S_CALL_B64 - #1535
Merged
adriadam10 merged 3 commits intoOct 8, 2026
Merged
Conversation
This was referenced Oct 8, 2026
Sanjaysrinivas
force-pushed
the
feat/shader-static-call
branch
from
October 8, 2026 11:48
b1b432b to
3e14f46
Compare
Sanjaysrinivas
marked this pull request as ready for review
October 8, 2026 11:48
Sanjaysrinivas
force-pushed
the
feat/shader-static-call
branch
from
October 8, 2026 12:23
3e14f46 to
6214d25
Compare
9 tasks done
Sanjaysrinivas
force-pushed
the
feat/shader-static-call
branch
from
October 8, 2026 14:42
6214d25 to
2a3616e
Compare
9 tasks done
Sanjaysrinivas
force-pushed
the
feat/shader-static-call
branch
from
October 8, 2026 15:18
2a3616e to
871e631
Compare
9 tasks done
9 tasks done
Reuse the prerequisite call-region analysis for signed relative calls, including callees after s_endpgm. Lower the saved link as shader base plus PC+4 and reject unsupported targets and call shapes. Add decoder, IR, CFG and Vulkan execution regressions. Seven focused CMake tests pass; five layouts cover 15 dispatches and 3,200 output comparisons on lavapipe. Record ISA sources and native RDNA2/PS5 limits in TechnicalDebt.
Reject tuple and descriptor overlap, wrong-pair returns, relative SGPR reads, reversed regions and ordinary or conditional fall-through into a callee. Preserve the existing scalar write analysis and require exact return-pair matching. Seven targeted regressions fail before these guards and pass afterward. Seven focused CMake tests and 15 SPIR-V validations pass; the execution matrix passes 3,200 comparisons and detects a one-bit expected-output mutation.
ComputeTarget(32) can fall back to the default subgroup size. Report both effective sizes and dispatch the third configuration only when it differs, so duplicate runs do not imply wave32 host coverage. Lavapipe exposes subgroup 8 for both requests: seven CMake checks pass, the distinct matrix passes 1,920 comparisons, ten captured modules validate, and the expected-output negative control fails as intended.
Sanjaysrinivas
force-pushed
the
feat/shader-static-call
branch
from
October 8, 2026 18:29
871e631 to
2b2a0c0
Compare
Collaborator
|
Reviewed on the merge with current |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Execute bounded
S_CALL_B64subroutines through the existing static call/return model. With the prerequisites alone, the relative call decodes but its return is rejected as a dynamics_setpc_b64. This follow-up resolves the static target, saves the next instruction address, links the paired return, and includes forward callees afters_endpgmin decoding.Dependencies: none outstanding. #1217 and #895 have both merged into main. Their duplicate prerequisite commits are dropped from this branch; ebosido444-ai and Kikoarl retain authorship in upstream history. This PR contains only the three bounded-CALL follow-up commits.
Related open PR #1523: its GraphBuilder performance work must preserve the scalar-call metadata now supplied by main and this follow-up's CALL and link-lifetime checks. Neither feature depends on the other. Rebase and combine the precomputed branch-target scans when that contribution lands.
The branch is rebased onto current main
4ddbf0497dbdd16f885fb27d30941a772185370dand contains only the three follow-up commits:The integration keeps upstream CALL decoding, the newer prepared-shader code, and #1217's fetch-shader registration fix and execution regression. External fetch translation remains main's implementation. CALL is handled by the shared bounded call translator with a single switch case. The execution fixture uses descriptor word
0x31016fac, matching main's existing scalar GPU fixtures and their raw-buffer bounds mode; its instruction words and expected arithmetic outputs are unchanged.The new runtime work is in the execution and guard commits; the last commit makes the test evidence reflect actual device capabilities. It reuses the prerequisite analyser and link translation rather than introducing a second call framework. No coverage script or reported percentage is edited.
Semantics come from AMD's RDNA2 ISA reference, sections 3.6.3 (SGPR alignment), 12.2 (
S_CALL_B64) and 12.3 (S_GETPC_B64,S_SETPC_B64,S_SWAPPC_B64). CALL savesPC + 4and uses a signed, dword-scaled relative displacement. LLVM 18 independently assembled all five fixtures for bothgfx1013andgfx1030; all ten.textsections match the test words exactly, with no unresolved text relocations. Assembling a target is an encoding check, not native execution on that target.Supported calls have static targets, distinct ordinary aligned SGPR link pairs, one exact paired return, and nested or disjoint regions. Unsupported targets, recursion, shared links, escaping link values, overlapping tuples/descriptors, relative SGPR reads, and cross-region branches/fall-through throw. The analyser checks all decoded instructions, including unreachable code. Arbitrary indirect subroutines and general call frames remain unsupported. The inherited vertex fetch path remains separately documented in
docs/dev/TechnicalDebt.md.Tested
Current rebase:
2b2a0c09b4238c188b9487ca9d4ad9fb2e609831on main4ddbf0497dbdd16f885fb27d30941a772185370d. Normal Release CMake targets were rebuilt with GCC 13.3 on Ubuntu 24.04/WSL2, SPIRV-Tools integration disabled. All eight focused CTest cases passed three repetitions with Vulkan required, shader caching disabled, and lavapipe, including upstreamagc_driver_scalar_swappc_fetch. The static-call fixture retains five variants, ten dispatches, 480 active lanes and 1,920 output comparisons per execution; both requested host targets report subgroup 8. Fresh full GitHub CI is pending; earlier full CI, native encoding checks and captured modules below identify their original revisions.Earlier validation at head
871e6317(retained for encoding and capture evidence):Ubuntu 24.04 under WSL2, GCC 13.3, CMake 4.4.4, Ninja 1.13.2. Normal Release CMake targets build the shader compiler, driver/runtime dependencies and tests from this worktree. The first configure reused host feature-detection cache values from an earlier build on the same host; compiler and driver objects were built in a new build directory. FFmpeg uses the existing prepared repository dependency package. No old manually linked candidate compiler is used for the CMake tests.
Vulkan execution uses lavapipe / llvmpipe LLVM 20.1.2, physical subgroup size 8.
ANYPS5_REQUIRE_VULKAN=1makes unavailable Vulkan fail rather than skip; shader caching is disabled. No native RDNA2 or PS5 execution, local Windows build, title run, or general indirect-call correctness is claimed. These limits and the supported model are recorded in the existing technical-debt document.At the preceding head
2a3616e9, GitHub Windows builds/tests and all three Relinker jobs passed. The Linux job failed before compilation at the test-registration check:guest_formatting_testswas already registered with CTest but remained in the non-WindowsKNOWN_UNRUNexception list. Upstreammainremoves that stale exception in59fd2022; this refresh picks up that fix by rebasing. The original CI check now passes locally. GitHub CI now passes Linux and Windows builds/tests and all three Relinker jobs at head871e6317(successful workflow run); conventions and the progress report also passed. The seven focused checks ran without skips locally and in Linux CI. Windows CI skipped the Vulkan execution fixtures, so its successful job does not establish Windows GPU execution. The captures below identify the revision tested locally.Build and run the focused checks from a normal checkout with its submodules initialized:
Use the appropriate Vulkan ICD path for the host. The seven checks pass with zero skips. Expected integer results are calculated from runtime input buffers using add/XOR formulas, independently of the translator. The execution matrix is:
Total per final matrix run: 10 dispatches, 480 active lanes, 1,920 output comparisons, plus 640 inactive-output sentinel checks. The backward fixture uses a negative SIMM16. The mixed fixture uses distinct outer/inner link pairs.
Lavapipe reports both its default target and
ComputeTarget(32)as subgroup 8. An earlier matrix executed a third, duplicate configuration and passed 3,200 comparisons; that did not establish a distinct wave32 host path. The final test reports the effective target sizes and runs the additional wave64-on-wave32 case only when it differs from the default target. A genuine 32-wide host path remains untested locally.Before the extension, the existing decoder/SWAPPC/SETPC/branch-past-END checks passed, and the new execution fixture failed on the CALL return at PC
0x34after successfully running SWAPPC. Seven additional cases were each incorrectly accepted before the guard fix; each now throws. These before-fix captures predate the main refreshes; the call implementation and guard test files were unchanged by the main refreshes. The matrix was subsequently deduplicated as explained above.The scalar regression executable accepts the individual case names
tuple,wrong_return,fallthrough,conditional_fallthrough,return_before_target,descriptor, andrelative_read. With no argument it runs every case and the positive tests, including the first and last supported link pairs.An instrumented local copy of the execution fixture captured all 10 modules from the same CMake-built compiler/driver. All validate with SPIRV-Tools under
vulkan1.1spv1.4. File capture is confined to that local diagnostic copy; no test-only dumping interface is added to production code. A negative control flips only the expected first output bit and fails as intended:Fixture assembly used for the independent encoding checks
All fixtures begin with:
The shared callee arithmetic is:
Forward CALL:
Backward CALL places the callee before the caller, initially branching over it. The after-END fixture places the store and first
s_endpgmimmediately after CALL, with the callee and its paired return after that END. The mixed fixture calls its outer region with SWAPPC and an inner region with CALL through s12:s13; the outer region returns through s8:s9. The exact instruction words are in the committedScalarStaticCall.cpp.Final validation captures
Validation revision:
871e6317rebased ontomain4b005b22.The same Linux registration check against the same configured build graph, before and after the upstream script fix:
Reproduction command (run with the script from the indicated revision):
Focused CTest results:
GitHub CI, with each runnable test repeated three times:
Skipped entries are included in CTest totals above. Windows skipped the Vulkan execution fixtures; Linux ran the bounded-call fixture.
Captured module SHA-256 values (fixture order above, wave32 then wave64):
7ea252e211d6859811feb16bd9278cd4ba2a5c03514d4696d7b5488ca060d951239c4683127d3c1e78b0a0592f62a5d6014a41aabd6ad2613e5a63e77a0f1fec7ea252e211d6859811feb16bd9278cd4ba2a5c03514d4696d7b5488ca060d951239c4683127d3c1e78b0a0592f62a5d6014a41aabd6ad2613e5a63e77a0f1fecb92b4d0fdea18b814f223db55962719ade17963ef993aa6d7b1207f459238dfa83511cf385a7e2aa962e81c6a35c85eacb3529eba762e8469e6f8a60e38be3e14d03bc103aa8a145d479bab7163ea93cf977e06a8f29d2be9a5cd8fbdff5f6c30874f20b5e983101c0155688210d16ba569ed205e8d0c66b3d5bee6acc848725460d00fe5881bbde6de9c898388d8f2bb39e958e3154d0c567181a8c34712e728d2bb16c644839e40f93e33982c12e9350103d1a118086d1bf3f7329d3345183The capture copy changes only file output and the optional expected-bit negative control; it links the same CMake-built compiler and driver. Native RDNA2/PS5 validation is absent.
Checklist
main; both former prerequisites are merged, and only the three follow-up commits remain; neither open PR implements this bounded CALL execution follow-up