Skip to content

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

Open
SleglJan wants to merge 1 commit into
boykopovar:mainfrom
SleglJan:pr/merged-hull
Open

SleglJan wants to merge 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:
    • 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 L171
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 8077 docs/dev/debt/shader.md L171
PR 8134 docs/dev/debt/shader.md L171

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 6611 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp
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 6879 core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
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 6970 core/shader/recompiler/Recompiler.hpp
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 7223 core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 7332 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawDecode.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ProgramMetadata.hpp
core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
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
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/shader.md
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 7677 core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
PR 7684 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 7689 core/shader/recompiler/Recompiler.hpp
PR 7831 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
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 7888 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/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/shader.md
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

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>
@SleglJan

Copy link
Copy Markdown
Contributor Author

@milescoviello thanks. The head to restack #6612 on is 3b69fde on main 46f2762, after #6503's version 36 (target.float32FlushToZero, a trailing flag after #4650's depth-remap fields). It writes 37 and reads mergedHull only from 37. In the tests:

  • the flag sits 51 bytes from the end;
  • the old-version loop reads 30, 31, 32, 34, 35 and 36 as not merged;
  • the serializer replay test replays main's version 36 format (main36).

#6801 now also writes 37, and so will #6639 after your rebase. The first of the three to land keeps 37, the second takes 38 and the third 39.

AI-assisted: yes (Claude Code)

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 19, 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 19, 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

@SleglJan thanks for the version map. #6612 now carries 3b69fde's patch unchanged as its first commit (same patch id, rebased as 15949ba), on main f72c7aa, because adriadam10 asked for the quadList conflict with main to be resolved. Its head is 235f513, and the tessellation, journal and request serializer tests pass 3 of 3 there. #6639 takes 37 or 38, whichever of the three is free when it lands, as you laid out.

AI-assisted: yes (Claude Code)

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 19, 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 19, 2026
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 19, 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

@SleglJan a heads-up on versions: main took request version 37 itself, in simonbronk's 7563b4a (stencil operation value export, read if (version >= 37u) into the pixel info). So #6679's 37 now collides with main, and the next free version is 38. My #6639 is moving its point fields to 38 in the rebase I'm testing now. As before, whichever of #6679, #6801 and #6639 lands first keeps 38, and the next takes 39. I'll restack #6612 on your head again once #6679 is rebased.

AI-assisted: yes (Claude Code)

@SleglJan

Copy link
Copy Markdown
Contributor Author

@milescoviello thanks, rebased: the head is 83a04ab on main 0fbfd91. It writes 38 and reads mergedHull only from 38. In the tests:

  • the flag still sits 51 bytes from the end;
  • the old-version loop also reads 37 as not merged;
  • the serializer replay test replays main's version 37 format (main37).

Both conflicts adriadam10 listed on #6612 (Draw.cpp with #6931, and RequestSerializerTests.cpp) are in this PR's commit, and this head resolves them; #6612's own three commits apply onto it without a conflict (git merge-tree). In Draw.cpp: the three record lookups stay UserDataWords(programs, roles, ...), so every program that holds the register gets the word, both stages of a merged hull program included. #6931's lastDrawable scan follows them. Each record's words are patched and its stages rebuilt before the check that queues the last drawable record, so the queued draw carries them. No test covers that path with a merged hull draw yet. The debt entry is also down to 999 characters, under main's 1000-character check (which counts the whole line).

#6941 already writes 38 on a base with #6762. Its version lines are the same as this PR's, so git merges RequestSerializer.cpp between the two without a conflict, and only the tests file stops. #6639 moving to 38 makes three at 38 (#6679, #6941, #6639); #6801 and #7410 still write 37 on bases before #6762, and #7332 reads its two target flags from 38. Whichever lands first keeps 38, the next takes 39, and so on.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 19, 2026
@milescoviello

Copy link
Copy Markdown
Contributor

@SleglJan thanks, that was quick. #6612's three commits apply onto 83a04ab without a conflict here too (77d218a). The graphics, journal, serializer and tessellation runs on it are queued, and I'll push #6612 when they pass. #6639 is now at 38 too (0111965), so of the three at 38, whichever lands first keeps it.

AI-assisted: yes (Claude Code)

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 19, 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 19, 2026
@milescoviello

Copy link
Copy Markdown
Contributor

@SleglJan another version heads-up: #6941 merged at 3:17 PM PDT with request version 38 for its mesh barycentric layout (read if (version >= 38u && reader.ReadBool()) in the graphics section). So #6679's mergedHull at 38 now collides with main, and the next free version is 39. I've moved #6639's point fields to 39 (a255453, pushed), so of the two at 39, whichever lands first keeps it and the other takes 40. In #6941's tests, the old-format fixtures get its field through InsertMeshBarycentricFlag before the version byte is raised, which is where I needed to add it in RequestSerializerTests.cpp. #6612 follows your rebase; I'll restack it once #6679 is on 39.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 19, 2026
@SleglJan

Copy link
Copy Markdown
Contributor Author

@milescoviello thanks, rebased. The head is 3054153 on main 3aa4448; it writes 39 and reads mergedHull only from 39. In the tests:

Both sides wrote 38, so git merged RequestSerializer.cpp without a conflict at the old number, and only RequestSerializerTests.cpp stopped. #6639 and #6801 (on #6639's commits) also write 39, on bases with #6941, and merge the same way against this head, so whichever of #6639 and this change lands first keeps 39. #7332 also writes 39, on a base from before #6941. 3054153 is ready for the #6612 restack. #6612's head 77d218a still carries 83a04ab's version 38 read, which collides with #6941's 38; restacked onto this head it reads 39 with the rest of this change, as #6612 adds no version of its own. Its three commits then conflict only where main changed since 0fbfd91 (CacheKey.hpp, Draw.cpp, DrawCapture.cpp, ShaderValidation.cpp).

AI-assisted: yes (Claude Code)

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 19, 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

@SleglJan thanks. #6612 is restacked onto 3054153 (09356fe, pushed). As you said, it reads 39 with the rest of your change. The four conflicts were all main's mesh barycentric change (#6941), in CacheKey.hpp, ShaderValidation.cpp, Draw.cpp and DrawCapture.cpp, and both sides are kept in each. The graphics, tessellation, journal, serializer, mesh and geometry tests pass, 16 of 16, 3 of 3. The 1.4.363 validation layer gives no messages on your head or on #6612's.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 19, 2026
A registered type-3 hull program holds the local and the hull part of a
tessellation draw in one binary, 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. The draw decode asked 0x148 for a type-5 local half, and
PPSA11386 (007 First Light) stopped in its level load with "registered
program refers to an incompatible shader binary type".

The draw decode now gives a registered type-3 program both the local and
the hull role and marks the tessellation configuration mergedHull. The
local stage only passes gl_VertexIndex and gl_InstanceIndex in a 16-byte
record. The 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 that a control point writes
in its own record and reads in any record of its patch after the barrier.
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). Its lanes are gl_InvocationID, not host
subgroup invocations, so the s_cbranch_execz around the local part tests
the invocation's own lane. With the device's subgroup it took a subgroup
ballot, and lavapipe, whose subgroup stages lack the tessellation control
stage, rejected the draw ("subgroup capability 61 is unsupported for
shader stage 2").

The lowering refuses more input than output control points, LDS writes
outside the own record, reads outside the patch's records, barriers that
some invocations do not reach or that sit in a loop, reads or writes of
another lane's register, outputs beyond the device limits, and fetch
subroutines. Type 3 is prepared with its stage group like type 5 and
takes its float mode from RSRC1_HS. The hull user-data address (SH
0x102/0x103) is optional for a merged program: s[0:1] take it, unchecked,
when the draw sets it and are zero otherwise.

Both stages refer to one binary, so a draw lists each code and header
region once (AppendProgramMemory); a request's memory regions must not
overlap. An indirect draw's record words go into every program whose user
data holds the register, so the hull stage of a merged program reads
them too.

mergedHull is part of the recompile cache key, the draw decode comparison
and the request serialization (version 39).

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 20, 2026
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>
@oneandonlydean oneandonlydean self-assigned this Oct 20, 2026

This branch has not been deployed

No deployments
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.

4 participants