Skip to content

feat(agc): replay proven finite stencil reference exports - #5466

Merged
adriadam10 merged 15 commits into
boykopovar:mainfrom
fdfawef324:codex/stencil-export-emulation
Oct 14, 2026
Merged

adriadam10 merged 15 commits into
boykopovar:mainfrom
fdfawef324:codex/stencil-export-emulation

Conversation

@fdfawef324

@fdfawef324 fdfawef324 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

Replay finite stencil reference exports on devices without VK_EXT_shader_stencil_export, for a conservative subset of shaders and draws whose equivalence can be proved. This PR establishes synthetic replay cases; it does not establish advancement in Demon's Souls. The title's quad DPP and ballot-based kill early-outs remain refused.

The recompiler proves complete export coverage and at most 16 eight-bit references, and reserves a bounded word in the existing push block. The driver keeps one Vulkan pipeline bound throughout each original draw and preserves instance, primitive and reference order. Both faces retain their stencil operations and masks, including depth-fail replacement. Multiple-reference replay admits direct triangle lists and preserves indexed offsets, base vertex and first instance.

Replay requires deterministic, read-only stages and no attachment feedback. Unsupported topology, indirect/restart draws, multisampling, early/ordered tests, incomplete coverage, unbounded references, side effects and surviving subgroup/helper dependence throw. Guarded read-only SRT faults are checked synchronously before host copyback. The native extension path is retained.

This revision separates the vertex lane-bound fold into #5914 and the empty-image feedback check into dependent #5917. GuardImplies and masked-export coverage helpers remain here because they prove the pixel export coverage needed for replay; the separate vertex optimizer is absent from this diff. Current-main vertex input layouts, sample-location grids and per-sample shading are retained.

The artifact schema uses format 34 and updates docs/dev/ARCHITECTURE.md. It rejects formats 31/32/33 and preserves current main's image-table invocation metadata and mapped persistent-cache tests. Merged #758 uses format 33; #5734 also touches this cache. Format 34 keeps the replay schema distinct. The feedback scan now also checks sampled ImageTable entries using main's validated eight-word image elements.

Tested

  • Rebased on e34c47921; original authors, author dates and full commit messages are preserved. Conventions and diff checks pass.
  • Fresh current-header whole-translation-unit g++ -O3 -fsyntax-only checks pass for Recompiler, the full ShaderDiskCache test, Draw, Pipeline, State and the native replay fixture. The fixture now copies the immutable SPIR-V span into a vector before mutation.
  • Fresh actual IR/optimizer builds and the full replay CPU fixture pass. The frozen export-coverage-disabled and malformed-message controls fail; their compiler-resolved source/header inputs match the current source after only CRLF-to-LF normalization.
  • Matching public layout/codec validation passes for artifact/invocation/result/binding/info/runtime sizes 264/200/472/592/352/48, stencil proof and push-slot fields, both binding layouts, and main's runtime image metadata. Existing artifact round trips, readonly native mapping, retained writer, alias copy-on-write, replace/remove lifetime, hand-built plan graph/metadata, damaged payload and malformed-plan checks pass. Changing only the codec to format 33 fails the explicit format-33 refusal. Fresh selected CPU checks use the whole current cache translation unit, six literal production helper bodies and matching fresh IR providers. Main's table poison/ranges/read ranges, buffer-read metadata and float-mode serialization are preserved. Format-33 and wrong replay-layout selective controls fail. The full frontend-dependent generated-plan suite has not been run on this head.
  • Earlier public synthetic GPU runs checked GPL and APS5_NO_GPL=1, without skips: overlapping primitives/instances, indexed offsets/base vertex, first instance, distinct face operations/masks, truncation, depth-fail replacement, fragment kills, adjacent push data and valid/poisoned SRT handling. These results predate this rebase. This current public head has no fresh native GPU or title run; that validation remains pending. Integration character-creation/FPS results are not evidence for this public head.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw; silent stubs are listed in their library's technical debt
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: synthetic finite-reference stencil replay cases only; no Demon's Souls advancement claimed
  • GPUs tested: NVIDIA GeForce RTX 3060 12 GB, driver 591.86 (32.0.15.9186), Vulkan 1.4.325, Windows Server 2025 10.0.26100 (earlier public/integration runs; current public head CPU-only)
  • AI-assisted: yes

Co-Authored-By: Codex noreply@openai.com

@github-actions github-actions Bot added build shader core/shader docs agc libSceAgc* needs rebase Conflicts with main, rebase needed labels Oct 13, 2026
@fdfawef324
fdfawef324 force-pushed the codex/stencil-export-emulation branch from fff34dc to d87ea1b Compare October 13, 2026 21:43
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 13, 2026
@fdfawef324
fdfawef324 force-pushed the codex/stencil-export-emulation branch from d87ea1b to c7595e9 Compare October 13, 2026 23:21
@fdfawef324
fdfawef324 force-pushed the codex/stencil-export-emulation branch from c7595e9 to 63368e1 Compare October 14, 2026 00:58
@tibzejoker

Copy link
Copy Markdown
Contributor

Intel run for this PR: Intel UHD Graphics 770 (Raptor Lake iGPU of an i9-13900K), driver 32.0.101.6129, Windows 11, MinGW-w64 GCC 15.2.0 Release, device picked with ANYPS5_GPU=Intel, at head 63368e11e.

  • agc_driver_stencil_replay and agc_driver_stencil_replay_no_gpl pass, as do agc_masked_select and agc_driver_graphics.
  • ctest -R "agc_driver|agc_masked|agc_shader" -j4: no failures out of 390 (362 pass, 28 skipped). These are the same 28 skips as main has on this GPU (f64, 64-bit and float atomics, fp16 interpolation and dot, mesh, shader clock and the like, which it does not support), and no new ones.

AI-assisted (Claude Code).

@fdfawef324

Copy link
Copy Markdown
Contributor Author

Thanks for testing head 63368e1. I have recorded the Intel UHD 770 result separately from the local RTX 3060 matrix: both stencil pipeline modes and the masked-select/graphics checks passed, with 362 passes and the same 28 main-branch skips in the broader selection. The current rebase also needs compatibility checks for the disk resource-plan format that merged into main; those CPU results will be reported separately. A further vertex-mask case is being verified and is not covered by the tested head.

@fisherjoey

Copy link
Copy Markdown
Contributor

Demon's Souls (PPSA01341 v1.07) on Linux, RTX 5070 Ti, NVIDIA 595.91 (no VK_EXT_shader_stencil_export), tested at c7595e9. The setup and the per-build table are on #4276: #4276 . The title stops on this PR's refusal stencil reference export emulation requires a replay-safe pixel shader with late tests. The pixel shader is 788 words. It is refused at four addresses: 0x24abb6d00 and 0x24ab57200 are byte-identical, and 0x24ab5a100 and 0x24ab6dc00 stop the same way, so they are most likely the same code, and the draw that matters writes the reference through write mask 0x80. Tests are late: the driver clears early Z when stencil export is on.

With your three #758 adaptations applied (the first removes a separate blocker, #758's EXEC operand on ImageSampleRaw), StencilReplaySafe still rejects the shader for two reasons. Line numbers are at 63368e1. agc_shader_replay on the captured request reproduces both offline, and the in-game logs report the same reasons.

  1. The cross-lane rule (StencilReplay.cpp:702, DppMoveU32 / DppUpdateU32). The shader computes coarse derivatives by hand with DPP quad_perm: v_mov_b32 with quad_perm [0,0,0,0] at 0x234, 0x23c, 0x40c and 0x414, and v_sub_f32 with quad_perm [1,1,1,1] / [2,2,2,2] at 0x260-0x278 and 0x438-0x450. All use row_mask 0xf, bank_mask 0xf and bound_ctrl 1, so these are quad-local reads.
  2. control() (called at StencilReplay.cpp:110). It rejects six conditional branches, all kill early-outs: s_andn2_b64 s[20:21], s[20:21], vcc then s_cbranch_scc0. The IR condition is any() of the ballot mask, which guaranteed() can't prove. The kill exit is exec 0, exp null, s_endpgm. The main exit exports MRTZ with stencil 0 or 255.

With both rules bypassed locally, the shader recompiles (66435 SPIR-V words). The title then stops at t+513, still in the level load, on another limit: stencil replay requires an unused push constant dword (BindingAllocator.cpp:120), shader 0x24ac2cb00, whose push data already fills the push block. The bypass is a local experiment only.

The captured request holds the game's shader binary and captured guest memory, so I can't attach it. I can run a build or log specific values on request.

AI-assisted: yes

fdfawef324 and others added 15 commits October 14, 2026 22:08
Preserve instance and triangle order with one dynamic-reference shader pipeline. Require bounded references, complete export coverage, replay-safe mask control and resources; refuse unsupported side effects and feedback.

Co-Authored-By: Codex <noreply@openai.com>
Update only dynamic reference state between replay classes so asynchronous pipeline optimization cannot switch the shader prefix within an original draw.

Co-Authored-By: Codex <noreply@openai.com>
Main now uses disk cache format30 for persisted resource plans. Stencil replay
adds artifact and binding fields, so reject that format instead of sharing its
version. Keep format31 for the combined codec and cover rejection of a format30
artifact header.

Co-Authored-By: Codex <noreply@openai.com>
Preserve replay refusal for observable lane-dependent values, non-vertex stages, unknown subgroup widths and varying-size modules. Validate the actual native vertex subgroup contract and retain compiled single-lane targets.

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
Advance the stencil artifact schema past current main format 31 and retain explicit rejection of that format. Update Linux artifact size guards for main runtime image resource metadata.

Co-Authored-By: Codex <noreply@openai.com>
Advance stencil artifacts to format 33 after main's format 32 change. Keep explicit rejection of upstream format 32 while preserving the existing stencil fields and runtime image metadata.

Co-Authored-By: Codex <noreply@openai.com>
Keep format 33 and its previous-format 32 refusal; also cover the current main format 31 explicitly.

Co-Authored-By: Codex <noreply@openai.com>
Move bounded vertex folding and empty-image feedback into separate topics. Keep the replay coverage proof, stage contracts, finite-reference tests and mapped cache regressions; version the stencil layout separately as format 34.

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
Check sampled image-table entries with the existing stencil replay depth-feedback refusal. Keep the cache regression tied to current upstream format 33 while stencil artifacts use format 34.

Co-Authored-By: Codex <noreply@openai.com>
Main's flatVolumeLineCompatible change also took format 34 with another layout, so entries of either would load as the other.

Co-Authored-By: Claude <noreply@anthropic.com>
@adriadam10
adriadam10 force-pushed the codex/stencil-export-emulation branch from 436fc35 to d8e97a7 Compare October 14, 2026 20:17

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-checked at 436fc35: the build error, the title/"Unblocks" claim and the topic split are fixed, thanks.

Since your base, dd8f2eb also moved the shader disk cache to format 34 (with a different layout), so both would have loaded each other's entries. I rebased onto current main, resolved the docs/dev/ARCHITECTURE.md conflict, and moved the stencil artifacts to format 35 (ShaderDiskCache.hpp, ARCHITECTURE.md now says entries from formats 31 to 34 are rejected; the existing previous-version test covers 34).

Checked on the rebased tree: build, agc_driver_stencil_replay, agc_driver_stencil_replay_no_gpl, agc_shader_disk_cache, agc_masked_select, agc_driver_graphics pass; the PR's tests don't build without the code change. The only failing test in the area, agc_driver_tessellation, segfaults inside RADV on plain main too. Merging once the full Build is green.

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

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

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

Pull request Conflicting files (lines on main) Same exports Same new files
#5304 docs/dev/debt/libSceAgcDriver.md L81
#5734 core/shader/recompiler/ShaderDiskCache.cpp L93-94
#6032 core/shader/recompiler/ShaderDiskCache.hpp L16

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants