Skip to content

feat(agc): run registered merged hull programs (binary type 3) - #6679

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
SleglJan:pr/merged-hull
Oct 20, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
SleglJan:pr/merged-hull

Conversation

@SleglJan

@SleglJan SleglJan commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

What

PPSA11386 (007 First Light) registers its tessellation hull programs as type 3: one binary with the local and the hull part, addressed through SPI_SHADER_PGM_LO_LS (SH 0x148), with no SPI_SHADER_PGM_LO_HS. The local part runs on the lanes below s3[7:0] and writes LDS, an s_barrier follows, and the hull part runs on the lanes below s3[15:8] and may store the registers the local part filled. main skips type 3 at registration (#1893) and its draw decode asks 0x148 for a type-5 local half, so the title stops in its level load:

registered program refers to an incompatible shader binary type

#3444 handles a header fused at runtime that selects a registered back half; a registered type-3 binary has no back half to select.

Changes:

  • Draw decode: a registered type-3 program at 0x148 gets both the local and the hull role, and the tessellation configuration is marked mergedHull. The hull user-data address (SH 0x102/0x103) is optional for it: s[0:1] take it, without the range check, when the draw sets it and are zero otherwise (the separate hull half keeps requiring and checking it). Type 3 is prepared with its stage group like type 5 and takes its float mode from RSRC1_HS.
  • Local stage: only passes gl_VertexIndex and gl_InstanceIndex in a 16-byte record per input control point.
  • Hull stage: runs the whole program, one invocation per output control point. v2 and v5 come from the record of control point min(gl_InvocationID, inputs - 1), v3 is the relative vertex id, and the LDS becomes a per-control-point output array (ControlShared): a control point writes its own record and reads any record of its patch after the barrier, with the stride taken from the code as for the local stride. Registers live across the barrier stay in the invocation.
  • The hull stage of a merged program runs at one lane per invocation on every device (HostSubgroupSize 1, as vertex programs do without vertex subgroups). Its lanes are gl_InvocationID, not host subgroup invocations, and main's hull lowering already turns every lane-dependent value into a per-invocation one (lane id, own-lane bits) and refuses other lane masks. In the test's merged program the s_cbranch_execz around the local part is the only wave-level operation left: with the device's subgroup it took a subgroup ballot (GroupNonUniform, GroupNonUniformBallot), which lavapipe rejects in the tessellation control stage (subgroup capability 61 is unsupported for shader stage 2). With one lane per invocation the branch tests the invocation's own lane and the module declares no subgroup capability, on lavapipe and on hardware alike.
  • The lowering refuses: more input than output control points; LDS writes outside the own record and reads outside the patch's records; an s_barrier that some invocations do not reach or that sits in a loop; reads or writes of another lane's register (v_readlane_b32, v_writelane_b32, DPP, ds_swizzle_b32, ds_permute_b32, ds_bpermute_b32, v_permlane16_b32), which one lane per invocation does not hold; outputs beyond the device's tessellation control limits; fetch subroutines.
  • Both stages refer to one binary, so a draw lists each code and header region once (AppendProgramMemory, used by the draw and by PrepareGraphicsStages); a request's memory regions must not overlap (RequestMemoryView memory regions overlap otherwise).
  • A CPU-path indirect draw writes its record words (base vertex, start instance, draw index) into every program whose user data holds the register (UserDataWords). The local and hull stages both hold SH 0x10c onwards; main wrote only the first, the local stage, which of a merged program only writes the vertex record. Separate hull halves now get the words in both halves too, as both read the same registers.
  • mergedHull is part of the recompile cache key of the local and hull stages, the draw decode comparison and key, and the request serialization: version 39, a byte at the end of the tessellation configuration.
  • A hull program declares gl_InvocationID when it writes a per-control-point output (ControlOutput, ControlShared), not only when it reads its lane id: those writes are indexed by it.
  • PrepareGraphicsStages takes its memory from AppendProgramMemory too, so it now leaves out empty regions, as the draw already did.

The Merged hull programs entry in docs/dev/debt/shader.md records where this differs from the console: the same control point of the same patch per hull lane, the register layout taken from the separate halves (not measured on hardware), the one-lane wave-mask branch (an invocation whose own lane fails skips the scalar instructions the console runs for the wave) and v_readfirstlane_b32 (the invocation's own value), runtime buffer loads for the vertex fetches, and the optional user-data address.

Overlap (trial merges with git merge-tree of the 98 open PRs that touch the same files, against this branch and against main 3aa4448; 82 give the same result with both, 40 of them merging cleanly):

Tested

  • Rebased onto main ef0eed9, after fix(shader): test an empty exec mask in s_subvector_loop_begin with one compare #7623 changed the debt line next to this change's entry (placement only). There, on the Linux build node, the change's own 12 tests pass (request_serializer, agc_shader_memory, agc_driver_tessellation, agc_tessellation_factor_ring, the agc_driver_prepared_graphics tests, the two journal tests, perf(agc): queue CPU-path indirect draws on the draw pipeline #6931's agc_driver_pipelined_indirect_draw and guest_requested_exit). The wider runs below are on main 3aa4448. feat(shader): emulate barycentrics and per-vertex parameters on the mesh path #6941 took request version 38 there, so this change writes 39 and reads mergedHull only from 39. Both sides wrote 38, so git merged RequestSerializer.cpp without a conflict at the old number; the tests catch that, as they did on the rebase onto feat(agc): remap a viewport depth range the device cannot express into the vertex shader #4650's 35.
  • On main 324e0e4, the previous head (4e7fa2b, version 35): 744 of 762 pass, the same as main 324e0e4. Both fail the same 18: agc_driver_bc_block_copy, agc_driver_depth_compare_copy, agc_driver_guest_memory_lifetime_converted, agc_driver_image_srgb_sample_copy, agc_driver_image_srgb_sample_copy_forced, agc_driver_image_table_vouched_lookups, agc_driver_image_table_vouch_queued_draws, agc_driver_msaa_dcc_clear_2, agc_driver_msaa_dcc_clear_4, agc_driver_msaa_dcc_clear_8, agc_driver_native_depth_bda_clear, agc_driver_native_depth_clear_refusals, agc_driver_native_depth_clears, agc_driver_native_depth_retirement, agc_driver_native_multisample_depth, agc_driver_staged_clear_sampled_read, agc_driver_storage_write_back_overhang, agc_storage_kept_unit_settle.
  • Linux build node: Arch Linux container on a 16-thread Xeon E5-2640 v3, GCC 16.2.1, Release with BUILD_TESTING=ON, lavapipe (Mesa 26.2.4, LLVM 23.1.1). ctest -R 'agc|shader|recompiler|request' on main 92e5041, with the earlier version-31 head:
    • This change: 591 of 601 pass.
    • main: 591 of 601 pass.
    • Both fail the same ten with the same messages: agc_storage_kept_unit_settle, agc_pending_key_stores, agc_driver_bc_block_copy, agc_driver_depth_compare_copy, agc_driver_native_multisample_depth, agc_driver_staged_clear_sampled_read, agc_driver_storage_write_back_overhang, agc_driver_native_depth_retirement, agc_driver_native_depth_clears, agc_driver_native_depth_clear_refusals (most need write watching, which the container does not have).
  • New and extended tests:
    • The merged test programs (MergedHull* in Tessellation.cpp) are written for these tests. Each is an eight-dword entry, then main's LocalCode (without its s_swappc), two dwords of glue and main's HullCode with one LDS read offset changed (LocalCode and HullCode are from the same file). The entry's lane id is HullCode's, and its other instructions are assembled with llvm-mc (gfx1010). MergedHullReadLane's v_readlane_b32 is also assembled with llvm-mc (gfx1030). MergedHullDivergentBarrier inserts an s_barrier. MergedHullRegisters, MergedHullForeignRecord and MergedHullOutsidePatch change a store's registers or an LDS offset by hand. The entry's layout and the vertex-table slots of CheckMergedHullVertexTables follow PPSA11386's merged programs, and the entry's first seven dwords (the lane test) also occur in them; apart from HullCode's own v_mbcnt pair, no run of four consecutive dwords from these programs occurs in the title's shader binaries captured here. The PreparedGraphics.cpp cases use 64 filler words and s_endpgm, as main's Fixture does.
    • agc_driver_tessellation: two merged-hull draws (MergedHullCode, and MergedHullRegisters, whose hull part stores a register its local part filled) checked like the separate-hull draws (RequirePatches); refusals for more input than output control points, an LDS write into another control point's record, an LDS read past the patch's records, a divergent s_barrier and a v_readlane_b32 of lane 0 (which the one-lane emitter would otherwise compile); the merged hull stage compiled with the device target declares no GroupNonUniform capability; registration and graphics ABI resolution of a type-3 stage group (twice, the second from the prepared ABI).
    • agc_driver_prepared_graphics: the decode of a merged hull draw at ABI resolution and at draw time (roles, entry points, user SGPR layout, user-data address set, unset, zero, and set to an unmapped address that the program does not need), its program memory listed once and accepted by RequestMemoryView (and used as the stages' request memory), the user-data words of SH 0x10e in both stages, preparation as two separate stages that the draw reuses, separate halves still decoded as before and still requiring the address; a merged program's vertex tables read from its user-data slots behind the eight hidden words.
    • agc_shader_memory and request_serializer: the mergedHull byte round-trips; version 30, 31, 32, 34, 35, 36, 37 and 38 requests (38 is main's current format; with and without tessellation) read as not merged, keep their fields and re-serialize to the version 39 bytes; the version 39 fixtures; version 40 is rejected. With the field read from version 35 on, as git merged it on the rebase onto feat(agc): remap a viewport depth range the device cannot express into the vertex shader #4650, both fail with RequestSerializer: truncated data.
  • Rebased onto main 1b1f848 (after feat(recompiler): run single-wave wave64 compute programs at one lane per invocation on 32-lane hosts #5405 took version 32), the same node: request_serializer, agc_shader_memory, agc_driver_tessellation, agc_tessellation_factor_ring, the four agc_driver_prepared_graphics tests and guest_requested_exit pass (9 of 9). ctest -R 'agc|shader|recompiler|request': this change 617 of 626 pass, main 1b1f848 built the same way 617 of 626; both fail the same nine (agc_driver_bc_block_copy, agc_driver_depth_compare_copy, agc_driver_native_depth_clear_refusals, agc_driver_native_depth_clears, agc_driver_native_depth_retirement, agc_driver_native_multisample_depth, agc_driver_staged_clear_sampled_read, agc_driver_storage_write_back_overhang, agc_storage_kept_unit_settle).
  • On main eb901bc with the previous head 36529f1, the same node: request_serializer, agc_shader_memory, agc_driver_tessellation, agc_tessellation_factor_ring, the four agc_driver_prepared_graphics tests and guest_requested_exit pass (9 of 9).
  • On the same node and base (main 92e5041, earlier head): main with only the tests that compile there (the type-3 registration case in agc_driver_tessellation, the serializer fixtures): agc_driver_tessellation fails with registered program refers to an incompatible shader binary type, agc_shader_memory with new requests did not use serialization version 31 (39 now), and request_serializer aborts on its version fixture. The other new cases use the new field and functions; with the change and one part reverted at a time, the check written for that part fails: the draw decode not detecting type 3 (agc_driver_prepared_graphics and agc_driver_tessellation: registered program refers to an incompatible shader binary type); no mergedHull byte in the serialization (a merged hull configuration was lost in serialization, request_serializer aborts); the lowering not treating the program as merged (unsupported LDS access in a tessellation stage); the hull stage at the device subgroup size (the hull stage of a merged hull program declares subgroup operations ...); no cross-lane refusal (a tessellation program was accepted although another lane's register: a v_readlane_b32 of lane 0 compiles silently); the program memory without the dedupe (a merged hull draw's program memory does not list each code and header region once); UserDataWords stopping at the first program (an indirect draw's user-data register does not reach both stages of a merged hull program); the hull user-data address required (merged shader user-data address is null); the optional address range-checked (guest memory is not readable at 0x10); the read-past-patch check removed (a tessellation program was accepted although reads LDS outside its patch's control point records).
  • On the same node and base, the hull stage of MergedHullCode without the one-lane layout declared capabilities 61 and 64 with one OpGroupNonUniform* instruction; with its s_cbranch_execz replaced by s_nop it declared neither, so the branch is the only source.
  • Not covered by a test: the Draw.cpp indirect record loop (only UserDataWords is), the draw key's mergedHull, and the refusals for outputs beyond the device limits, a barrier in a loop and fetch subroutines.
  • agc_driver_tessellation takes under 1 s on the node.
  • tools/check_conventions.py --base upstream/main and git diff --check pass.
  • With the previous head 36529f1 on main eb901bc: NVIDIA GeForce RTX 3080 (615.78.08), CachyOS (Linux 7.2.10), GCC 16.2.1, Release with BUILD_TESTING=ON, ctest -R 'agc|shader|recompiler|pm4|draw|position|tess|hull|request':
    • This change: 625 of 627 pass; agc_driver_stencil_ref_export skips and agc_driver_store_over_untracked fails.
    • main built the same way: the same 625 pass, the same skip and the same failure, on the same test list.
    • agc_driver_store_over_untracked fails on both with the result did not reach a block the CPU left alone; Windows: StoreOverUntracked fails at "the first result was not stored" #6347 tracks the same test failing on Windows.
  • PPSA11386 v01.018.000, RTX 3080, in a bubblewrap sandbox, on my bring-up stack: main 4186f06 plus open PRs, unpublished local fixes the title needs, local logging and scripted input, and the title's two feedback-wait limits widened in its executable as described in 007 First Light (PPSA11386): the terrain crash after Resume is a stale read of a GPU feedback buffer past the title's own wait limits #6172 (local only). These runs used the earlier version-31 head, before perf(agc): queue CPU-path indirect draws on the draw pipeline #6931's queued indirect path; the version changes do not touch the draw path.
    • With this change the level load passes and the title reaches gameplay's first tutorial prompt.
    • An earlier main-based stack without a merged-hull change stopped in the level load after present 1188 with registered program refers to an incompatible shader binary type.
    • With this change reverted and feat(agc): draw tessellation followed by an NGG geometry stage #6612 (head 89aa76a) merged instead, which brings main up to 5d9dcc4, the title stops in the level load after present 1195 with merged shader user-data address is null: a merged hull draw there leaves the hull user-data address null.

Checklist

  • Based on current main; feat(agc): draw tessellation followed by an NGG geometry stage #6612 builds on this change
  • 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: PPSA11386 007 First Light (PPSA11386) #5714
  • GPUs tested: lavapipe (Mesa 26.2.4, LLVM 23.1.1), Arch Linux container; NVIDIA GeForce RTX 3080, 615.78.08, CachyOS
  • AI-assisted: yes (Claude Code)

🤖 Generated with Claude Code

@milescoviello

Copy link
Copy Markdown
Contributor

A note on overlap: #6612 (Crimson Desert, PPSA25286, opened 10-15) also takes a registered type-3 program at 0x148 with nothing at 0x108, in the same lines of DrawDecode.cpp (L96-101) and in TessellationLowering.cpp. Whichever lands second needs a rebase.

The two handle it differently. #6612 compiles the program twice: once as the local role, with no hull threads in s3, and once as the hull role, with no local vertices. The values then go through the existing local-to-hull LDS path. That split can't carry VGPRs from the local part into the hull part across the barrier. Your MergedHullRegisters case covers that, and you say 007 First Light needs it, so your approach looks like the more general one.

Crimson Desert's merged hull draw has VGT_LS_HS_CONFIG 0x1043f (63 patches, 4 input and 4 output control points), so your refusal for more input than output control points wouldn't apply to it. Its halves pass 16-bit values through LDS, and #6612 adds 16-bit LDS writes in local programs and reads in hull programs for that. I haven't run it on your path. The title still needs #6612's tessellation-to-geometry path either way, so I can't check it with this PR alone.

If this lands first, I'll move #6612 onto your merged hull, drop its type-3 split, and check that Crimson Desert gets as far as before.

AI-assisted: yes

@github-actions

github-actions Bot commented Oct 16, 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
PR 6639 core/shader/recompiler/tests/RequestSerializerTests.cpp L217, L221-222, L257, L261-262, L283, L407-413, L422, L427-428, L443, L445
PR 6657 core/shader/recompiler/Optimization/src/TessellationLowering.cpp L959-960, L962
PR 6801 core/shader/recompiler/tests/RequestSerializerTests.cpp L217, L221-222, L257, L261-262, L283, L407-413, L422, L427-428, L443, L445
PR 6959 docs/dev/debt/shader.md L172
PR 7410 core/shader/recompiler/tests/RequestSerializerTests.cpp L217, L257, L283, L407-411, L422, L443, L445
PR 7691 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawCache.hpp L13, L46-47
PR 7816 core/shader/recompiler/Recompiler.cpp L146-147
PR 7888 core/shader/recompiler/tests/RequestSerializerTests.cpp L217, L221-222, L257, L261-262, L283, L407-413, L422, L427-428, L443, L445
PR 8077 docs/dev/debt/shader.md L172
PR 8134 docs/dev/debt/shader.md L172
PR 8267 docs/dev/debt/shader.md L172
PR 8489 docs/dev/debt/shader.md L172

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 1896 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 4072 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Translation/src/InstructionTranslator.cpp
PR 5021 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
docs/dev/debt/shader.md
PR 5115 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 5371 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 5404 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 5426 docs/dev/debt/shader.md
PR 5431 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 5441 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 5500 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawDecode.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/StageIO.hpp
core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/debt/shader.md
PR 5609 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawCache.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
PR 5925 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/shader/recompiler/Recompiler.hpp
PR 5941 docs/dev/debt/shader.md
PR 6009 docs/dev/debt/shader.md
PR 6177 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawCache.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawDecode.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
core/shader/recompiler/Recompiler.hpp
PR 6235 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawDecode.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
core/shader/recompiler/Optimization/include/Optimization/ShaderStageInputInfo.hpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/shader.md
PR 6280 docs/dev/debt/shader.md
PR 6290 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6412 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
docs/dev/debt/shader.md
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 6539 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawCache.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
PR 6636 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 6645 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6683 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawDecode.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
core/shader/recompiler/Optimization/include/Optimization/ShaderStageInputInfo.hpp
core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
PR 6867 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 6946 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawCache.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
PR 6947 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawCache.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ProgramMetadata.hpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
PR 6977 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawDecode.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/Translation/src/InstructionTranslator.cpp
docs/dev/debt/shader.md
PR 7085 docs/dev/debt/shader.md
PR 7201 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ProgramMetadata.hpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
PR 7392 core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
docs/dev/debt/shader.md
PR 7395 core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 7446 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
PR 7484 core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
docs/dev/debt/shader.md
PR 7642 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawCache.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ProgramMetadata.hpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
PR 7644 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 7684 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 7689 core/shader/recompiler/Recompiler.hpp
PR 7922 docs/dev/debt/shader.md
PR 8004 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/shader.md
PR 8281 docs/dev/debt/shader.md

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 16, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added shader core/shader docs agc libSceAgc* labels Oct 16, 2026
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 16, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@milescoviello

Copy link
Copy Markdown
Contributor

A heads-up on the request version: #5884 merged with version 31 for MeshConfiguration::outputPrimitiveSize, so main now writes 31 without mergedHull. This PR still merges textually, but it reads mergedHull under version >= 31. A version 31 request from main with a tessellation configuration would then have the byte after its tessellation fields read as mergedHull. I hit it while rebasing #6612 on top of this PR. #6639 has moved its point fields to 32, so whichever of the two lands second would take 33.

AI-assisted: yes

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 16, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SleglJan

Copy link
Copy Markdown
Contributor Author

Thanks @milescoviello, good catch: after #5884 this PR still merged cleanly with main, since both made the same 30 to 31 edits. This PR now writes 32 and reads mergedHull only from 32 on, and a new test checks that main's version 31 requests, with and without tessellation, read as not merged and keep their fields. That test fails with the old >= 31 gate. #6639 and the others that also take 32 are listed under Overlap. #6612's first commit is the old head 8f93aa0, so it needs a restack onto the new one.

AI-assisted: yes (Claude Code)

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 16, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Scramblrrrr

Copy link
Copy Markdown
Contributor

Fresh Windows11/RTX5070Ti617.42 cross-test on current integrationc6bd8b539047dacb9ddc95b41c45e69b78d39f19 (main d9b696d + shared-table/007 boot stack + canonical #6679 36529f1 and #6364 9fffcea; #4339 excluded):30/30 selected native controls PASS15.94s, no skips. Includes storage_flush_ordering, storage_write_back_overhang, depth_storage_dispatch, tessellation, prepared_graphics and its unset/0/1 prebuild cases, serializer, shader memory/disk cache, shared tables and draw-cache checks.

6364 negative control: retained the new fixture and other integration code, removed only FlushPending's PendingWriterSerial/Reap/Sync/FinishUpTo wait block, rebuilt the unpatched driver and ran the fixture. It FAILS in0.37s with storage flush ordering, writer in flight: the pending image's store put its older texels over a newer address-based store. Restored the exact committed Texture.cpp, rebuilt patched modules, and30/30PASS14.53s. Source/conventions clean. This is a wait-only negative in our integration, not a standalone main red/green.

Public branch https://github.com/Scramblrrrr/AnyPS5/tree/codex/first-light-level-two-lane . Matched driver/Agc/VideoOut now staged together, same2GiBfree/28GiBprivate guard. Starting007; title level/cinematic outcome still pending, so the native pass is not claimed as playable gameplay. AI-assisted: Codex; title data local.

@SleglJan

Copy link
Copy Markdown
Contributor Author

@milescoviello #6679 is rebased onto main 1b1f848. #5405 merged with request version 32 (target.spannedWaves), so mergedHull now reads from version 33. The new head is 01947dd. Against 36529f1 it changes only the request version (the writer, the reader limit and the mergedHull gate) and the serializer tests; the rest of the change, the debt entry included, is the same. #6612's first commit, 734a8f5, is 36529f1 rebased onto main 4524944, so it needs another restack, and its first commit should read mergedHull from 33. #6639 and #6801 also write 33 now; whichever lands first keeps it.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 16, 2026
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 17, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 17, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 18, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 18, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 18, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 20, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wachi35676

Copy link
Copy Markdown
Contributor

An AMD data point after the merge. agc_driver_tessellation fails on AMD's proprietary Windows driver, on an AMD Radeon RDNA2 iGPU (1002:13c0, driver 32.0.21042.62, ANYPS5_GPU=AMD), 3 of 3:

AGC graphics: merged hull program, unculled: the level-1 patch was not drawn as one flat triangle, centre (16, 24, 40, 255)

Setup: Windows 11, WinLibs GCC 15.2.0, Release, ANYPS5_REQUIRE_VULKAN=1. The tree is main d073fe6a1 plus #7410, which only touches compute wave64 shared VGPRs. On the RTX 5070 Ti (617.42), the same build passes. I haven't looked into the cause.

AI-assisted: yes (Claude Code); results above were run on this machine.

@SleglJan

Copy link
Copy Markdown
Contributor Author

@wachi35676 thanks for the data point. I can't reach that case on an AMD GPU here. On the Ryzen 9 7950X3D's iGPU (RDNA2, RADV, Mesa 26.2.4), agc_driver_tessellation crashes inside the driver in the fourth separate-hull case (HullDynamicIndex). With APS5_NO_GPL=1 it segfaults too; I didn't trace where. That matches #5444, Mesa 26.2's nir_opt_varyings crash on a hull that reads a control point at a computed index. The build was main 68323ba with #5799, #6868, #5372, #6918, #7643 and #6679 (at 0307183).

The test stops at its first failure, so in your run the separate-hull cases before the merged ones passed. (16, 24, 40, 255) is the test's background colour, so the level-1 patch wasn't drawn at all. The difference is in what the merged lowering adds to the same patches.

Three things on your machine would narrow it down:

  1. Check the pipelineLibrary= value in the device's "Vulkan features" line.
  2. If it's 1, run with APS5_NO_GPL=1, so the draws go without graphics pipeline libraries. If the merged cases then pass, it's the library link on that driver.
  3. Run with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, to see whether any VUID- appears before the failure.

AI-assisted: yes (Claude Code)

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 20, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Regression on AMD (Windows): agc_driver_tessellation fails since this merge on an AMD Radeon RX 6700 XT (gfx1031, AMD proprietary driver 26.8.1, maxMeshOutputLayers 8), Windows 11 22621, WinLibs GCC 15.2 UCRT r7, Release, fresh BUILD_TESTING=ON build:

  • 3177d1989 (this merge's first parent): passes
  • 5ccf1824d (this merge): fails, and still fails on main 57fdffd:
AGC graphics: merged hull program, unculled: the level-1 patch was not drawn as one flat triangle, centre (16, 24, 40, 255)

The tested GPUs above are lavapipe and an RTX 3080, so this may be AMD-specific. I can run a build or a diagnostic on this card if that helps.

@SleglJan

Copy link
Copy Markdown
Contributor Author

@JJenkx thanks for the bisect, and yes, a run on that card would help. An AMD data point from Linux first:

So RADV draws the merged programs. @wachi35676's RTX 5070 Ti passes on the same Windows build, so what you both see points to AMD's proprietary Windows driver. On the RX 6700 XT, the same three checks I asked @wachi35676 for above would narrow it down:

  1. The pipelineLibrary= value in the device's "Vulkan features" line.
  2. If it's 1, a run with APS5_NO_GPL=1. If the merged cases then pass, it's the library link on that driver.
  3. A run with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, to see whether any VUID- appears before the failure.

AI-assisted: yes (Claude Code)

@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

@SleglJan the three checks on the RX 6700 XT (Windows 11 22621, AMD driver 26.8.1, MinGW GCC 15.2 Release), agc_driver_tessellation_tests built from main 6c12024:

  1. "Vulkan features" line: tessellationAvailable=1 mesh=1 depthClip=1 depthRangeUnrestricted=1 pipelineLibrary=1.
  2. Default (pipelineLibrary=1): fails at AGC graphics: merged hull program, unculled: the level-1 patch was not drawn as one flat triangle, centre (16, 24, 40, 255). With APS5_NO_GPL=1 (pipelineLibrary=0): fails at the same check, but the centre is (255, 243, 0, 255). So it is not only the library link. Without libraries something is drawn at the centre, but still not the flat triangle.
  3. Not done: the Khronos validation layer is not installed on this machine (no Vulkan SDK; the only registered explicit layer is a third-party one), so VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation loaded nothing and the zero VUID- count means nothing. I will add it if I can install the layer.

@SleglJan

Copy link
Copy Markdown
Contributor Author

@JJenkx thanks, that helps. The two colours say different things about patch 0:

  • With libraries, the centre is the background, so nothing covers that patch's centre.
  • Without them, the centre is the patch colour with a high green channel. The domain program writes green from the barycentric coordinates, so a flat level-1 triangle has none and that pixel is an interior point.

So patch 0 differs between the two modes on that driver, while NVIDIA and RADV draw it flat. The domain program passed earlier in the same run with the separate hulls, so the difference is in the merged program's local or hull half. Either the merged lowering relies on behaviour Vulkan doesn't guarantee, or the driver mishandles it. I'm reading the lowering now. If a diagnostic build would separate the candidates, I'll push one to a branch on my fork and ask you to run it.

AI-assisted: yes (Claude Code)

@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Correction to my last comment: the APS5_NO_GPL=1 difference does not reproduce. Five more runs each, same build and machine: all ten fail at the same check with centre (16, 24, 40, 255), whether pipelineLibrary=1 or pipelineLibrary=0. The single yellow (255, 243, 0, 255) result was only the first no-library run (possibly the first time those pipelines were built without libraries; not established). So turning off the library link changes nothing on this driver: the merged-hull draw leaves the clear colour either way.

Check 3 is still not done. The only Windows build of the validation layer I could get without the SDK (MSYS2's, 1.4.363) needs the GCC 16 C++ runtime. Loaded into this GCC 15.2 build, it hangs at layer initialization. I will report it if I get a working layer.

@SleglJan

Copy link
Copy Markdown
Contributor Author

@JJenkx thanks for the correction. With the centre background in all ten runs, the library link is out. The validation-layer check waits for a working layer.

A diagnostic build would separate the remaining candidates. The branch diag/merged-hull-amd on my fork is one commit (2127ffe) on main 7ab4b2e.

  • It adds three switches. With all of them off it emits the same shaders as main.
  • APS5_DIAG_MERGED_CONSUME and APS5_DIAG_MERGED_BARRIER change only merged-hull draws; APS5_DIAG_MERGED_READBACK changes every tessellation draw.
  • Any value turns a switch on, 0 included.

From the build directory, with agc_driver_tessellation_tests only. In cmd the binary is tests\agc_driver_tessellation_tests.exe. Set the variables first, and clear the previous switch between runs (set APS5_DIAG_MERGED_CONSUME=).

  1. ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 tests/agc_driver_tessellation_tests
  2. The same with APS5_DIAG_MERGED_CONSUME=1: the domain stage reads the hull's shared records, so that hull output has a consumer.
  3. The same with APS5_DIAG_MERGED_BARRIER=1: the merged hull's barrier gets memory semantics (AcquireRelease | WorkgroupMemory, Device scope).
  4. The same with APS5_DIAG_MERGED_READBACK=1:
    • the hull stores its level source per patch and keeps every patch drawn, and the domain writes that source into the blue channel;
    • each draw then prints a "diag …" line with the three patch centres and coverage counts, its checks no longer stop at the first failure, and the run ends with a summary after the two merged cases.
    • The whole stdout of this run would be the most useful.
  5. Only if run 2 passes: APS5_DIAG_MERGED_CONSUME=place, which moves the records without the consumer.

On a driver that works, runs 1, 2, 3 and 5 print "Tessellation tests passed", and run 4 ends with "20 checks failed, 20 of them the level-0 patch drawn by design" and exits 0. In run 4, patch 0's blue shows what its hull read as the level source:

  • 96 is the right value;
  • 64 means it read 0: an unwritten record, or the level-0 patch's;
  • 223 means it read patch 2's record;
  • 0 or 255 means garbage;
  • (16, 24, 40) is still the background, not a reading.

All five runs pass on an RTX 3080 and lavapipe, and on RADV (gfx1036) with the two computed-index cases skipped locally (#5444). There, run 4 ends 16 of 16. Runs 2–4 under the validation layer on the RTX report no VUID-.

AI-assisted: yes (Claude Code)

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 21, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 21, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 22, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 22, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 23, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 23, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 23, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 23, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 24, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 24, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 24, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 24, 2026
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from boykopovar#6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants