Repository navigation
fix(agc): put a stencil replay shader's guest buffer offsets where its shader data is - #8615
Conversation
|
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.
|
|
Windows run of 895a93e merged onto Built |
…s shader data is A pixel shader whose stencil export is replayed gets a push constant block that ends with the stencil reference word. When its shader data is not in push constants (registration modules give a shader with an image a shader data buffer, and data over the stage push range goes there too), the block holds only that word, and buildPrepare took any non-empty block to mean the guest buffer offsets are in push constants: the draw threw "guest buffer offset lies outside the shader's push constants". Only the stencilReferenceDword words before the reference now count as shader data in push constants; with none, the offsets go to the shader data buffer, where the shader reads them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draw takes an optional fragment push range size. The new case sets it to the stencil reference dword, so the shader data of a pixel shader that reads its color with s_buffer_load_dword through a buffer descriptor in user data is in a buffer with or without the pipeline library, and the reference is the only push constant. The replayed draw must color every pixel from the buffer. Without the buildPrepare fix before it, both stencil replay registrations refuse that draw with "guest buffer offset lies outside the shader's push constants". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
895a93e to
15803c7
Compare
|
Linux AMD run of the same paired protocol, on the driver family none of the runs above covered (RADV): Machine: CachyOS, kernel 7.2.10, GCC 16.2.1, Ninja, Release, Paired run —
One RADV difference worth noting: AI-assisted: yes (OpenCode); both runs and the old-code cross-check were executed on this machine. |
|
In-title datapoint, PPSA20397 (Assassin's Creed Shadows), RTX 3070 + Windows 11. Stacked In the run before this PR was added, |
|
Thanks @blawesom and @akkadbakkad89, I've added both runs to the description. The RADV run is under Tested and GPUs tested. Assassin's Creed Shadows (PPSA20397, #8674) is now among the titles that reach this error with changes not yet on Monster Hunter Wilds (PPSA24191), where I first found this, now reaches it in the title with open pull requests only, no local changes. I ran it on
That is in the description now as well. AI-assisted: yes (Claude Code). The MH Wilds runs are from this machine. |
What
On a device without
VK_EXT_shader_stencil_export, a pixel shader that exports stencil is drawn by replay, which passes the reference in a push constant word after the shader data. When the shader data is not in push constants, that word is the whole push block (stencilReferenceDword0):BindingAllocator::Allocategives a shader data buffer to any shader with an image under registration modules, which follow the pipeline library, and to shader data larger than the stage push range.ShaderResources::buildPreparetook any non-empty push block to mean the guest buffer offsets are in push constants, so such a shader that reads a guest buffer fails withAGC graphics: guest buffer offset lies outside the shader's push constants(byte 64 against a 4-byte block in the first commit's test case).Found while bringing up Monster Hunter Wilds (PPSA24191, #7972) on NVIDIA. On
main1e20650e8with #10304 and the open stencil replay changes (#9317 with #9904, #9393, #9905 and #9906), the title's first replayed draw of an unbounded stencil export throws this error. With this PR, the run gets past it and stops at a later stencil replay check (see Tested). @TheSovietWaffle found the same failure in Onimusha: Way of the Sword (PPSA27836, #5769) on an RTX 3080, running it with a local stack of the open stencil replay changes, and opened #9427 with the same fix; its test case is the second commit here, with them as its author, as they agreed there. @akkadbakkad89 hit it in Assassin's Creed Shadows (PPSA20397, #8674) on an RTX 3070, in a local stack with #9317, #9393, #9904, #9905 and #9906 (see Tested). No title is known to reach this onmainalone. The RTX 5090 used here lacksVK_EXT_shader_stencil_exportand has the pipeline library, so onmainevery replayed stencil export there whose shader uses an image and reads a guest buffer throws.The shader reads the offsets from push constants only when its layout puts the shader data there, and from the shader data buffer otherwise (
EmitShaderDataDwordLoad). For a shader with stencil references,buildPreparenow counts only thestencilReferenceDwordwords before the reference as push constant shader data and, when there are none, writes the offsets to the shader data buffer. Shaders without stencil references keep the current rule.applyShaderDataPatchesand the draw cache's verify comparison also index push bytes by user data slot. For such a shader they reach only the reference word, which replay rewrites before every pass, so they are unchanged.No console reference applies: replay emulates a missing Vulkan extension on the host. Not measured on a console.
Tested
Gentoo Linux, kernel 7.2.8, GCC 16.2.1, glibc 2.43, Release,
BUILD_TESTING=ON, NVIDIA GeForce RTX 5090 (595.99.02). The branch was first tested onmain8727ddb and is now rebased ontomain4777cac; the runs below are on 4777cac unless a bullet says otherwise.core/libs/prx/libSceAgcDriver/tests/execution/StencilReplay.cpp, which removesStencilExportEXTfrom the target so that every device replays. A pixel shaderimage_loads a 64x1 32_FLOAT texture of 1.0 andbuffer_load_dwords through two V#s in user data over one array: the stencil V# starts 4 bytes in (0x30 + x at column x) and the other at the start, so the stencil V# needs a 4-byte offset. It exports the stencil V#'s value as stencil and the texel as color. The case checks that the replayed draw colors every pixel with the texel and that an EQUAL 0x35 probe passes exactly column 5. Onmain8727ddb, a temporary print (since removed) showed where the offset goes: inagc_driver_stencil_replay(pipeline library on) the push block is the reference alone and the offset is shader data byte 64; inagc_driver_stencil_replay_no_gpl(APS5_NO_GPL=1) 17 shader data words precede the reference in push constants and the offset is push byte 84.s_buffer_load_dwordthrough a buffer descriptor in user data, and passes 4 as a new optionalDrawargument,pixelPushBytes, which shrinks the fragment push range to the reference dword, so its shader data is in a buffer with or without the pipeline library. The replayed draw must color every pixel from the buffer.ShaderResources.cppfrommain,agc_driver_stencil_replayandagc_driver_stencil_replay_no_gplboth fail withAGC graphics: guest buffer offset lies outside the shader's push constants: the second commit's case, which runs before the first commit's, fails in both because its shader data is in a buffer either way. With the first commit's test file alone,agc_driver_stencil_replayfails the same way andagc_driver_stencil_replay_no_gplpasses, since without the pipeline library that case's shader data fits in push constants.main8727ddb, before the second commit: with a local change that skips writing guest buffer offsets to the shader data buffer (acontinuebefore the write inShaderResources::buildComplete),agc_driver_stencil_replayfails withpixel (5, 0) is 64, expected drawn: the EQUAL 0x35 probe passes column 6, which read the word before its own.agc_driver_stencil_replay_no_gpl, whose offset is in push constants, passes.ANYPS5_NO_SHADER_CACHE=1,agc_driver_stencil_replayandagc_driver_stencil_replay_no_gplpass in 20 of 20 runs each (ctest --repeat until-fail:20).tools/select_tests.py: 1130, of which 1110 passed, 3 failed and 17 skipped. The skips are the 13video_out_flip_*tests,video_out_frame_dump_queue,video_out_frame_dump_waitandvideo_out_telemetry_caption(no Vulkan surface under the offscreen SDL video driver), andagc_driver_stencil_ref_export(the device lacksVK_EXT_shader_stencil_export). The failures areagc_driver_sample_order,agc_driver_sample_order_grid_referenceandagc_driver_sample_order_recipe_depth_locations; they fail with the same messages withShaderResources.cppfrommain, as test(agc): read the sample order tests' depth through a sampled copy #9056 describes.mainand on this branch withctest -V,VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation,ANYPS5_NO_SHADER_CACHE=1andANYPS5_REQUIRE_VULKAN=1, of 20 focused tests:agc_driver_stencil_*(6),agc_driver_sample_mask_depth_stencil,agc_masked_select,agc_driver_graphics,agc_driver_draw_cache_relocation,agc_driver_draw_cache_reuse*(4),agc_driver_prepared_graphics*(4),agc_driver_prepared_unregistered_graphicsandguest_buffer_reuse. On both, 19 pass andagc_driver_stencil_ref_exportskips. Neither log haswas not found but was requested by env var VK_INSTANCE_LAYERSor aVUID-line, and both have the same 10 layer warnings (Undefined-Value-ShaderOutputNotConsumed, 9 of them the-DynamicRenderingform).tools/check_compile.py --base upstream/main: 2 translation units compile.x86_64-w64-mingw32-g++16.2-fsyntax-only -Wall -Wextrawith the same warnings as theirmainversions. This is a syntax check, not a Windows build or run.tools/check_conventions.pypasses againstmain.main1e20650e8with fix(agc): keep buffer owners when a staged address space dissolves #10304 (e0d6e062a9) merged; without it the title stops earlier onmain, atguest buffer has no GPU ownerin a compute dispatch. On top are fix(recompiler): exempt proven control conditions and own-bit ballots in stencil replay #9317 (d02c6280f5, merged) and each follow-up's own commit (fix(recompiler): accept optional bodies that end the wave through an exit that keeps no lane #9904, fix(recompiler): accept optional-body merges implied by the skip predicate in stencil replay #9393, fix(recompiler): accept optional-body merges of ballot words of the skipped lanes' mask bits #9905 and fix(recompiler): let optional-body merges reach ballots that helper lanes cannot contribute to #9906, cherry-picked). None of the 7 runs stopped on the recompiler refusal thatmainwith fix(agc): keep buffer owners when a staged address space dissolves #10304 stops on (stencil reference export emulation requires a replay-safe pixel shader with late tests).Stencil replay: a draw replays all 256 stencil reference values ...) threwAGC graphics: guest buffer offset lies outside the shader's push constantsin 1 of 2 runs.15803c7f1a) merged as well, no run had the push-constant error. In 2 of 5 runs, that draw got pastbuildPrepare, and the run then stopped at a later stencil replay check,stencil replay refuses depth or stencil feedback reads.sample-preserving guest publication of native multisample depth is not implemented.mainb77bd58, on Windows 11 with an RTX 4070 SUPER (driver 616.92, MinGW-w64 GCC 15.2.0):agc_driver_stencil_replayandagc_driver_stencil_replay_no_gplpassed on both of 2 repeats (comment below). On fix(agc): keep guest buffer offsets in shader data when stencil replay adds a push constant #9427, its own equivalentbuildPreparechange (62a5b6c onmaina6dcea9) with the second commit's case was run by @TheSovietWaffle on Windows 10 (RTX 3080, AMD RDNA 2 iGPU) and by @jotitadev on Linux (RTX 3070, lavapipe):agc_driver_stencil_replayfails without the change and passes with it.15803c7f1a(clean againstmainf075f91737) on CachyOS with an AMD Radeon RX 9070 XT (RADV, Mesa 26.2.4):mainand on this branch under the layer, with noVUID-line.ShaderResources.cppfrommain, bothagc_driver_stencil_replaytests fail withAGC graphics: guest buffer offset lies outside the shader's push constants.agc_driver_stencil_ref_exportruns instead of skipping.0x407321e400failed withAGC graphics: guest buffer offset lies outside the shader's push constants.0x407325e400and stopped at a later check (stencil replay refuses sampled depth-surface feedback).0x407321e400didn't come up in that run.ShaderResources.cpp:!shader.program->dataAddressPushto the sameif (!push.empty())condition and conflict withmain.Not run on macOS or a console; on Windows only as above.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)main: the open stencil replay changes, and for PPSA24191 also fix(agc): keep buffer owners when a staged address space dissolves #10304; for PPSA20397, see Tested)mainb77bd58, the two stencil replay tests); AMD Radeon RX 9070 XT, RADV (Mesa 26.2.4), CachyOS (kernel 7.2.10) (@blawesom:15803c7f1a, the 20 focused tests with the layer); not run on Intel or lavapipe (see Tested for fix(agc): keep guest buffer offsets in shader data when stencil replay adds a push constant #9427's runs)🤖 Generated with Claude Code