Skip to content

fix(agc): treat type-0 texture descriptors as null - #4779

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
MarcZX10:codex/null-tsharp-type-4139
Oct 14, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
MarcZX10:codex/null-tsharp-type-4139

Conversation

@MarcZX10

Copy link
Copy Markdown
Contributor

What

Treat an AMD texture descriptor with TYPE=0 as a null image, even when its base address is nonzero. This lets guest shaders bind stale S#+V# words in image slots without trying to decode them as a real texture. The scope is the observed TYPE=0 case from issue #4139; this PR does not implement cube T# reads through 2D accesses.

The null predicate is shared across image precollection, binding resolution, refresh, revalidation and surface presync so each path classifies the same descriptor consistently. Regression coverage includes zero-base descriptors, TYPE=0 with a nonzero base, and a valid nonzero-base descriptor.

Evidence and limits

The issue reports S#+V# words in image slots in High on Life, including repeated TYPE=0 substitutions. An issue contributor measured TYPE=0 behavior on gfx1036 RDNA2: image sample/load/resinfo returned zero, including the reported nonzero unmapped bases, without a GPU fault. This is gfx1036 evidence; PS5 gfx1013 behavior was not measured.

Tested

  • Linux Release: agc_driver_graphics passed (1/1) on current main base 584cc4c5716b02210ca031593d1a6b0b4ce049cb.
  • python3 tools/check_conventions.py --base upstream/main passed.
  • git diff --check upstream/main...HEAD passed.
  • The reported console behavior and gfx1036 experiment were not rerun by this PR; no console/GPU hardware validation was performed here.

Checklist

  • Based on current main; no open PR implements TYPE=0 null descriptor handling
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw or use NotImplemented_nid_no_patch
  • No investigation files added to the repository
  • No new third-party code
  • Generic behavior
  • Depends on: none
  • AI-assisted: yes

@xXPBSXx

xXPBSXx commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Windows test (MinGW GCC 15.2, Release, Windows 10, RTX 4080 SUPER). Built in a batch with five other open GPU PRs cherry-picked onto main 44ab0c39e (not current main, which needs a submodule that isn't checked out here), so only the tests that belong to this PR say anything about it:

  • tests/GuestTextureResource.cpp, which is part of agc_driver_graphics_tests: see below.

agc_driver_graphics over the batch: 9 of 10 runs passed. The one failure is the known address-layout flake from #4660 as far as I can tell: I kept only the first lines of that run's log (the host import ... vkAllocateMemory (-2) lines, which appear in passing runs as well), not its final error message, so I can't confirm the cause for that one run. Plain main failed 2 of 10 on the same machine earlier.

Not tested: no game run; the batch was not rebuilt per PR, so a failure would have needed a bisect (there was none besides the flake).

AI-assisted (Claude Code).

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Two things before merging:

@github-actions github-actions Bot added the agc libSceAgc* label Oct 13, 2026
@MarcZX10

Copy link
Copy Markdown
Contributor Author

Thanks. The title is High on Life (PPSA15388), documented in #4139; its current-main failure is the rejected descriptor/shader-draw path. The gameplay result in that issue used a local experiment that null-bound both the TYPE=0 slot and the separate cube-through-2D case. This PR changes only the TYPE=0 handling, and I do not have an isolated run of this exact PR head that gets the title past the failure. The gfx1036 measurement is not a console measurement, so I will keep that limitation explicit and will not claim this PR alone gets High on Life to gameplay.

@Sam-mon7

Copy link
Copy Markdown
Contributor

A second title with TYPE=0 image descriptors: Demon's Souls (PPSA01341 v1.07), Windows 11, RTX 4070 (driver 596.21), MinGW GCC 15.2 Release.

  • Stop: during the PS Studios intro, compute shader 0x248a05b00 (shader_248a05b00_failed.req): runtime image descriptor is invalid, then SIGABRT. In the captured request, image slots 3-6 have TYPE=0 (dword3[31:28]) with a nonzero base and nonzero remaining words. Slots 0-2 and 7-9 are valid descriptors.
  • This PR covers the driver binding paths. The recompiler's static image check (ResourceMaterializer.cpp) still treats only a zero base as null, so a TYPE=0 descriptor with a nonzero base is rejected there first. A CPU regression with such a descriptor fails with this PR applied. I have not replayed the captured request against this head alone.
  • Locally I added the same TYPE=0 predicate in ResourceMaterializer.cpp (words cleared before metadata and swizzle selection), and TYPE=0 image-table entries resolve to null. With this PR plus that change, the captured request gets past image validation, and later runs pass the intro and reach character creation. That tree carries other local changes, so it is not an isolated run of this head either.
  • On the RTX 4070 (not gfx1013): TYPE=0 descriptors with nonzero or unmapped bases read four zero components through a direct sample, a buffer-table sample and load, and a raw-pointer table sample. A reserved TYPE=1 still faults.

If it helps, I can open the recompiler half as a follow-up that depends on this PR.

AI-assisted: yes

@MarcZX10

MarcZX10 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks, this separates the two layers clearly: this PR handles runtime binding, while ResourceMaterializer rejects the TYPE=0 descriptor earlier. The separate CPU regression and title trace are useful evidence. A focused follow-up for the recompiler path, depending on this PR, seems like the right way to carry that fix; the remaining gfx1013 behavior should stay explicit as unverified.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

I opened the recompiler-side follow-up as PR #5473, depending on this PR. It adds a regression for an image descriptor with TYPE=0 and a nonzero base. The focused Linux test passes with the change and fails on the previous predicate with runtime image descriptor is invalid. I recorded that this does not include the runtime binding change from this PR.

RINNECODER added a commit to RINNECODER/AnyPS5 that referenced this pull request Oct 13, 2026
- skip pure PM4 NOP packets in the Metal packet loop (upstream PR boykopovar#5481)
- note the dispatch registers after direct and indirect Metal dispatch so
  COPY_DATA from a shader register works there (upstream PR boykopovar#5477)
- NullImageDescriptor delegates to IsNullTextureResource (upstream PR boykopovar#4779)
- tests: pm4 compute replay reads the dispatch initiator and group counts
  back through COPY_DATA; metal utility tests cover a type-0 image descriptor

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj
RINNECODER added a commit to RINNECODER/AnyPS5 that referenced this pull request Oct 13, 2026
* perf(agc): fast-skip pure PM4 NOP packets during queue execution

(cherry picked from commit 139bf04)

Ported from upstream PR boykopovar#5481

* fix(agc): copy a shader, context or user config register to memory with COPY_DATA

A dispatch now leaves its initiator and, for DISPATCH_DIRECT, its group
counts in the shader registers, where the CP puts them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 5e36c08)

Ported from upstream PR boykopovar#5477

* fix(agc): accept reported vertex stage state

(cherry picked from commit 632331d)

Ported from upstream PR boykopovar#4341

* fix(agc): initialize stencil control and reference masks

(cherry picked from commit 85e0d98bba896002539365bb29a7a39a8e43f501)
(cherry picked from commit 13dca48)

Ported from upstream PR boykopovar#5347

* fix(agc): accept inactive vertex point size on non-point draws

(cherry picked from commit d4b59ce)

Ported from upstream PR boykopovar#4715

* fix(agc): treat type-0 texture descriptors as null

(cherry picked from commit 7e1e1ce)

Ported from upstream PR boykopovar#4779

* fix(agc): fall back out-of-range sceAgcInit versions to table 13

Pointer-shaped NID kW3GLb7QfPg calls from public homebrew succeed on console; returning an error left those titles failing init after boykopovar#4835.

(cherry picked from commit 939f784)

Ported from upstream PR boykopovar#5163 (debt-doc hunk dropped: file absent on main)

* fix(agc): clamp sceAgcInit versions above 13 inline

(cherry picked from commit 0cc5102)

Ported from upstream PR boykopovar#5163 (second commit)

* metal: adapt the shared AGC driver slice to the Metal execution loop

- skip pure PM4 NOP packets in the Metal packet loop (upstream PR boykopovar#5481)
- note the dispatch registers after direct and indirect Metal dispatch so
  COPY_DATA from a shader register works there (upstream PR boykopovar#5477)
- NullImageDescriptor delegates to IsNullTextureResource (upstream PR boykopovar#4779)
- tests: pm4 compute replay reads the dispatch initiator and group counts
  back through COPY_DATA; metal utility tests cover a type-0 image descriptor

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj

---------

Co-authored-by: Kikoarl <7354010+Kikoarl@users.noreply.github.com>
Co-authored-by: LeandroLP23 <leandroplacidi@gmail.com>
Co-authored-by: MarcZX100 <marczxrr@gmail.com>
Co-authored-by: MathiasDevelopes <25400788+MathiasDevelopes@users.noreply.github.com>
Co-authored-by: lorkydey <57268822+Lorkydey@users.noreply.github.com>
Co-authored-by: mazen <mazenshaar@hotmail.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
@adriadam10 adriadam10 self-assigned this Oct 14, 2026
@adriadam10
adriadam10 force-pushed the codex/null-tsharp-type-4139 branch from 7e1e1ce to 58b2245 Compare October 14, 2026 17:20
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the shared IsNullTextureResource predicate against every site that used the old zero-base test (precollect, resolve, refresh, revalidate, presync): all consistent. agc_driver_graphics passes, and the new type-0 case fails if the type == 0 check is removed.

Added on top, per @oneandonlydean's request: a docs/dev/debt/libSceAgcDriver.md entry saying a TYPE=0 descriptor with a nonzero base is bound as a null image, from the gfx1036 measurement in #4139 and not measured on the console. Rebased onto current main; merging once CI is green.

@adriadam10
adriadam10 merged commit 26ce6e9 into boykopovar:main Oct 14, 2026
8 checks passed
billythemenace2 pushed a commit to billythemenace2/AnyPS5 that referenced this pull request Oct 15, 2026
A static, read-only image slot whose T# has TYPE 1 is now bound as a null
image, like TYPE 0 since boykopovar#5473 and boykopovar#4779. On gfx1010, image_sample_lz,
image_sample_b, image_load and image_get_resinfo through a format-22
TYPE 1 T# return zeros without a fault, and gfx1035 reads it as zeros
too. Written, atomic and table slots still throw, and the reserved
types 2-7 stay refused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants