Skip to content

feat(agc): blend into 11_11_10 float color targets in the pixel shader - #9020

Merged
oneandonlydean merged 24 commits into
boykopovar:mainfrom
frankea:packed-float-blend
Nov 7, 2026
Merged

oneandonlydean merged 24 commits into
boykopovar:mainfrom
frankea:packed-float-blend

Conversation

@frankea

@frankea frankea commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

A blended or partial write into a one-sample 11_11_10 float color target used to throw (AGC graphics: blending into an 11_11_10 float color target is unsupported). No host format holds this target's bits (red in 31..21, blue in 9..0, the mirror of B10G11R11), so it renders as R32_UINT and fixed-function blending can't apply. This PR blends in the pixel shader instead, through the pixel-interlock merge that JAB-dev's #8564 adds for partial 4_4_4_4 writes. The merge mechanism is theirs; this PR adds blending to it and opens it to mips and 2D array slices.

#8564 and #8563 are in main since dcd7e3a, and this branch merges main 3bd88ca. The changes of this PR are its two commits, 9a7a202 (the blend) and 6f240cb (mips and array slices), plus the resolution of the merge commits, which number this PR's serializer fields after #8564's: frankea/AnyPS5@f5edd53...6f240cb

  • DecodeState turns a blended or partial write into a one-sample 11_11_10 float target into a merge. TargetMerge carries the target's packing and the color equation of CB_BLEND_CONTROL, and its mask is 32 bits wide; ColorTarget.partialWriteMask is 32 bits as well, next to a new mergeBlend. With feat(agc): merge a draw into more than one unclamped normalized color target #12916 in main a draw carries one TargetMerge per merged target, and these fields sit on each entry; a packed merge still merges alone, so an 11_11_10 blend or partial write next to another merged target throws, as a 4_4_4_4 partial write does.
  • The pixel shader unpacks the stored word, evaluates the equation in fp32 and packs the result with the same toward-zero conversion the export path uses, then applies the write mask. The target has no alpha, so destination alpha is 1. MIN and MAX ignore the factors, and a ZERO or ONE factor never multiplies, so an infinite operand doesn't turn into NaN.
  • Mips and 2D array slices: TargetMergeSurface describes the resident image of the whole array (ArraySurfaceForTarget, moved from Draw.cpp to State.cpp and shared) at the drawn mip, so the merge's storage image is the same image the target renders into. EncodeTextureResource encodes a mip range and 2D arrays, and the shader addresses the view's first slice plus gl_Layer, clamped to the view's last slice as the console clamps the render target index to SLICE_MAX, so a guest layer index past the view never reaches outside the image. This applies to one-sample 4_4_4_4 merges too.
  • Still throw: constant color and dual-source factors, multisampled 11_11_10 targets, volume targets, multisampled mips or arrays, and devices without fragmentShaderPixelInterlock. The refusal now names the target's shape.
  • Formats: request serializer 55. main reads feat(agc): merge partial writes into 4_4_4_4 UNORM color targets #8564's merge record from 46 (target, mask, samples, descriptor and the two depth and stencil flags), feat(agc): blend into an unclamped normalized color target in the pixel shader #11684's target blend from 46 as well (bit 16 of the mask word, then its fields after the two flags), feat(agc): merge a draw into more than one unclamped normalized color target #12916's further merges (their count in bits 17-19 of the first record's mask word, then one record each), its depth export bounds from 49, and target flags at the end of the stream from 51 to 54; it rejects 50. At 55 this PR writes each record's mask as a full 32-bit word and, after the two flags, a flag byte that holds what the 46-54 word kept above its mask (bit 0 the blend, bits 1-3 the number of further merges, on the first record), then feat(agc): blend into an unclamped normalized color target in the pixel shader #11684's blend fields when it is set, then this PR's packing, blend control, layered flag and the view's first and last slice; the depth export bounds follow the last record. A version 46 to 54 record (as main writes it) takes the flags from the upper half of its mask word, keeps the 16-bit mask limit, and without a blend reads a merge as a one-slice 4_4_4_4 merge without blending. request_serializer and agc_shader_memory read version 51, 53 and 54 streams as main writes them. Shader disk cache 57 (main is at 56; fix(agc): retire a multisampled color target a write-only storage image overwrites #10049 takes 58; this branch's cache key adds the merge's packing, blend and slice fields). Pipeline journal 16 with sizeof(State) 944 (main is at 15 and 936; feat(agc): merge partial writes into 4_4_4_4 UNORM color targets #8564's 16-bit partialWriteMask becomes 32 bits and mergeBlend follows it).
  • With feat(agc): blend into an unclamped normalized color target in the pixel shader #11684 (oneandonlydean, merged into main on 10/29): its blend into an unclamped normalized target uses the same merge with a float storage image and a stored texel, and this PR's packed merges keep the uint image and the stored word; MergeColorTarget takes feat(agc): blend into an unclamped normalized color target in the pixel shader #11684's path first when its blend is set. ShaderInputInfoBuilder accepts a merge without packing only when it carries feat(agc): blend into an unclamped normalized color target in the pixel shader #11684's blend. TargetMergeSurface now gives every merge, feat(agc): blend into an unclamped normalized color target in the pixel shader #11684's included, the drawn mip and, for a 2D array view, the array's image with the view's slices; the 11_11_10 debt entry says so. feat(agc): blend into an unclamped normalized color target in the pixel shader #11684's UnclampedBlendMask (0xffff) stays unambiguous with the 32-bit mask: a 4_4_4_4 merge with all four nibbles is a full write and never merges, and no 11_11_10 field mask gives 0xffff.
  • With main's ONE/ZERO/ADD rule (such a color equation into a packed target is a plain write) the merge only takes other equations, and with main's staged multisampled 4_4_4_4 partial writes (StagedMerge.cpp) a multisampled 4_4_4_4 partial write still takes that path; 11_11_10 merges stay one-sample.

Tested

  • After merging main 3cb1cd2 and 3bd88ca (head 4ba1676), Apple M5 Max (macOS 27.0.1, x86-64 under Rosetta 2, MoltenVK 1.4.2 from Vulkan SDK 1.4.363.0), each test run three times: request_serializer, agc_shader_memory, agc_driver_graphics, agc_driver_packed_float_blend, agc_driver_packed_float_color_target, agc_driver_packed_unorm4444_color_target and agc_driver_packed_unorm4444_partial_write pass 7/7, and agc_driver_packed_unorm4444_multisample_partial_write skips (no multisampled storage images on MoltenVK). main no longer builds libkernel on macOS (pthread_getattr_np, pthread_getcpuclockid, the Linux signal context, sched_getcpu, RUSAGE_THREAD, environ), so these builds carry a local, uncommitted macOS patch for those calls. The RTX 4090 runs below predate this merge; I will repeat them on it.
  • After merging main ee9a9a6 (head aa1d452; feat(agc): merge a draw into more than one unclamped normalized color target #12916's multi-target merges, see the comments), RTX 4090 (NVIDIA 616.92, Windows 11), each test run three times: the 75 ctest entries of the same 14 targets pass 75/75, and 75/75 under the validation layer (VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, VK_LOADER_DEBUG=layer, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1, ctest -V): 115 Insert instance layer lines, no VUID- line, 39 Undefined-Value-ShaderOutputNotConsumed-DynamicRendering warnings (in the tests main also runs, the counts main shows; 10 in agc_driver_packed_float_blend). main ee9a9a6 passes a 236-entry set holding all of these but agc_driver_packed_float_blend in both runs, with no VUID- line. The shader memory test now also checks one and two merges at serializer versions 49 and 50. Not run on Linux.
  • After merging main bb04a4f (head 237ede9; see the comments for the renumbering and feat(agc): blend into an unclamped normalized color target in the pixel shader #11684), RTX 4090, each test run three times: the 72 ctest entries of 14 targets (request_serializer, agc_shader_memory, agc_shader_disk_cache, agc_driver_pipeline_journal, agc_driver_graphics, agc_driver_key_miss, agc_driver_unclamped_normalized_blend, agc_driver_depth_export_clamp, agc_driver_layered_array_color_draw, agc_driver_packed_float_blend, agc_driver_packed_float_color_target, agc_driver_packed_unorm4444_color_target, agc_driver_packed_unorm4444_partial_write, agc_driver_packed_unorm4444_multisample_partial_write) pass 72/72, and 72/72 under the validation layer (VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, VK_LOADER_DEBUG=layer, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1, ctest -V): 115 Insert instance layer lines, no VUID- line, no was not found but was requested by env var VK_INSTANCE_LAYERS, 39 Undefined-Value-ShaderOutputNotConsumed-DynamicRendering warnings. main bb04a4f passes its 71 entries (no agc_driver_packed_float_blend) in both runs: 110 Insert instance layer lines, no VUID- line, 29 of those warnings. sizeof(State): a macOS probe gives 920 for main (its Linux guard) and 928 for this head (the new guard). Not run on Linux.
  • tests/execution/PackedFloatBlend.cpp (new) against a CPU reference, bit for bit on every pixel: 11 equations, a blended and a plain partial write, a back-to-back chain, two same-draw overdraws of 16 alternating layers, and three array merges (mip 0 of all six slices of a 128x128 array of 8 mips, one layer per slice, the shape Gran Turismo 7 renders; mip 1 of slices 1 to 3 of a 256x256 array; one slice drawn without a layer export).
  • RTX 4090 (NVIDIA 616.92, Windows 11, WinLibs GCC 15.2), head 5990601: agc_driver_packed_float_blend, agc_driver_packed_unorm4444_partial_write, agc_driver_packed_unorm4444_multisample_partial_write, agc_driver_packed_float_color_target, agc_driver_layered_array_color_draw, agc_driver_graphics and agc_shader_memory pass.
  • Linux x86-64 (Docker, emulated on an Apple-silicon Mac): the 35 tests of request_serializer, agc_shader_disk_cache, agc_shader_memory, agc_shader_control_flow, agc_driver_bda_device, agc_shader_replay_requests, agc_driver_graphics, agc_pipeline_journal and agc_driver_prepared_shaders pass.
  • After the main merges, head e554d27 on the RTX 4090: agc_shader_memory, agc_driver_graphics, agc_driver_layered_array_color_draw, agc_driver_packed_float_blend, agc_driver_packed_float_color_target, agc_driver_packed_unorm4444_partial_write and agc_driver_packed_unorm4444_multisample_partial_write pass. The same 35 Linux tests pass on 374556c, the main merge before it.
  • After merging main 7e69be6 (head 4fad5fd) on the RTX 4090: the 49 ctest entries of agc_driver_graphics_tests, agc_shader_memory_tests, agc_driver_pipeline_journal_tests, agc_driver_packed_float_blend_tests, agc_driver_packed_float_color_target_tests, agc_driver_packed_unorm4444_partial_write_tests, agc_driver_packed_unorm4444_multisample_partial_write_tests and agc_driver_layered_array_color_draw_tests pass 49/49, each test run three times (ctest --repeat until-fail:3).
  • Validation layer: VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (Vulkan SDK 1.4.363.0), ANYPS5_NO_SHADER_CACHE=1 and ANYPS5_REQUIRE_VULKAN=1 with ctest -V, on main 83462cc (7e69be6 plus eight commits to tools/ only) (46/46: main lacks the float blend and both 4_4_4_4 partial-write tests) and on this head (49/49). Neither log has was not found but was requested by env var VK_INSTANCE_LAYERS, and neither has a VUID- line. The layer's only messages on this head are Undefined-Value-ShaderOutputNotConsumed-DynamicRendering warnings from the merge tests, where the merged target has no color attachment and the fragment output goes unused: 10 in agc_driver_packed_float_blend, 10 in agc_driver_packed_unorm4444_partial_write and 9 in agc_driver_packed_unorm4444_multisample_partial_write. main logs no validation message in its 46.
  • After merging feat(agc): merge partial writes into 4_4_4_4 UNORM color targets #8564's head d201de3 and main 2259f05 (head 634b3dc) on the RTX 4090: the 56 ctest entries of agc_driver_graphics_tests, agc_shader_memory_tests, agc_driver_pipeline_journal_tests, agc_driver_packed_float_blend_tests, agc_driver_packed_float_color_target_tests, agc_driver_packed_unorm4444_partial_write_tests, agc_driver_packed_unorm4444_multisample_partial_write_tests, agc_driver_packed_unorm4444_color_target_tests, agc_driver_layered_array_color_draw_tests, request_serializer_tests, agc_shader_disk_cache_tests and agc_driver_key_miss_tests pass 56/56, each test run three times. Under the validation layer, with the settings above: this head 56/56 and main 9d6adeb 54/54 (main lacks the float blend test and feat(agc): merge partial writes into 4_4_4_4 UNORM color targets #8564's three); no VUID- line in either log, and this head's only messages are the same 29 Undefined-Value-ShaderOutputNotConsumed-DynamicRendering warnings.
  • After merging main 0db47b2 (head a51e479; the only conflict was the disk cache format), RTX 4090: the same 56 ctest entries pass 56/56, each test run three times, and 56/56 under the validation layer with no VUID- line (the same 29 warnings); main 0db47b2 54/54 and 54/54 under the layer, no VUID- line.
  • After merging feat(agc): merge partial writes into 4_4_4_4 UNORM color targets #8564's head 3a66884 (which takes disk cache format 46 and merges main) and main 513ca7e (head 6806092; no textual conflicts, and the disk cache format moves to 47), RTX 4090: the same 56 ctest entries pass 56/56, each test run three times, and 56/56 under the validation layer with no VUID- line (the same 29 warnings). The head also merges cleanly with main 58ceeb8.
  • After merging main 379b1dc (head 5e04550), which has feat(agc): merge partial writes into 4_4_4_4 UNORM color targets #8564's final head: this PR's serializer fields move to version 47 and the disk cache stays at 47 over main's 46; the journal is 10 and sizeof(State) 832 over main's 9 and 824. request_serializer and agc_shader_memory now also check that a version 47 record carries the packing, blend control and slice bytes, that a version 46 record with a merge reads as 4_4_4_4 without blending, and that a version 46 record whose mask is wider than 16 bits is refused. RTX 4090: the 59 ctest entries of the same targets (main added three since the last run) pass 59/59, each test run three times, and 59/59 under the validation layer with no VUID- line (the same 29 warnings). Built with Apple clang on macOS, main's RequestSerializerTests.cpp aborts against this head's serializer (it expects version 46), and this head's passes. The head also merges cleanly with main 9c85790.
  • After merging main 732ab06 (a657def): the only conflict was the journal's sizeof(State) guard, now 848. main had meanwhile moved the pipeline journal to format 10 and the shader disk cache to 47 for its own changes, the numbers this PR used, so the merge kept both lines without a conflict. 5f72874 moves them to 11 and 49. The request serializer stays at 47; main's is still 46. RTX 4090, head 5f72874: the 65 ctest entries of the same targets (main added six since the last run) pass 65/65, each test run three times, and 65/65 under the validation layer with no VUID- line (the same 29 warnings). main 3af09d9, on the targets it has plus agc_driver_sample_mask_draw_tests and agc_driver_stencil_known_replace_tests: 66/66, three times each, and 66/66 under the layer with no VUID- line (19 Undefined-Value-ShaderOutputNotConsumed-DynamicRendering warnings, from its own two 4_4_4_4 partial-write tests). The head also merges cleanly with main 504ea3b, whose newer commits change no AGC code.
  • @Celegans12 ran the same comparison for feat(agc): blend into 10_11_11 unorm color targets in the pixel shader #9748 on an RTX 3080 Laptop (driver 610.62), with this PR's previous head aab4fb4 among the trees: no VUID- errors. The layer's one message there is Undefined-Value-ShaderOutputNotConsumed-DynamicRendering, 10 per merge test, because the merged target has no color attachment and the fragment output goes unused.
  • sizeof(State) is 848 on Linux x86-64 after the latest merge: main's 840 plus a 32-bit partialWriteMask and mergeBlend (feat(agc): merge partial writes into 4_4_4_4 UNORM color targets #8564's 16-bit mask keeps main's size). A probe built on macOS gives the Linux guards' values for main 732ab06 (840) and this PR's previous head 5e04550 (832), and 848 for this head. Not built on Linux since the merge.
  • Gran Turismo 7 (PPSA01317) on the RTX 4090, with an earlier state of these commits (before the main merge and the layer clamp) and fix(agc): raise no end-of-pipe event from flips and carry the release's interrupt context #7978, fix(agc): write a replace blend into a packed color target without blending #7243, feat(agc): render layered draws into a depth view of several slices #7256 and fix(shader): answer image_get_resinfo on any T# dimension #7550 merged locally: past the 11_11_10 blend stop and the cube-map target, the main menu at 4.4 FPS. With scripted input it goes on to the World Map, the Used Cars dealer and a car purchase, then stops in the car delivery scene on color targets with fewer fragments than samples (EQAA) are unsupported, which this PR doesn't touch.

Checklist

A blended or partial write into a one-sample 11_11_10 float target goes
through the pixel-interlock merge: the pixel shader unpacks the stored
word, evaluates the CB_BLEND_CONTROL color equation in fp32 and packs the
result toward zero before the write mask. Constant color and dual-source
factors still throw, and so does a mipmapped, volume, array or
multisampled target, now with the target's shape in the message.
A one-sample 4_4_4_4 partial write or 11_11_10 blend into a mip of a
mipmapped target, or into a slice range of a 2D array, now goes through the
pixel-interlock merge instead of throwing. The merge descriptor names the
same whole-array surface as the resident color image at the drawn mip, and
the shader addresses the slice as the view's first slice plus gl_Layer,
clamped to the view's last slice as the console clamps the render target
index to SLICE_MAX. Volume targets and multisampled mips or arrays still
throw.
@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 21, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@github-actions

github-actions Bot commented Oct 21, 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 6858 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 7085 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 7395 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 8939 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 9457 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 9508 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L8197, L8318, L8437, L8439-8440, L8469, L8883-8884
core/shader/recompiler/Recompiler.cpp L1912-1913
core/shader/recompiler/ShaderDiskCache.hpp L16
core/shader/recompiler/tests/RequestSerializerTests.cpp L574-575, L583, L609, L669-670, L686, L825-826, L918-919, L938-939, L984-987, L998-1000, L1016-1017
PR 9633 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 9748 core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_packed_float_blend_tests.cmake
core/libs/prx/libSceAgcDriver/tests/execution/PackedFloatBlend.cpp
PR 9749 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 9790 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 9895 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp L38
PR 9969 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 11551 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L8197, L8318, L8437, L8439-8440, L8469, L8610, L8883
core/shader/recompiler/tests/RequestSerializerTests.cpp L113-114, L118-119, L319, L368, L403, L542, L574-575, L577, L583, L597-598, L609, L636, L670, L686, L826, L918-919, L939, L960, L985, L999, L1016-1017
PR 14032 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 14561 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L8197, L8318, L8439-8440, L8469, L8883
core/shader/recompiler/tests/RequestSerializerTests.cpp L319, L368, L403, L542, L574-578, L583, L609, L636, L670, L686, L826, L939, L960, L985, L999, L1016-1017
PR 14636 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 14871 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 15343 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L8197, L8318, L8437, L8439-8440, L8469, L8883-8884
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp L901, L956
core/shader/recompiler/ShaderDiskCache.hpp L16
core/shader/recompiler/tests/RequestSerializerTests.cpp L319, L368, L403, L542, L574-577, L583, L609, L636, L670, L686, L826, L939, L960, L985-986, L999-1000, L1016-1018
PR 15458 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L8197, L8318, L8437-8439, L8468-8469, L8882-8883
core/shader/recompiler/tests/RequestSerializerTests.cpp L574-575, L583, L609, L686, L825-826, L998-999
PR 15555 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 16472 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 16631 core/shader/recompiler/ShaderDiskCache.hpp L16

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 1368 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5021 core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 5371 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 5609 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
PR 5925 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/libSceAgcDriver.md
PR 6186 docs/dev/debt/libSceAgcDriver.md
PR 6188 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/shader/recompiler/Recompiler.hpp
PR 6194 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
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 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 6412 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 6416 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 6481 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6804 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6924 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 7275 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7410 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/tests/RequestSerializerTests.cpp
docs/dev/debt/shader.md
PR 7449 docs/dev/debt/libSceAgcDriver.md
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7622 core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7684 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 7689 core/shader/recompiler/Recompiler.hpp
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/tests/RequestSerializerTests.cpp
docs/dev/debt/shader.md
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 9356 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9748 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestTextureResource.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_packed_float_blend_tests.cmake
core/libs/prx/libSceAgcDriver/tests/execution/PackedFloatBlend.cpp
core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 9852 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 9893 docs/dev/debt/libSceAgcDriver.md
PR 9915 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10233 core/libs/prx/libSceAgcDriver/Graphics/src/GuestTextureResource.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 10249 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
PR 10359 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/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10442 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 10652 core/shader/recompiler/CacheKey.hpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
docs/dev/debt/shader.md
PR 10678 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 10757 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
PR 11452 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 11483 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/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/shader.md
PR 11825 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 12324 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
PR 12619 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
PR 12828 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
PR 12904 docs/dev/debt/libSceAgcDriver.md
PR 13148 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13793 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13796 core/libs/prx/libSceAgcDriver/Graphics/src/GuestTextureResource.cpp
PR 13809 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13847 docs/dev/debt/shader.md
PR 13863 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13920 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13928 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13929 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14051 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 14137 docs/dev/debt/libSceAgcDriver.md
PR 14212 docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 14296 docs/dev/debt/libSceAgcDriver.md
PR 14344 docs/dev/debt/libSceAgcDriver.md
PR 14377 docs/dev/debt/shader.md
PR 14853 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 14944 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/libSceAgcDriver.md
PR 15059 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
PR 15136 docs/dev/debt/libSceAgcDriver.md
PR 15169 docs/dev/debt/libSceAgcDriver.md
PR 15529 docs/dev/debt/libSceAgcDriver.md
PR 15548 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
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/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
core/shader/recompiler/tests/RequestSerializerTests.cpp
docs/dev/debt/libSceAgcDriver.md
PR 15570 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp

…ed-float-blend

# Conflicts:
#	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/Translation/src/ShaderInputInfoBuilder.cpp
#	core/shader/recompiler/tests/RequestSerializerTests.cpp
#	docs/dev/debt/libSceAgcDriver.md

@CnRJay CnRJay left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing a thrown refusal with a working blend is worth having (GT7 gets past the 11_11_10 stop to its main menu), and building on #8564's interlock merge is reasonable. The cost of that mechanism is not in either PR.

  • A blended draw into this target now runs its pixel shader in a fragment-shader-interlock critical section with early fragment tests forced, and for multisampled targets with per-sample shading. Interlock serializes overlapping fragments of the same pixel, and forcing early fragment tests changes when depth is tested relative to the shader's discards; on a blend-heavy pass (particles, UI, fog) that can be much slower than fixed-function blending. The description's only speed figure is "main menu at 4.4 FPS" in GT7 on an RTX 4090 with an earlier state of the commits. Please post the summary lines of the same scene with and without the blend path (the unsupported draw can be skipped with a switch for the comparison), and Graphics.Draw per frame, so the cost is known before titles depend on it.
  • State which GPUs support fragmentShaderPixelInterlock and what happens on those that do not (the previous behavior was a clear throw; the replacement should be too, with a message that names the missing feature), including lavapipe, which the tests run on.
  • The 2,961 lines include #8563 and #8564 "unchanged". Rebase onto them once they merge so this PR's two commits are what is reviewed; as it stands this PR is marked conflicting and cannot be tested as a unit.

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

frankea commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

@CnRJay thanks, all three points are fair. In order:

Cost in GT7. Here is the same scene with and without the blend path, from the same build: Gran Turismo 7 (PPSA01317 01.710.000) idling on its main menu with no input, RTX 4090 (NVIDIA 616.92), Windows 11, Ryzen 7 5800X, 3840x2160 output, warm shader cache. The build is this PR before its main merge, plus what GT7 needs to reach the menu (#9068's two fixes, #7978, #7243, #7256, #7550, and a local change that draws a partially resident depth target whose pages are all committed) and local diagnostics. For "without", a local switch that is not in this PR (APS5_REFUSE_PACKED_MERGE) throws for any pixel stage that would merge, and APS5_SKIP_REFUSED_DRAWS=1 skips those draws. Both configurations set APS5_SKIP_REFUSED_DRAWS=1 and APS5_TRACE_SUMMARY_EVERY=10. They also set two local switches for later GT7 stops (APS5_SKIP_REFUSED_DISPATCHES, APS5_A2C_UNDITHERED), and neither fires in these runs. Two runs of each, alternating; each value is the median of the 10 s interval lines from 240 s to 510 s after the first present, when the menu is steady:

run frame p50 (ms) p90 p99 GPU busy per present (ms) Graphics.Draw per frame (ms) Driver.Packet per frame (ms)
without, run 1 221.5 228.5 234.7 67.1 134.4 256.3
with, run 1 220.4 226.9 234.9 67.1 133.6 254.8
without, run 2 222.9 230.3 236.0 67.2 135.3 257.5
with, run 2 224.3 230.1 236.9 67.4 136.4 259.0

About 12 draws per frame go through the merge here, out of about 1,880, and all of them are this PR's path: blended, layered draws into an 11_11_10 array target, from one pixel shader (0x120af97800). GPU busy per present is the same either way, so in this scene the interlocked merge costs less than the run-to-run spread. But the merged draws are few, and the frame is CPU-bound (queue worker 0 is about 95% busy, Driver.Packet takes about 255 ms per frame), so this scene says little about a blend-heavy pass with large overlapping draws. A skipped draw still goes through decode and capture up to the refusal every frame, so the CPU columns of the "without" rows include part of those draws' cost; the GPU column doesn't.

For that bound I added a timed overdraw case to the GPU test, aab4fb4: agc_driver_packed_float_blend_tests --benchmark-overdraw, which CTest doesn't run. It records one draw of N full-target triangles with a premultiplied source-over blend (CB_BLEND_CONTROL 0x40000501, the blend of GT7's World Map draw in #9335) into a 2048x2048 tiled target, twice: once as 11_11_10 float through the merge, and once as 10_11_11 float, the same 32 bits in mirrored order, which the host blends itself as B10G11R11_UFLOAT. GPU time comes from the recorder's batch timestamps (APS5_PROFILE_GPU). The time per layer is (N=64 minus N=1) / 63, which leaves out the fixed cost of the batch. Medians of 9 rounds, three runs on the RTX 4090:

path N=1 N=64 per full-target layer fill rate
11_11_10 through the merge 0.060 ms 3.654 to 3.659 ms 0.057 ms 73 Gpixel/s
10_11_11 blended by the host 0.033 to 0.034 ms 1.768 to 1.769 ms 0.0275 ms 152 Gpixel/s

So when every fragment overlaps 63 others in the same draw, the merge blends at about half the host's rate on this GPU: 2.07x the time per layer, the same in all three runs. At GT7's 12 merged draws per frame that disappears in the noise, as above. A full-screen particle or fog pass with heavy overdraw into an 11_11_10 target would take about twice as long as fixed-function blending. I only measured the RTX 4090.

One summary line of each configuration
{"commit":"6b2abf6280b2","dirty":false,"env":{"APS5_A2C_UNDITHERED":"1","APS5_COUNT_PACKED_MERGES":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_REFUSE_PACKED_MERGE":"1","APS5_SKIP_REFUSED_DISPATCHES":"1","APS5_SKIP_REFUSED_DRAWS":"1","APS5_TRACE_DIR":"<path>","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4090","driver":"NVIDIA 616.92","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32688,"title_id":"PPSA01317","title":"Gran Turismo® 7","content_version":"01.710.000","resolution":"3840x2160","window":{"spec":"summary_every 10","first_present":6002,"ms":10068.172},"interval_start_s":308.048,"interval_end_s":318.116,"presents":45,"frame_ms":{"p50":223.224,"p90":228.548,"p99":231.352,"max":231.352},"gpu_busy_ms_per_present":67.109,"worker_busy_pct":{"queue worker 0x0":94.996,"queue worker 0x50":16.165,"queue worker 0x51":2.0,"queue worker 0x2a":1.611,"queue worker 0x23":0.137,"queue worker 0x2b":1.064,"queue worker 0x4a":0.0,"queue worker 0x4b":0.362},"top_phases_ms_per_frame":{"Driver.Packet":257.351,"Driver.Packet.draw":136.407,"Driver.Draw":135.473,"Graphics.Draw":134.318,"Graphics.Draw.draw_and_resource_release":122.08,"Driver.Draw.shader_compile_and_link":75.933,"Shader.DrawStage":68.33,"Resources.Complete":66.874},"trace_dropped":false,"trace":""}
{"commit":"6b2abf6280b2","dirty":false,"env":{"APS5_A2C_UNDITHERED":"1","APS5_COUNT_PACKED_MERGES":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_SKIP_REFUSED_DISPATCHES":"1","APS5_SKIP_REFUSED_DRAWS":"1","APS5_TRACE_DIR":"<path>","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4090","driver":"NVIDIA 616.92","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32688,"title_id":"PPSA01317","title":"Gran Turismo® 7","content_version":"01.710.000","resolution":"3840x2160","window":{"spec":"summary_every 10","first_present":6068,"ms":10133.97},"interval_start_s":308.212,"interval_end_s":318.346,"presents":46,"frame_ms":{"p50":220.356,"p90":227.307,"p99":230.243,"max":230.243},"gpu_busy_ms_per_present":67.021,"worker_busy_pct":{"queue worker 0x0":94.948,"queue worker 0x50":16.493,"queue worker 0x51":2.003,"queue worker 0x2a":1.57,"queue worker 0x23":0.063,"queue worker 0x2b":1.069,"queue worker 0x4a":0.007,"queue worker 0x4b":0.33},"top_phases_ms_per_frame":{"Driver.Packet":253.753,"Driver.Packet.draw":137.355,"Driver.Draw":136.429,"Graphics.Draw":133.212,"Graphics.Draw.draw_and_resource_release":120.961,"Driver.Draw.shader_compile_and_link":74.699,"Shader.DrawStage":67.017,"Resources.Complete":65.963},"trace_dropped":false,"trace":""}

On the mechanism:

Devices without fragmentShaderPixelInterlock. That case stays a throw that names the feature. The recompiler throws a partial write of a packed color target needs the fragmentShaderPixelInterlock feature, which the device lacks (#8564's check in SpirvModuleSetup.cpp). #8564's unit test pins it for a 4_4_4_4 merge with a target that lacks the capability, and the 11_11_10 merge goes through the same check. The GPU tests print skipped, the device lacks fragmentShaderPixelInterlock and return the skip code. Which drivers expose the feature:

  • Mesa at 3e32b0e1f: lavapipe always (lvp_device.c), so the CI's lavapipe runs these tests rather than skipping them. ANV always (anv_physical_device.c). RADV on GFX9 and newer when it compiles with ACO (radv_has_pops). NVK, turnip, panvk and honeykrisp don't expose it.
  • MoltenVK 1.4.1: when the Metal device reports raster order groups (MVKDevice.mm).
  • Windows, from the Vulkan Hardware Database's fragmentShaderPixelInterlock listing and its &option=not counterpart: NVIDIA from second-generation Maxwell on; the reports without it are Kepler, first-generation Maxwell, or drivers from 2019 and earlier. Intel from Gen9 on (Broadwell and older lack it). AMD's own driver from around Vulkan driver version 2.0.317 (early 2025), for example the RX 9070 GRE on 2.0.395 and the Radeon PRO W7900 on 2.0.353. It is missing on 2.0.310 and older, for example the RX 7700S on 2.0.310 and the RX 7800 XT on 2.0.299.

So on an AMD Windows driver from before early 2025, GT7 now stops on the interlock message instead of the old 11_11_10 blend message.

#8563 and #8564. Agreed. The branch carries them unchanged so that it builds and tests as a whole. This PR's own change is the two commits in the compare link in the description. I merged current main into the branch today (e554d27), so it no longer conflicts. Once they merge, I'll rebase onto main and drop them.

AI-assisted: yes (Claude Code)

@Celegans12

Copy link
Copy Markdown
Contributor

Ghost of Yōtei (PPSA26344) on plain main (0c6a5bd) stops about 20 minutes into a warm open-world run on AGC graphics: blending into a 10_11_11 unorm color target is unsupported. That's the sibling packed target, so I'd like to cover it on top of your merge instead of adding a second mechanism.

Your blend path already passes the packing through TargetMerge, PackedWriteMask and the merge emitter. As far as I can see, 10_11_11 unorm needs four things on top: decode letting Unorm10_11_11 into the merge, its 10/11/11 fields in PackedWriteMask, unorm unpack and pack in the merge emitter (round to nearest, as the existing export does), and the serializer range. We've carried a working version of that blend in our own tree since 10-12. It uses a separate epilogue, so I wouldn't send it as is, but its CPU reference test (the factor and op combinations Yōtei uses, add and both subtracts) should carry over.

Would you rather fold 10_11_11 unorm into #9020, or should I open a small follow-up with Depends on: #9020 once your stack settles? Either way I'll run it in Yōtei and post the result here. I don't think #7243's ONE/ZERO case covers it: I haven't pinned down the exact blend Yōtei sets on this target yet, but our working version needed real blending.

@frankea

frankea commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

@Celegans12 thanks for the Yōtei report. Please open it as a follow-up with Depends on: #9020; I'd keep #9020 to 11_11_10 float while it's under review. #9020 itself depends on #8564, which is still open, so your PR stacks on both.

Your list matches what I see in #9020's head (aab4fb4):

  • Decode: in DecodeColorBuffer, only an 11_11_10 float target moves the blend into mergeBlend, so a blended 10_11_11 unorm target still reaches blending into a 10_11_11 unorm color target is unsupported. The decode already requires ROUND_MODE 0 for 10_11_11 unorm, which fits your round-to-nearest pack.
  • PackedWriteMask takes 4_4_4_4 unorm and 11_11_10 float only. It needs the 10_11_11 fields: red in the low 11 bits, green in the next 11 and blue in the top 10.
  • Merge emitter: ShaderInputInfoBuilder refuses a blending merge into anything but 11_11_10 float. That's where your unorm unpack and pack go.
  • Serializer: I don't think it needs a change. Since version 44 it reads ColorExportPacking up to Unorm4_4_4_4, which includes Unorm10_11_11, and it reads the merge's blend control unconditionally.

Two limits of #9020 to keep in mind for Yōtei. First, its blend refuses a multisampled 11_11_10 float target, so a multisampled 10_11_11 unorm target would need that case too. The merge as a whole also refuses volume targets and mipmapped or array multisampled ones. Second, the merge needs fragmentShaderPixelInterlock, and devices without it throw.

Post the Yōtei result here or on your PR, whichever you prefer. I can run your branch on an RTX 4090 if that helps.

AI-assisted: yes (Claude Code)

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head aa1d452 merged onto main 9f748f4 · tested 2026-10-30 17:28 UTC · 24 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,398 passed · 3 failed (0 new, 2 also fail on main, 1 unstable on main) · 42 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,443 of 3,021 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (912 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_bda_device 63.3 s, ⚠️ agc_driver_graphics 30.6 s, ⚠️ agc_driver_graphics_maps_fallback 30.5 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_submit_progress_no_timeline: failed in 7 of the last 9 main runs
Failing on main too (2, not counted against this PR)
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 425 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (425 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_array_layer_target_cpu, agc_driver_bda_span_reads_draw_pipeline, agc_driver_bitfield_mask, agc_driver_buffer_atomic_csub, and 417 more
VUID-vkCmdCopyImage-srcImage-01548 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-vkCmdCopyImage-srcImage-01551 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (42)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_msaa_dcc_compared_import_2: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_4: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_8: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fresh: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or plat
Reproduce
git fetch origin aa1d45243d7b000d6add7b1acda2170cd664bd65 9f748f4d8e36ce3714f3b95f3386316e110a9b22
git checkout 9f748f4d8e36ce3714f3b95f3386316e110a9b22 && git merge --no-ff aa1d45243d7b000d6add7b1acda2170cd664bd65
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Thanks for the merge-main. Two things before this can go in, reviewed at aa1d45243d:

  1. The branch conflicts with current main again (RequestSerializer.cpp, RequestSerializerTests.cpp, State.hpp, ShaderMemory.cpp, libSceAgcDriver/CMakeLists.txt). Please merge main once more.

  2. main now writes recompile request version 51 (tessellationEvaluationSubgroups) and rejects 50, which leaves 50 to this PR. After the merge, a stream that a main build wrote as version 51 does not contain this PR's merge fields (32-bit mask, flags byte, packing, blend control, layered, slice range), but version >= 50u would read them from it. Could you write the merged format as version 52, gate this PR's fields on version >= 52u, keep 50 rejected, and add a round-trip case that reads a version 51 request without the new fields?

Celegans12 pushed a commit to Celegans12/AnyPS5-Ghost-of-Yotei that referenced this pull request Nov 1, 2026
Adopt the complete boykopovar#9020 net change on the current main API.
Preserve its per-target merges, normalized blend path and array views.
Keep main replacement writes, volume refusal and compressed journals.
Use request 52, disk 51 and journal 14 for the combined layouts.
This private prerequisite is source adoption, not a new implementation.
Based on frankea/AnyPS5@aa1d452
core/libs/prx/libSceAgcDriver and core/shader (author: frankea).
Original history, authors, dates and messages are retained in the ledger.
AI-assisted: yes
Celegans12 pushed a commit to Celegans12/AnyPS5-Ghost-of-Yotei that referenced this pull request Nov 2, 2026
Adopt the complete boykopovar#9020 net change on the current main API.
Preserve its per-target merges, normalized blend path and array views.
Keep main replacement writes, volume refusal and compressed journals.
Use request 52, disk 51 and journal 14 for the combined layouts.
This private prerequisite is source adoption, not a new implementation.
Based on frankea/AnyPS5@aa1d452
core/libs/prx/libSceAgcDriver and core/shader (author: frankea).
Original history, authors, dates and messages are retained in the ledger.
AI-assisted: yes
Celegans12 pushed a commit to Celegans12/AnyPS5-Ghost-of-Yotei that referenced this pull request Nov 2, 2026
Adopt the complete boykopovar#9020 net change on the current main API.
Preserve its per-target merges, normalized blend path and array views.
Keep main replacement writes, volume refusal and compressed journals.
Use request 52, disk 51 and journal 14 for the combined layouts.
This private prerequisite is source adoption, not a new implementation.
Based on frankea/AnyPS5@aa1d452
core/libs/prx/libSceAgcDriver and core/shader (author: frankea).
Original history, authors, dates and messages are retained in the ledger.
AI-assisted: yes
# Conflicts:
#	core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
#	core/shader/recompiler/tests/RequestSerializerTests.cpp
@frankea

frankea commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean thanks, both done in 4ba1676, which merges main 3bd88ca.

  1. Merged. Besides the version lines, two things needed more than keeping both sides: main's staged multisampled 4_4_4_4 partial writes now take this PR's mask and checks first, then go down main's staged path (11_11_10 merges stay one-sample), and main's ONE/ZERO/ADD rule runs before the 11_11_10 blend check, so that equation is a plain write and the test of it moved to main's expectations.
  2. main had moved on to 54 (the f16 NaN fields) by the time I merged, so this PR writes version 55 and reads its merge fields only from 55; 50 stays rejected. A stream main writes at 51, 53 or 54 has no merge fields and is read the old way. request_serializer now reads a version 51 stream and a version 54 stream without the merge fields and checks that both serialize back to the version 55 stream, and agc_shader_memory reads the merge record as main writes it at 54 and 53. The disk cache is 57 over main's 56, and the pipeline journal 16 with sizeof(State) 944.

Tested on an M5 Max with MoltenVK, each 3 times: the 7 focused entries pass and the multisampled 4_4_4_4 test skips there (details in the description). I'll repeat the RTX 4090 runs on this head.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 6, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

❌ NVIDIA GPU test: build failed

PR head 4ba1676 merged onto main 9fb6149 · tested 2026-11-06 22:40 UTC · 11 min

Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ❌ failed
Tests not run
build: first errors
[6175/8274] Building CXX object core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/MemoryAccounting.cpp.o
[6176/8274] Building CXX object core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/PipelineJournal.cpp.o
FAILED: core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/PipelineJournal.cpp.o 
ccache /usr/bin/g++ -DANYPS5_ENABLE_SPIRV_TOOLS=1 -DAPS5_ENABLE_TIMING_LOG=0 -DlibSceAgcDriver_EXPORTS -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/libs -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/build/core/libs/prx/libSceAgcDriver/generated -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/shader/recompiler/RdnaDecoder/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/3rdparty/Vulkan-Headers/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/3rdparty/SPIRV-Headers/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/build/core/libs/prx/libc/run_report_generated -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/shader/recompiler -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/shader/recompiler/ControlFlow/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/shader/recompiler/IntermediateRepresentation/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/shader/recompiler/Translation/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/shader/recompiler/Optimization/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/shader/recompiler/SpirvBackend/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/3rdparty/glslang -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/Decoder/Png/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/build/3rdparty/SDL2/include -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/build/3rdparty/SDL2/include/SDL2 -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/build/3rdparty/SDL2/include-config-release/SDL2 -I/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/3rdparty/zstd/build/cmake/../../lib -isystem /home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/3rdparty/zstd/lib -isystem /home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/3rdparty/libjpeg-turbo/src -isystem /home/ben/anyps5-gpu-ci/data/trees/pr-9020/build/libjpeg-turbo/include -O3 -DNDEBUG -std=c++20 -fPIC -fmacro-prefix-map=/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/= -MD -MT core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/PipelineJournal.cpp.o -MF core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/PipelineJournal.cpp.o.d -o core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/PipelineJournal.cpp.o -c /home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp:45:29: error: static assertion failed: State changed: update CanonicalPipelineState and the recipe codec
   45 | static_assert(sizeof(State) == 944, "State changed: update CanonicalPipelineState and the recipe codec");
      |               ~~~~~~~~~~~~~~^~~~~~
/home/ben/anyps5-gpu-ci/data/trees/pr-9020/src/core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp:45:29: note: the comparison reduces to '(952 == 944)'
[6177/8274] Building CXX object core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/BarrierBatch.cpp.o
[6178/8274] Building CXX object core/libs/prx/libSceAgcDriver/CMakeFiles/libSceAgcDriver.dir/Graphics/src/MultisampleTextureLayout.cpp.o
Reproduce
git fetch origin 4ba1676e00cf38e9cfb1bc3f06109e17295ea1d3 9fb6149d12d51e8dc769943c828f2f23635acb4d
git checkout 9fb6149d12d51e8dc769943c828f2f23635acb4d && git merge --no-ff 4ba1676e00cf38e9cfb1bc3f06109e17295ea1d3
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

ColorTarget's partialWriteMask is now 32 bits and mergeBlend was added,
so State grows from 944 to 952 bytes; the recipe codec already writes,
reads and canonicalizes both fields.

Co-authored-by: frankea <frankea@users.noreply.github.com>
@oneandonlydean
oneandonlydean dismissed XairRrR’s stale review November 7, 2026 00:27

Both points are met on the current head a5730d0: it now merges cleanly with main (ad8e79f), and it moved to free version numbers (request serializer 55 over main's 54, ShaderDiskCache FormatVersion 57 over main's 56), with the PipelineJournal State size assert updated to 952. Windows build run 42311605065 passed on this head.

The recipe codec now stores partialWriteMask as 32 bits and adds
mergeBlend, so a format 16 journal written before this change would be
read with the wrong field layout. Bump the journal format to 17 so
those files are discarded instead.

Co-authored-by: frankea <frankea@users.noreply.github.com>
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Hi @XairRrR, a correction to my dismissal of your review: your pipeline journal point was still open. The size guard was updated (sizeof(State) == 952 in a5730d0), but FileFormat had stayed at main's 16 even though the recipe codec now stores partialWriteMask as 32 bits and adds mergeBlend. b24fdae bumps it to 17, the next free number (main is at 16 and no open PR takes 17), so journals written in the old layout are discarded instead of misread. Thanks for catching it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build 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.

9 participants