Skip to content

fix(shader): honour SPI_BARYC_CNTL.FRONT_FACE_ALL_BITS for the front-face input - #5314

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
XairRrR:fix/shader-front-face-all-bits
Oct 14, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
XairRrR:fix/shader-front-face-all-bits

Conversation

@XairRrR

@XairRrR XairRrR commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

The pixel shader's front-face VGPR was always +1.0 / -1.0. That is its form only while SPI_BARYC_CNTL.FRONT_FACE_ALL_BITS (bit 24) is clear. With the bit set, a back face reads 0 and a front face non-zero:

  • Mesa 22.0 RADV sets the bit (radv_pipeline.c), and ACO tests the input with v_cmp_lg_u32 0, front_face (aco_instruction_selection.cpp).
  • Current RADV clears the bit and reads the input as a float (fgt 0, and fsign for ±1.0, in ac_nir_lower_intrinsics_to_args.c). That is the form the driver produced until now.

Uncharted: Legacy of Thieves Collection (PPSA05684) sets the bit. Its two-sided cloth shaders enable FRONT_FACE (SPI_PS_INPUT_ENA = 0x1b02, so the input is v5) and test it with v_cmp_lt_u32 0, v5. -1.0 (0xbf800000) is non-zero, so every back face was taken as a front face. The insides of the menu skeleton's rags kept their front normals and were lit white by the spot light behind the cage. With this change the rags render dark, as on the PC version.

Changes:

  • ShaderPixelStageInfo::frontFaceAllBits, decoded from SPI_BARYC_CNTL only when FRONT_FACE is an active input, so contexts without the input don't need the register.
  • The flag is in the request serialization (version 27, after main's version 26 linked call fallbacks, with a version 26 replay case; RequestSerializerTests upgrades older fixtures to version 27), the shader cache key, the draw lookup key and the draw register key comparison. DrawKeyRegisters covers 0x1b6..0x1b8.
  • With the bit set, the translator turns the FrontFacing builtin into 0xffffffff / 0.
  • The exact front value (0xffffffff) is not measured; only back = 0 and front ≠ 0 are sourced. It is listed in docs/dev/debt/shader.md.

Tested

  • Arch Linux, NVIDIA GeForce RTX 4070 Ti SUPER, driver 615.78.08, Release.
  • New agc_driver_front_face_all_bits: a front-facing and a back-facing triangle export the raw front-face VGPR into an R32_UINT target. It expects 0x3f800000 / 0xbf800000 without the bit and 0xffffffff / 0 with it. With the translator change reverted, it fails with with FRONT_FACE_ALL_BITS: the front-facing triangle read FRONT_FACE as 0x3f800000, expected 0xffffffff.
  • agc_driver_graphics decodes the bit (set, clear, and set without the front-face input). agc_shader_memory round-trips the flag and replays a version 26 request.
  • Full ctest: 1179 of 1179 on main 32e810d, before adriadam10's rebase onto version 27 (he re-ran the affected tests on the rebase). tools/check_conventions.py --base origin/main passes.
  • PPSA05684 menu on a local stack (it does not run on main yet, it needs feat(agc): implement image and sampler tables indexed at runtime offsets #757/feat(agc): implement image tables loaded through 64-bit pointers #758): the white rags are gone and the skeleton matches the PC reference.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: PPSA05684 Uncharted: Legacy of Thieves Collection (PPSA05684) on Linux / NVIDIA #4001 (white cloth in the main menu)
  • GPUs tested: NVIDIA GeForce RTX 4070 Ti SUPER, driver 615.78.08, Arch Linux (kernel 7.2.9)
  • AI-assisted: yes

@github-actions github-actions Bot added shader core/shader docs agc libSceAgc* labels Oct 13, 2026
RINNECODER added a commit to RINNECODER/AnyPS5 that referenced this pull request Oct 14, 2026
* fix(agc): accept integer tessellation partitioning

Ported from upstream PR boykopovar#5234, adapted to our triangle/fractional-odd
only tessellation path: VGT_TF_PARAM.PARTITIONING 0 decodes, emits equal
spacing and bounds factors at 64. Metal still refuses guest tessellation
draws in MetalRenderState.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

* fix(agc): accept fractional-even tessellation partitioning

Ported from upstream PR boykopovar#5402 (its integer-partitioning base commit is
the previous commit), adapted to our triangle-only tessellation path:
VGT_TF_PARAM.PARTITIONING 3 decodes, emits fractional-even spacing and
bounds factors at 64. Metal still refuses guest tessellation draws.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

* fix(shader): place hull input components by their offset in the control-point slot

Ported from upstream PR boykopovar#4723 (shader hunk; its Vulkan execution test is
not ported).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

* fix(shader): lower hulls with one input or one output control point (partial)

Ported from upstream PR boykopovar#5457, commits 1, 4 and 5 of 5 (hull exec masks
restored through phis, input stride from the patch term, one output
control point per patch). Vulkan execution-test hunks are not ported.

Skipped from boykopovar#5457, with reasons:
- relative patch index rebuilt as data: needs GE_CNTL.PRIM_GRP_SIZE and
  BREAK_WAVE_AT_EOI in TessellationConfiguration, VGT_LS_HS_CONFIG
  patchesPerGroup and the request key/serializer additions. None of
  these exist on main, which only lowers triangle fractional-odd hulls.
- recording BDA faults in hull programs: drops a refusal whose safety
  rests on upstream hull work we lack; the refusal stays.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

* fix(shader): honour SPI_BARYC_CNTL.FRONT_FACE_ALL_BITS for the front-face input

Ported from upstream PR boykopovar#5314. Tracks SPI_BARYC_CNTL in the draw key and
shader request key, and bumps the request serialization to version 24
(shared with the following slice-offset port, which adds no second bump).

Not ported: the ShaderMemory serializer-version assertions of the PR,
which build on upstream test scaffolding absent from main.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

* fix(shader): propagate color view slice to pixel ancillary input

Ported from upstream PR boykopovar#5500, adapted to main: the draw decode sets the
color view slice as layerBase (the layer-export decode this PR also
touches does not exist on main, so its diagnostic and layers hunks are
skipped). layerBase is added to the pixel info, request key, shader info,
disk cache and pipeline specialization constants. The request
serialization stays at version 24, bumped once by the front-face commit.
The shader disk cache format is bumped to 36.

Not ported: unrelated hunks the upstream commit carried in Recompiler.cpp
(dot-product capability option) and its ShaderMemory serializer tests.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

* test(shader): cover tessellation partitioning, hull slot placement, layerBase and serializer v24

Fix the stale serialization version expectation in the shader memory test,
add pixel ancillary rows with a non-zero layerBase, extract PixelLayerBase
for a derivation test, and point the FrontFace note at TechnicalDebt.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: XairRrR <dev910382@gmail.com>
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@adriadam10 adriadam10 self-assigned this Oct 14, 2026
@XairRrR
XairRrR force-pushed the fix/shader-front-face-all-bits branch from be3c05c to dcf37ed Compare October 14, 2026 18:25
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked on a build merged onto current main: agc_driver_graphics, agc_shader_memory (incl. the version 25 replay), agc_driver_front_face_all_bits and the prepared-graphics tests pass; the flag is in the serialization, shader cache key, draw lookup key and draw register comparison. The only red test in the scoped run, agc_driver_tessellation, segfaults inside libvulkan_radeon.so on a tree without this PR too. Minor: the body says "replays a version 23 request", the test replays version 25. The front value 0xffffffff is unmeasured and listed in the debt file; merging.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
XairRrR and others added 2 commits October 14, 2026 21:37
…face input

The front-face VGPR was always +1.0 / -1.0, which is its form only while
FRONT_FACE_ALL_BITS is clear (current Mesa reads it with fgt 0 / fsign).
With the bit set, as Mesa 22.0 RADV programs it, a back face reads 0 and
a front face non-zero: ACO then tests it with v_cmp_lg_u32 0. Uncharted:
Legacy of Thieves Collection (PPSA05684) sets the bit and its two-sided
cloth shaders test v_cmp_lt_u32 0, so -1.0 (0xbf800000) made every back
face a front face: the insides of the menu skeleton's rags kept their
front normals and were lit white by the spot light behind them.

The pixel stage info now carries the bit (request version 26, cache and
draw keys), the decode reads SPI_BARYC_CNTL when FRONT_FACE is an active
input, and the translator turns the builtin into 0xffffffff / 0. The
exact front value is not measured (docs/dev/debt/shader.md).

AI-assisted: yes
Co-Authored-By: Claude <noreply@anthropic.com>
@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased onto current main, which took serialization version 26 for the linked call fallbacks in the meantime. The front-face all-bits flag is now serialized in version 27 (RequestSerializer.cpp); RequestSerializerTests.cpp and ShaderMemory.cpp follow (upgrade fixtures, the replay case is now a version 26 request, the "unsupported version" fixture is 28). Re-ran agc_shader_memory, agc_driver_graphics, agc_driver_front_face_all_bits, the serializer and prepared-graphics tests on the rebase: green. agc_driver_tessellation still segfaults in libvulkan_radeon.so, as on main. Merging once the full Build is green.

@adriadam10
adriadam10 force-pushed the fix/shader-front-face-all-bits branch from dcf37ed to c22bda1 Compare October 14, 2026 19:40
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#5200 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L2905, L3020-3021, L3023, L3139-3142
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp L341, L393, L765, L798
core/shader/recompiler/tests/RequestSerializerTests.cpp L205-206, L243-244, L267-268, L390-391, L405, L407
#6015 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L2905, L3020-3021, L3023, L3141
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp L341, L393, L765, L798
core/shader/recompiler/tests/RequestSerializerTests.cpp L205-206, L243-244, L267-268, L390-391, L405, L407

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@adriadam10
adriadam10 merged commit 4e210a1 into boykopovar:main Oct 14, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* docs shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants