Skip to content

fix(agc): apply RADV's HTILE depth fast clears to the host depth surface - #2229

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
TheAggie:fix/agc-radv-htile-depth-clear
Oct 10, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
TheAggie:fix/agc-radv-htile-depth-clear

Conversation

@TheAggie

@TheAggie TheAggie commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

What

A depth surface is a host image that AnyPS5 clears once, when it creates the image, to the DB_DEPTH_CLEAR value it sees then. RADV (and real hardware) clears depth differently: it doesn't touch the depth memory, it rewrites the HTILE metadata so every tile reads as "cleared" (ZMASK = 0), and the DB returns DB_DEPTH_CLEAR for those tiles. AnyPS5 doesn't model HTILE, so after the first frame the host depth image is never cleared again.

vkQuake (PPSA99010, the homebrew Vulkan port, through RADV) shows this as a black 3D view. It uses reverse Z (GREATER_OR_EQUAL, clear to 0.0), so the depth buffer keeps the largest depth of every earlier frame, and once the camera moves nearly every world draw fails the depth test. The HUD, the 2D draws and the post-process pass are unaffected.

  • DepthTarget carries the surface's HTILE address (DB_HTILE_DATA_BASE / _HI) when DB_Z_INFO.TILE_SURFACE_ENABLE is set and the base register has been written. 0x005 and 0x01e are added to DrawKeyRegisters.
  • RADV writes HTILE with its clear_htile_mask compute kernel (17 GFX10 words: htile = (htile & user[5]) | user[4] over the buffer at user[2..3]). HtileDepthClearAddress recognizes it by its code and 64x1x1 groups, and returns the HTILE address when the update leaves ZMASK at 0. The dispatch still runs, so guest memory is unchanged.
  • DepthSurfaceView clears the depth aspect of that surface to the draw's DB_DEPTH_CLEAR the next time the surface is bound, through Recorder::Commands() (which ends any open render pass) with barriers around the clear.

HTILE initialization (ZMASK 0xf, "expanded") and the stencil-only update RADV issues alongside it are left alone.

Limits: this matches one RADV kernel. Fast clears done some other way (the SDK's own paths, CP DMA fills, stencil HTILE clears) aren't covered.

Tests:

  • DepthStencilTests: the HTILE address decodes from DB_HTILE_DATA_BASE and its high byte, is 0 without the base register or without TILE_SURFACE_ENABLE, and every register the decoder reads is in DrawKeyRegisters.
  • htileDepthClearTests: the fast clear is recognized; HTILE initialization, the ZMASK-preserving stencil update, another group size, a changed kernel and a truncated kernel are not.

Other open PRs touch the same files (#1684, #2076, #2169 in DepthSurface/State, #2095 in the Graphics tests); I'll rebase onto whichever lands first.

Tested

Windows 11 Pro (26200), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, NVIDIA GeForce RTX 5070 Ti (driver 610.88).

  • Full local suite: 507 tests, 505 passed, 1 skipped; guest_sce_net timed out (also when run alone; it doesn't touch the AGC driver, likely my local network filtering). It was run from the generated CTestTestfile.cmake commands because antivirus blocks ctest.exe on this machine.
  • tools/check_conventions.py --base origin/main passes.
  • vkQuake (PPSA99010): the 3D view went from black to a correctly depth-tested, textured and lit world (E1M1 demo). That run was on my local test branch (current main plus my open RADV PRs and some local stubs), so it isn't reproducible on main alone.

Not tested on Linux or macOS.

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 in TechnicalDebt
  • 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: none
  • AI-assisted: yes

🤖 Generated with Claude Code

@github-actions github-actions Bot added the agc libSceAgc* label Oct 9, 2026
@TheAggie
TheAggie force-pushed the fix/agc-radv-htile-depth-clear branch from 6eeba14 to dd5a511 Compare October 9, 2026 14:21
@TheAggie TheAggie changed the title AGC: apply RADV's HTILE depth fast clears to the host depth surface fix(agc): apply RADV's HTILE depth fast clears to the host depth surface Oct 9, 2026
@popcoder565

Copy link
Copy Markdown
Contributor

Native Windows run, since no Windows results were posted. Setup: Windows 10 (19045), RTX 3060 Laptop (NVIDIA 616.92), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. Head dd5a5117, merged onto main d70b899 in one build with 33 other AGC/shader PRs that had no Windows run.

No title was run.

🤖 Addressed by Claude Code

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Please rebase; it conflicts with main in tests/Graphics.cpp.

@TheAggie
TheAggie force-pushed the fix/agc-radv-htile-depth-clear branch from dd5a511 to d44542a Compare October 10, 2026 06:20
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 10, 2026
@github-actions

github-actions Bot commented Oct 10, 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
#1430 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp L17
#1864 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/Dispatch.cpp L7-8, L53-60

TheAggie and others added 2 commits October 10, 2026 08:36
RADV clears depth by rewriting HTILE with its clear_htile_mask kernel
(ZMASK to 0) instead of writing depth memory. Recognize that kernel and
clear the matching host depth surface to DB_DEPTH_CLEAR when it is next
bound; the depth target now records its HTILE address.

AI-assisted (Claude Code).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@adriadam10
adriadam10 force-pushed the fix/agc-radv-htile-depth-clear branch from d44542a to 1de9bbe Compare October 10, 2026 06:48
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked on Linux (RADV host) on the rebased head: scoped build + ctest of libSceAgcDriver green, agc_driver_graphics and agc_driver_prepared_graphics pass, and agc_driver_graphics fails if the ZMASK check on user[4] is removed. I disassembled the 17-word kernel for gfx1030 and it is htile = (htile & user[5]) | user[4] as described. Windows run by @popcoder565 also passes.

Added by us on top of your rebase:

  • docs/dev/TechnicalDebt.md, "Functional": a line for the HTILE depth fast clear limits (only RADV's kernel, exact HTILE address match, no HTILE init / stencil / other fast-clear paths).

Merging once CI is green.

@github-actions github-actions Bot added the docs label Oct 10, 2026
@adriadam10
adriadam10 merged commit 40a7711 into boykopovar:main Oct 10, 2026
14 checks passed
MichonGoddijn231849 added a commit to MichonGoddijn231849/AnyPS5-fork that referenced this pull request Oct 10, 2026
Rebased onto main as one commit (the six commits of boykopovar#374). A uniform fill over a depth surface's whole
HTILE (DMA_DATA, the fill kernels or a CPU store) clears the depth and stencil aspects its ZMask and
SMem fields say, to DB_DEPTH_CLEAR / DB_STENCIL_CLEAR, when the surface is next bound or sampled.

Main's RADV clear_htile_mask recognition (boykopovar#2229) now goes through the same pending clear: an HTILE clear
marks the matching surfaces' depth aspect, and one for a surface not created yet is applied when it is
first bound. Main's HTILE address decode and this one are merged into one (TILE_SURFACE_ENABLE, a
nonzero DB_HTILE_DATA_BASE and a depth format).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
SleglJan pushed a commit to SleglJan/AnyPS5 that referenced this pull request Oct 10, 2026
…epth-clear

fix(agc): apply RADV's HTILE depth fast clears to the host depth surface
MichonGoddijn231849 added a commit to MichonGoddijn231849/AnyPS5-fork that referenced this pull request Oct 10, 2026
Rebased onto main as one commit (the six commits of boykopovar#374). A uniform fill over a depth surface's whole
HTILE (DMA_DATA, the fill kernels or a CPU store) clears the depth and stencil aspects its ZMask and
SMem fields say, to DB_DEPTH_CLEAR / DB_STENCIL_CLEAR, when the surface is next bound or sampled.

Main's RADV clear_htile_mask recognition (boykopovar#2229) now goes through the same pending clear: an HTILE clear
marks the matching surfaces' depth aspect, and one for a surface not created yet is applied when it is
first bound. Main's HTILE address decode and this one are merged into one (TILE_SURFACE_ENABLE, a
nonzero DB_HTILE_DATA_BASE and a depth format).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
adriadam10 pushed a commit to MichonGoddijn231849/AnyPS5-fork that referenced this pull request Oct 11, 2026
Rebased onto main as one commit (the six commits of boykopovar#374). A uniform fill over a depth surface's whole
HTILE (DMA_DATA, the fill kernels or a CPU store) clears the depth and stencil aspects its ZMask and
SMem fields say, to DB_DEPTH_CLEAR / DB_STENCIL_CLEAR, when the surface is next bound or sampled.

Main's RADV clear_htile_mask recognition (boykopovar#2229) now goes through the same pending clear: an HTILE clear
marks the matching surfaces' depth aspect, and one for a surface not created yet is applied when it is
first bound. Main's HTILE address decode and this one are merged into one (TILE_SURFACE_ENABLE, a
nonzero DB_HTILE_DATA_BASE and a depth format).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
SP4C3B4R-8 pushed a commit to SP4C3B4R-8/AnyPS5 that referenced this pull request Oct 11, 2026
Rebased onto main as one commit (the six commits of boykopovar#374). A uniform fill over a depth surface's whole
HTILE (DMA_DATA, the fill kernels or a CPU store) clears the depth and stencil aspects its ZMask and
SMem fields say, to DB_DEPTH_CLEAR / DB_STENCIL_CLEAR, when the surface is next bound or sampled.

Main's RADV clear_htile_mask recognition (boykopovar#2229) now goes through the same pending clear: an HTILE clear
marks the matching surfaces' depth aspect, and one for a surface not created yet is applied when it is
first bound. Main's HTILE address decode and this one are merged into one (TILE_SURFACE_ENABLE, a
nonzero DB_HTILE_DATA_BASE and a depth format).

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* docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants