Skip to content

feat(tools): add an offline shader archive tool that publishes prebuilt packs - #5793

Closed
SaloQT wants to merge 4 commits into
boykopovar:mainfrom
SaloQT:feat/shader-archive-tool
Closed

SaloQT wants to merge 4 commits into
boykopovar:mainfrom
SaloQT:feat/shader-archive-tool

Conversation

@SaloQT

@SaloQT SaloQT commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What

An offline tool that extracts shader programs from a game's archives, recompiles them ahead of time, and publishes the results as a prebuilt shader pack for the loader in #5792 (merged).

  • tools/shader-archive (new): reads Unreal IoStore v8 .utoc/.ucas pairs, decodes the Oodle Mermaid quanta those archives use with its own clean-room decoder (no vendored Oodle), scans shader libraries, and builds shader variants fully offline through the existing recompiler. Output is published atomically as a *.pack file (the format feat(recompiler): load prebuilt shader packs before the writable cache #5792 loads) plus a manifest.
  • Two small recompiler commits first: an uncached compile entry point so tools do not write through the disk cache, and encoded entry-key helpers so the tool builds entries in the cache's exact on-disk format.
  • Remaining decoder limits (other Oodle codecs, other entropy modes, checksums) throw typed errors and are listed in docs/dev/TechnicalDebt.md; the tool fails on archives it cannot decode instead of guessing.

Scope, honestly: extraction covers Unreal IoStore v8 only today; other engines' archives (Insomniac, RAGE) need their own readers. Keys are exact, so statically built variants only hit when the runtime request matches exactly — the verified end-to-end numbers are for replayed captured requests, and a real-game hit-rate measurement with a statically built pack is still open (also in TechnicalDebt). The tool also writes pipeline-cache.bin, but nothing loads it at runtime yet; whether offline pipeline compiles remove driver compile cost is unmeasured, so this PR claims no pipeline-compile saving.

Tested

Windows 11: rebuilt on current main; shader_archive, agc_shader_disk_cache and shader_cache_file_read pass. Full real-archive run: 4,803/4,803 IoStore groups decoded byte-identical to the licensed-SDK reference, 80,794 shader hashes matching. Offline build + publish + probe against captured requests: 10/10 exact-key hits. Not tested on Linux locally (no Linux box here); CI covers it.

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 (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: feat(recompiler): load prebuilt shader packs before the writable cache #5792 (merged)
  • Unblocks: none
  • GPUs tested: offline CPU recompile only; n/a
  • AI-assisted: yes

CompileShaderUncached compiles one request without the process-lifetime
source cache or a resource snapshot, so batch tools can compile shader
archives with bounded worker lifetimes. Optional frontend and backend
timings report where each compilation spent its time.
Read-only packs of encoded cache entries are mapped once at startup from
the shader cache prebuilt directory (plus ANYPS5_PREBUILT_SHADER_CACHE,
opt out with ANYPS5_NO_PREBUILT_SHADERS). Disk loads try packs and loose
prebuilt folders first and fall through to the writable cache and the
compiler on a miss. Keys, source version, format and payload checksums
are validated exactly as for writable entries, and interval logs report
prebuilt hits, misses, rejections and load timings.

Depends on the uncached compile entry point only through the offline
tool that produces these packs; the loader itself is independent.
…lt packs

agc_shader_archive extracts native shader programs from IoStore
containers, builds static AGC requests, compiles them through the
production recompiler with bounded workers, validates the SPIR-V, can
compile pipelines on a Vulkan device, and publishes the results as
prebuilt packs for the runtime loader. Captured requests can be
replayed offline with their actual targets, and probe reports exact
pack hit coverage and load timings.

Oodle Mermaid streams are decoded by a new decoder in Oodle.cpp whose
bitstream layout follows the MIT-licensed oozextract 0.5.5 decoder;
unsupported codecs and entropy forms throw and are recorded in
technical debt. The target is excluded from the default build.

Extraction of one measured title reproduces all 4,803 shader groups
byte-for-byte. Replaying eleven captured requests publishes an
eleven-entry pack, and probe then loads eleven of eleven from the pack
with an empty writable cache.

Depends on the uncached compile entry point and the prebuilt pack
loader commits.
New Markdown outside docs/ is rejected by the conventions check, so the
tool guide lives with the other developer documents.
@github-actions github-actions Bot added the open PR limit Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20 label Oct 14, 2026
@github-actions

Copy link
Copy Markdown

Thank you for your contribution! Authors with no pull requests merged into main can have 1 open pull request at a time, authors with at least 1 merged can have 20, and from 20 merged there is no limit. This PR has been automatically closed and labeled "open PR limit" because that limit was reached. This is not a judgment of the quality of your changes: reopen it once one of your open pull requests is merged or closed.

@github-actions github-actions Bot closed this Oct 14, 2026
JJenkx added a commit to JJenkx/AnyPS5 that referenced this pull request Oct 14, 2026
…cache

Integrate SaloQT's upstream PRs boykopovar#5792 and boykopovar#5793 against main 3242151.
Preserve mapped writable entries and resource-plan caching, fix Linux tool
linking and SPIR-V span access, and accept padded cache payload envelopes.
Add pack corruption, lifetime, cross-process and alignment regressions.

Co-authored-by: SaloQT <123214229+SaloQT@users.noreply.github.com>
JJenkx added a commit to JJenkx/AnyPS5 that referenced this pull request Oct 14, 2026
…cache

Integrate SaloQT's upstream PRs boykopovar#5792 and boykopovar#5793 against main 3242151.
Preserve mapped writable entries and resource-plan caching, fix Linux tool
linking and SPIR-V span access, and accept padded cache payload envelopes.
Add pack corruption, lifetime, cross-process and alignment regressions.

Co-authored-by: SaloQT <123214229+SaloQT@users.noreply.github.com>
@SaloQT

SaloQT commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

Reopened as #6032: this PR could not be reopened after the branch was force-pushed, so the same rebased branch (onto merged #5792) is now #6032 with an updated description.

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

Labels

open PR limit Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant