Skip to content

shader: a domain program reading a control point at an index computed from data is refused as "not affine", and a computed hull read leaves its patch when the relative patch is also data; fix branch ready #8051

Closed

Description

@TheSovietWaffle

Two related gaps in tessellation lowering's computed control-point reads (#4727, and the select/phi extension 9f429e65a):

  1. Domain reads are refused. Onimusha: Way of the Sword (PPSA27836) picks one of its patch's three control points from data in the first scene: v_cmp results feed v_cndmask/v_add_co_ci to make an index of 0, 1 or 2, and v_lshl_add_u32 scales it by the 32-byte control-point stride before a buffer_load from the off-chip ring. Main refuses it:

    shader stage 3: tessellation lowering: the tessellation ring or LDS address is not affine in the control point and relative patch at pc 0x354
    

    Computed indices are accepted only for hull LDS reads. Also, the index is computed from data the domain program read from its own patch, and independentOfRelative follows that read's address into the relative patch index, so even a hull read would be refused for an index derived that way.

  2. Hull reads point into another patch when the relative patch index is also data. A computed read keeps the program's own address, which contains relative * inputs * localStride. When the program also uses its relative patch index as data, every relative base is replaced by the grouped patch instead of 0, so that term stays and the read lands in another patch's slots. Nothing refuses it.

Fix branch: https://github.com/TheSovietWaffle/AnyPS5/tree/fix/recompiler-domain-computed-control-point (one commit on main 8c9161eac; Optimization/src/TessellationLowering.cpp, SpirvBackend/src/SpirvModuleEmitter.cpp, tests in tests/TessellationLowering.cpp and tests/execution/Tessellation.cpp, the hull input control points entry in docs/dev/debt/shader.md).

  • Off-chip EvaluationInput reads get the same dynamic term as hull LDS reads; it must be a whole number of control points, and the backend clamps the domain gl_in index to the last output control point as it already does for hull reads.
  • A value read from the patch's own ring or LDS no longer counts as depending on the relative patch index: the lowered read takes its patch implicitly.
  • When the relative patch index is used as data, computed reads (hull and domain) subtract their relative patch term before the bases are replaced. Programs that do not use it as data keep the program's own address, as 9f429e65a's tests require.

Checks:

Not verified: the console's result for an index past the patch (the debt entry records the clamp).

AI-assisted: yes (Claude Code).

Activity

  1. MarcZX10 commented on Oct 19, 2026

    @MarcZX10
    Contributor

    I checked the ready branch 8262969c against current main. The implementation diff is clean, but git diff --check upstream/main...<branch> reports trailing whitespace on the newly added lines 105–208 of core/libs/prx/libSceAgcDriver/tests/TessellationLowering.cpp; those lines appear to have CRLF endings. Normalizing that added block to LF should clear the whitespace warnings. No other concern from this check.

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