Repository navigation
fix(agc): import native multisample D32S8 targets with a separate stencil plane and a depth-only HTILE - #9533
EagleBearerYS wants to merge 26 commits into
Conversation
…HTILE fills A 2, 4 or 8 sample D32_SFLOAT_S8_UINT target with its stencil in HTILE is imported natively when every HTILE word proves both planes cleared: the depth range as before, and SMem 0 for the stencil. The stencil plane joins the watched, guarded and generation-checked ranges. A depth-only HTILE, an unaligned stencil plane, or a word failing either proof is refused with its own reason. A fill covering the whole HTILE of a sampled native target is a clear transition, proven at the next sample like the HTILE mask clear: complete tracked stores since the fill, no CPU or queued writes, and every word proving the depth and, with a stencil plane, the stencil clear value. A partial fill and an HTILE mask clear of a stencil target stay refused.
…attern A whole HTILE fill recorded on the GPU is still pending when the title binds or samples the depth in the same frame, so the HTILE words in guest memory are not the fill's yet and the queued write was refused as an external GPU write. The fill's write note is kept with its pattern: while it is still the newest queued write over the HTILE, the clear is proven from the pattern, and the completed tracked store check is not needed for a GPU fill. A later queued write, a CPU write or a pattern that does not prove the clear is refused as before. AI-assisted: yes
Brings upstream main a6dcea9 under boykopovar#6300's two commits. Conflicts: - DepthSurface.cpp prepareDepthSampling: boykopovar#6300's stencil checks are kept and main's 752cca1 drops the ITERATE_256 requirement, so the HTILE check is main's line ("requires pipe-aligned HTILE without VRS"). - DepthSurface.cpp NoteHtileDepthClear and NoteDepthMetadataFill: boykopovar#6300's clear and fill proofs are kept, written with main's first-refusal-wins DepthSamplingState::Refuse. After the proven whole-fill branch, the remaining fills take main's ForgetClear/NoteHtileClear and single-sample plane-fill paths. - NativeMultisampleDepth.cpp CheckDepthTarget takes both boykopovar#6300's ClearSource and main's iterate256, in that order; main's ITERATE_256 call passes ClearSource::HtileDispatch. - docs/dev/debt/libSceAgcDriver.md: one entry with boykopovar#6300's stencil and fill text and main's ITERATE_256 text. Adapted to main: main samples a native multisampled depth target through a shadow copy that is refreshed when the sampled view is looked up (1912045, 5a0a00f). CheckStencilTarget recorded its raster and the fetch in one batch, so the fetch read the shadow from before the raster ("native depth-stencil sampled fetch lost a depth sample or a stencil test outcome"). It now submits the raster, looks the view up again and syncs before the fetch, as main's CheckDepthTarget does.
…ared stencil plane
The Grinch: Christmas Adventures (PPSA07656) binds a two-sample
D32_SFLOAT_S8_UINT target whose stencil is a plane of its own and whose
HTILE is depth-only (DB_STENCIL_INFO.TILE_STENCIL_DISABLE), so HTILE
holds no stencil state. Every byte of that plane is the clear stencil
when the target is first bound. The import refused it ("native
multisample stencil import requires HTILE stencil metadata") and the
title stopped before its first present.
With a depth-only HTILE the stencil is uncompressed in its plane, so the
plane is its own proof: the import scans it once and accepts the target
when every byte equals DB_STENCIL_CLEAR. The depth keeps its HTILE clear
proof. The plane is already one of the import's ranges, accessible,
watched, generation-checked, guarded from guest publication and kept
apart from the depth and HTILE ranges, so a later CPU or GPU write to it
refuses sampling like a write to the depth. The host image is created
cleared to the clear stencil. The plane's base keeps the 64 KiB
alignment of the depth plane: both use SW_64KB_Z_X, the decode takes
the pipe/bank XOR from the depth base's low 16 bits and masks both bases.
A whole HTILE fill of such a target is proven for the depth only and
clears only the host depth: the stencil plane is untouched by the fill
and still proven unchanged since the import.
A stencil plane that is not all clear, a stencil in neither HTILE nor
its own plane, D16S8 and HTILE words that do not prove a clear keep
their refusals.
Tested: agc_driver_native_depth_separate_stencil imports a four-sample
target (two and eight where the device has them), samples the clear
depth, stencil-tests the clear stencil, and refills a depth-only HTILE
keeping a replaced stencil; one stencil byte not clear, a later stencil
write and an unwatched plane are refused. Without the import change the
target refuses "native multisample stencil import requires HTILE
stencil metadata"; without the fill change the refilled target loses
its stencil.
…or without HTILE Once its D32S8 target imports, The Grinch: Christmas Adventures (PPSA07656) samples the depth plane through a T# with no metadata (META_DATA_ADDRESS 0, not pipe-aligned) while the target has its HTILE. The pipe/bank XOR and ITERATE_256 match. CheckResource required the descriptor's metadata to be the target's HTILE and stopped the title with "native multisample depth sampled metadata or XOR mismatch". The host image keeps the depth decompressed, so a descriptor that reads the plane without metadata reads the values a metadata-aware one does. CheckResource now accepts a descriptor with no metadata at all beside one naming the target's HTILE, when its address, format, XOR and ITERATE_256 match. A descriptor with any other metadata keeps refusing. Assumption: on hardware such a read returns the decompressed depth only once the guest has expanded the plane (an in-place expand with compression disabled). Main draws an in-place expand as an ordinary draw that writes the depth attachment (DB_RENDER_CONTROL compress-disable bits are not refused), over a host image that already holds the decompressed depth, and has no out-of-place expand for multisampled planes. Nothing here observes whether the guest expanded first; a title that samples the plane unexpanded gets the decompressed values instead of the raw plane. Tested: agc_driver_native_depth_separate_stencil samples the separate stencil target through a descriptor without metadata, before and after raster writes and after a depth-only HTILE fill, and gets the depth. The same descriptor with another XOR and one naming other metadata are refused. Without the change the first sample refuses "native multisample depth sampled metadata or XOR mismatch".
…th-only HTILE when every word proves the same clear
Ghost of Tsushima (PPSA02225) samples a two-sample D32S8 1920x2160
target with a separate stencil plane and a depth-only HTILE that is
neither pipe-aligned nor ITERATE_256. The import required a pipe-aligned
HTILE.
Pipe alignment only decides where each tile's word sits in the HTILE.
When every word is the same and proves the clear, their order cannot
change what they prove, so a depth-only HTILE that is not pipe-aligned
is imported when all its words are one word proving the clear value.
A non-pipe-aligned HTILE whose words differ is refused ("native
multisample depth HTILE that is not pipe-aligned holds more than one
word"), and one that holds stencil state keeps the alignment refusal.
The range stays HtileMetadataBytes(extent): Ghost's whole-HTILE fill
covers exactly that, 0x50000 bytes for 1920x2160. ITERATE_256 is
already independent of the import (752cca1).
Tested: agc_driver_native_depth_separate_stencil runs every separate
stencil case on a depth-only HTILE that is not pipe-aligned or
ITERATE_256 too, sampled through a descriptor naming that HTILE and one
without metadata; one differing word is refused. Without the change the
target refuses "native multisample depth initial import requires
pipe-aligned HTILE without VRS".
…encil clear
Ghost of Tsushima (PPSA02225) fills the separate stencil plane of its
two-sample D32S8 target with pattern 0 (0x870000) before it samples the
target. Any write over the plane was refused ("guest writes over native
multisample depth are not implemented").
A DMA or compute fill that covers the whole plane of a target whose
depth-only HTILE leaves the stencil in the plane is now recorded like a
whole-HTILE fill. At the next sample it is proven the way a whole-HTILE
fill is: no CPU write since the fill, complete tracked stores since the
fill unless the fill is the plane's newest queued GPU write, and every
plane byte equal to the fill byte once it has landed. The host image's
stencil aspect is then cleared to that byte. A fill that covers part of
the plane is refused ("native multisample stencil plane partial fill
transition is not implemented"), and so is a pattern that is not one
byte, a fill over unwatched memory and a second fill before the plane
was proven.
Tested: agc_driver_native_depth_separate_stencil fills the HTILE, the
stencil plane, or both, after a draw replaced the stencil, on pipe-aligned
and non-pipe-aligned depth-only HTILE, and checks the sampled depth and
which stencil reference the next draw passes. Partial, two-byte-pattern,
unstored and CPU-raced plane fills are refused. Without the change the
first plane fill refuses "guest writes over native multisample depth are
not implemented", and the partial fill refuses with that text instead of
the partial fill one.
…te is recorded after the fill is noted Ghost of Tsushima (PPSA02225) fills the HTILE (0x50000 bytes) and the separate stencil plane (0x870000 bytes) of its two-sample D32S8 target with pattern 0 before it samples the target. Both are DMA_DATA fills larger than 64 KiB. PacketMemory notes a DMA_DATA fill before storeBufferFill records it, so when the range has a host import the fill's GPU write is recorded after NoteDepthMetadataFill took LastWriteNote. The note was then 0, the fill did not count as the queued fill, and the sample that followed in the same batch refused "external GPU writes over native multisample depth are not implemented". A compute fill is noted after its write is recorded and was not affected. When the noted fill had no write note yet, the sample now looks at the writes recorded over the HTILE or the stencil plane since the fill was noted. It takes the one write as the fill's note when that write is the only one, covers the whole range, and is a word fill of the noted pattern. A second write since, a different word or a fill of part of the range keeps the refusal. Everything else is proven as before: complete tracked stores, no CPU write since the fill, and the plane or HTILE words holding the fill once it has landed. The "native multisample depth metadata fill transition is not implemented" stop reported on boykopovar#6300 is set by a fill over the HTILE that does not cover all of it, or by any HTILE fill when the target's sampling never activated. Ghost's fill covers the whole HTILE, so its target was most likely refused at creation, and on boykopovar#6300 the fill's message replaced that refusal. Refusals now keep the first one, so a target refused at creation reports its creation reason after the fills. Tested: agc_driver_native_depth_separate_stencil runs Ghost's sequence (creation of a depth-only HTILE that is neither pipe-aligned nor ITERATE_256 with a separate stencil plane, clear 0 and stencil 0, a whole-HTILE fill of 0, a whole stencil plane fill of 0, then the first sample) with the fill stored, queued after it is noted, and queued before it is noted. Each one samples the cleared depth and passes only the stencil reference 0. A later queued stencil write, a queued HTILE fill of another word and a queued fill of part of the HTILE are refused, and a target refused at creation keeps its refusal after the fills. Without the change the fill queued after it is noted refuses "external GPU writes over native multisample depth are not implemented".
…nce its GPU write is recorded A compute dispatch of the memory-value fill kernel is noted twice: the dispatch path notes it from MatchMemoryValueFill before the fill runs (Dispatch.cpp), and storeBufferFill notes it again after FillBuffer has recorded its GPU write. On a native multisample depth target the second note refused "overlapping native multisample depth clear transitions are not implemented" for the HTILE, and the same refusal for the separate stencil plane, so a compute fill of either one never reached the sample. A second note of a pending fill is now taken as the same fill when it has the same pattern, the first note had no write note, and the one write recorded over the range since the first note is a word fill of the whole range with that pattern. That write's note becomes the fill's note, and the first note's write generation is kept, so CPU writes between the two notes are still refused. Two notes without that write between them still refuse as overlapping (agc_driver_native_depth_stencil's FillOverlap case, and a new stencil plane case). A memory-value fill that falls back to CPU stores, with no host import of the range, is still refused as overlapping. Tested: agc_driver_native_depth_separate_stencil runs Ghost's sequence with each fill noted, queued on the GPU and noted again, and samples the cleared depth and stencil 0. A stencil plane fill noted twice without a write between is refused. Without the change the second note refuses "overlapping native multisample depth clear transitions are not implemented".
MarcZX10
left a comment
There was a problem hiding this comment.
The implementation and regression report are detailed. The exact PR head is based on current main, required eligibility/conventions/intake/labels/report checks pass, and the reported lavapipe regressions include negative controls. The hosted Linux/Windows product and relinker jobs were skipped; I did not run local tests.
I’m requesting changes for these remaining correctness and contribution-rule items:
-
Required AGC validation comparison is missing from the report.
CONTRIBUTING.mdrequires the same focused tests onmainand this change, on the same machine and GPU, usingANYPS5_REQUIRE_VULKAN=1,ANYPS5_NO_SHADER_CACHE=1,VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, andctest -V. Please report both runs, confirm the validation layer was actually found, compare the logs for newVUID-errors, and give the GPU vendor/model/driver/OS. The current lavapipe report does not establish those required comparison details. -
The no-metadata sampling path accepts an unproven state.
CheckResourceacceptsdccAddress == 0for this target, while this PR says it cannot observe whether the guest performed the in-place expansion first and that an unexpanded sample will still receive the decompressed host image. The new fixture checks clear samples, not the title sequence that establishes this assumption. Please either provide evidence that the affected title expands before this descriptor is used and test that sequence, or keep refusing this descriptor until the guest expansion state is established. Otherwise the emulator can silently return different values from the guest memory the descriptor names. -
The
Unblockschecklist is incomplete. The repository requires each title ID to be paired with its Game bring-up discussion. The Grinch has #8606, but the Ghost of Tsushima and Spirit of the Island entries currently link to PR comments rather than Game bring-up discussions. Please add those discussion links, or narrow the checklist to titles with a qualifying discussion and mark the othersnone. -
Please close the overlap coordination loop. The live overlap scan reports shared
DepthSurface.cpp/test regions with open #7233 and #7371, also identified in this PR description. The repository asks authors to agree merge order for these overlaps and declareDepends onwhen one must land first. Please record the coordination/order and update the checklist if either PR is a prerequisite.
I have not found a reason to dispute the reported lavapipe regression results; the requests above concern the required validation evidence, the unverified no-metadata behavior, and the repository’s title/overlap checklist rules.
|
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.
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.
|
|
@EagleBearerYS Ghost of Tsushima (PPSA02225) on this PR's head
All three end with the same message, and none prints a What I can tell from it:
If that's the reader, then for Ghost the plane's current contents are in the host color image, not in guest memory. The clear proof would need to come from that target's last clear, or the import would need to take the plane from the color target's image. AI-assisted: yes (Claude Code) |
MarcZX10
left a comment
There was a problem hiding this comment.
Thanks for rebasing to the current main and updating the report with three Ghost of Tsushima runs on the PR head. The earlier native multisample refusal is now passed, but the run reaches a new guest access refusal over the same 0x870000 stencil-plane range. The reported overlap with a host-only multisampled color target also raises a concrete issue with the new CPU read used to prove the plane clear.
I’m keeping the request for changes for these remaining items:
- The separate-plane clear proof must account for the overlapping color target. The report says the plane range is also guarded as a multisampled color target and its samples are host-only; the title run now stops on a CPU read of exactly that range. Please trace the read to its source and establish how the implementation can prove the stencil plane’s clear without reading guest memory that is guarded or stale relative to the host color image. Add a regression for the relevant alias/guard path and update the game result after the fix. Until then, the reported title run does not establish this path as working.
- The no-metadata descriptor still accepts an unproven expansion state. The report says it cannot observe whether the guest expanded the plane before sampling and would return the decompressed host image even if it did not. Please provide evidence and a regression covering the guest sequence, or retain the refusal until that state is established.
- Required AGC validation comparison is still missing. Please report the same focused tests on
mainand this head usingANYPS5_REQUIRE_VULKAN=1,ANYPS5_NO_SHADER_CACHE=1, andVK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validationwithctest -Von the same machine and GPU; confirm the layer was found, compare for newly introducedVUID-messages, and name the GPU vendor/model/driver/OS. The existing lavapipe results do not include this required comparison. - Complete
Unblocksaccording to the repository checklist. The Ghost discussion is #4461. The Grinch is #8606. Spirit of the Island has no Game bring-up discussion yet, so please omit it fromUnblocksfor now (or add a qualifying discussion first). - Record overlap coordination and required ordering. The description identifies shared hunks with #7233 and #7371. Please record the authors’ agreed integration order and list the required PR number(s) on
Depends onif this branch needs them first.
The updated hosted eligibility, intake, conventions, labels and report checks pass; Linux/Windows product and relinker jobs are skipped, and I did not run local tests. I have not found grounds to dispute the reported lavapipe fixture results; the items above concern an observed guarded read on the title path, an explicitly unverified sampling assumption, required validation evidence, and the repository’s checklist/overlap rules.
|
Thanks for the new Ghost run and for documenting the exact next stop. The updated trace reaches a CPU read of the separate stencil plane, which the report also says overlaps a host-only multisampled color target. I have refreshed my review with a request to trace that read and prove the plane clear without relying on guarded or stale guest memory. I also noted that the no-metadata sampling assumption, required same-GPU Vulkan validation comparison, Spirit of the Island Unblocks entry, and #7233/#7371 ordering still need resolution. The existing lavapipe fixture results remain useful; I did not run them locally. |
|
@milescoviello thanks for the three Ghost of Tsushima Director's Cut (PPSA02225) runs and for tracing the stop this far. The range in the guard is exactly the stencil plane, and the only CPU read of exactly that range is this PR's clear check in @MarcZX10, thanks. The next commits, by point:
Points 4 and 5 are in the description now. @milescoviello, once the new head is up, would you run Ghost of Tsushima on it? Its new log line says whether the game clears or draws that colour target, which decides whether the next step is a copy of its samples into the stencil. |
|
@EagleBearerYS yes, I'll run Ghost of Tsushima (PPSA02225) on the new head when it's up, warm and cold, and post the log lines about that color target. The It's the same stop at 18 s. AI-assisted: yes (Claude Code) |
…rom that target
Ghost of Tsushima Director's Cut (PPSA02225) renders a 2-sample R8
colour target over the memory of a D32S8 target's separate stencil
plane. The native import proved the plane by reading it, and that read
hit the colour target's guard: "a CPU read of ... overlaps multisampled
color target ..., whose samples are only on the host".
MultisampleTarget gains a query that does not throw: the active colour
target whose guarded range overlaps a range, with its format, samples,
footprint and newest content. A pending fill the target absorbed, a
CMASK fast clear, or a clear it recorded with no draw since is a known
uniform value; a draw, a storage write or any refused metadata is not.
The target records its clears and whether it was drawn since.
prepareDepthSampling asks it for the depth, HTILE and stencil plane
ranges before reading guest memory. An R8 UNORM or UINT target with the
depth's sample count over exactly the plane, holding a known value,
gives the plane's initial stencil, which the first host clear uses. Any
other overlap refuses sampling ("native multisample stencil plane
aliases a multisampled colour target whose samples are only on the
host", or the depth or HTILE form) and prints the colour target's
address, format, samples and newest operation, at most eight times.
CheckCurrent runs the same query: a plane fill over an aliased plane is
proven from the colour target's value, not by reading the plane, and a
colour target that drew, changed value or appeared since the last proof
refuses sampling.
Tested: agc_driver_native_depth_aliased_stencil. A 4-sample R8 target
over the plane with an absorbed fill imports and the next stencil test
passes the fill value and not another; a second absorbed fill is proven
and taken; a colour draw after it refuses. The target drawn after its
fill, and an R8G8 target over the plane, refuse with the new reason. The
guest plane keeps its 0xa5 bytes throughout. Two and eight samples, and
another colour sample count, are not available on lavapipe. With the
product change reverted the cleared case throws the guard text above
(1 of 1); with it the mode passes 5 of 5.
… an in-place expand 5be005e let a descriptor with no metadata (META_DATA_ADDRESS 0, not pipe-aligned) sample a native multisample depth target from its decompressed host image, assuming the guest had expanded the plane. On hardware such a read sees decompressed depth only after an in-place expand, a draw with DB_RENDER_CONTROL DEPTH_COMPRESS_DISABLE (bit 6) and STENCIL_COMPRESS_DISABLE (bit 5) set, as radeonsi's in-place decompress sets them. DecodeDepthRenderControl reads DB_RENDER_CONTROL, DB_Z_INFO's format and sample count and DB_Z_READ_BASE for a draw with clear or compress-disable bits. The draw precheck hands it to NoteDepthRenderControl before the draw is dropped as drawing nothing (an expand draw has no depth test and no colour writes), draining the draw pipeline first for an expand, or for a clear over an existing depth surface. A draw over the target with the depth bit, and the stencil bit when the target has a stencil plane, marks the surface expanded; a clear draw, an HTILE clear or fill (NoteHtileDepthClear, NoteDepthMetadataFill, a cleared HTILE at DepthSurfaceView) and a plane fill clear the mark. CheckResource takes a descriptor without metadata only while the surface is marked, and otherwise refuses with "native multisample depth sampled metadata or XOR mismatch", printing the last DB_RENDER_CONTROL seen at most eight times. Tested: agc_driver_native_depth_expand_gate, for D32 and D32S8 with a separate stencil plane: a bare sample before any expand is refused, and after only the depth bit on D32S8; after the expand draw it gets the cleared and then the drawn depth; an HTILE fill, a clear draw and a plane fill (an HTILE mask clear on D32) each refuse it again until the next expand. The separate-stencil test now draws an expand before its bare sample. With the gate reverted the first bare sample is accepted (1 of 1); with it the mode passes 5 of 5.
A native D32S8 target whose separate stencil plane a multisampled R8 colour target covers is refused for sampling once that colour target has drawn. Taking it would need a GPU copy of the colour target's R8 samples into the depth image's stencil aspect; the debt file now names that gap and that the console's stencil reads of such a plane are not measured.
|
@EagleBearerYS I ran #9533 (5daa8cb) on PPSA03208 (current The next stop is at the first dispatch of a compute program, in I printed the descriptor at that check. The program samples the surface three times:
T# of the failing read: Here is how it gets there, as far as I can see. So the title reads the stencil of the native D32S8 target per sample, through a plain |
|
@oneandonlydean thanks for running it on PPSA03208 and for printing the descriptors, and good to see both of its stops clear. Your third read samples the stencil plane per sample through a plain |
…plane fill A native D32S8 target whose separate stencil plane a multisampled colour target covers with a draw, unknown content, or another format or sample count was refused at import, so sampling its depth failed as well. The plane is now imported unproven: its host stencil is not taken from it, depth sampling and depth-only draws continue, and a draw with a stencil test or a sample of the plane refuses with the stencil alias text and a line naming the colour target's state. A later whole-plane fill proves the plane from the fill byte without reading guest memory and clears the host stencil to it, provided a colour target still over the plane absorbed that fill as the same R8 byte at the same sample count; otherwise the fill is refused.
The sample shadow of a native multisampled depth target was moved from UNDEFINED to GENERAL with only the depth aspect. For a host format with stencil and without separateDepthStencilLayouts that breaks VUID-VkImageMemoryBarrier-image-03320, which the validation layer reported for every D32S8 shadow. The transition now names the stencil aspect too when the host format has one; the shadow still copies only the depth aspect.
|
Data point (Windows, AMD RX 6400), PR head 5daa8cb, merge-base a6dcea9 (merges cleanly into upstream/main). Target:
Only this one execution test was run; no title run and no other GPU. Logs are available as file names only: data_9533_rx6400_green1-3.log, data_9533_rx6400_red1-3.log. AI-assisted (Claude Code). |
|
@EagleBearerYS thanks, that matches what I saw: both stops clear with this PR, and the next one is the per-sample R8_UINT read of the stencil plane. A follow-up stacked on this one makes sense. Mention me when it's up and I'll run it on PPSA03208. |
|
Title data point (Windows, AMD Radeon RX 6400), PPSA02225, 600 s runs, one run each.
So on this title the PR moves the stop past the depth/stencil import; the next stop is a different refusal (CPU read of a multisampled color target). One run per state, so this says nothing about how often either stop occurs. No other title and no other GPU were run. Run folders on request (file names only: PPSA02225_rNT/run_072452, run_080153). |
|
@EagleBearerYS Ghost of Tsushima (PPSA02225) on the new head So the new commits don't change this title's path, which fits the depth-plane alias being left for your follow-up. I'll run that one when it's up. AI-assisted: yes (Claude Code) |
|
@milescoviello thanks for confirming the stop is unchanged on 1e07a65. That depth-plane alias is #9742's, stacked on this PR, and it's up now. With a depth-only HTILE whose every word proves |
…ear dispatch With main's pending clear model an HTILE mask clear dispatch is noted pending when its packet is decoded and takes its generation only when the dispatch is recorded. A whole-HTILE fill noted in between found no generation, took the clear as its own, and the arm that followed kept the fill's pattern, so the dispatch clear was proven as a fill. A fill now refuses while a dispatch clear is pending, from its notification until a sample takes it. agc_driver_native_depth_clear_refusals notes a fill between the clear's notification and its arm and expects the refusal.
# Conflicts: # core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
# Conflicts: # core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
Main's boykopovar#6727 retires an unwritten native multisample depth surface on a guest read instead of refusing it, and its own fixtures note a draw's write with NoteDepthSurfaceWrite before they expect a refusal. The D32S8 stencil fixture now does the same before it reads the stencil plane, so --stencil still checks that a written surface refuses.
A queued DMA_DATA fill of more than 64 KiB is stored through a host import. Windows compares its direct host imports instead of keeping them write-watched, so after the store the HTILE is no longer watched and the fill's note refuses with "native multisample depth metadata fill over unwatched memory is not implemented". On an NVIDIA GeForce RTX 3070 Laptop GPU, agc_driver_native_depth_driver_queued_fill failed that way in 4 of 4 runs. Noting the fill before the store only moves the refusal to the next sample, because the clear proof needs a write-watched HTILE. On Windows the queued mode now skips, and says why, when PrepareImportWatch reports compared imports. Linux still forces watched imports, so the case keeps running there. The debt entry records that such a fill is refused wherever host imports are compared.
jotitadev
left a comment
There was a problem hiding this comment.
Apple GPU / MoltenVK run of 1582cf6cc0. The two new driver-path tests check every case and pass it. Then the process aborts at exit on macOS, when the driver singleton tears down the device the test handed it.
Machine: Apple M2 Max, macOS 27.2, x86_64 under Rosetta 2. Vulkan loader + MoltenVK 1.4.2 (Vulkan SDK 1.4.363.0), and again against MoltenVK main + SPIRV-Cross #2704. Release, BUILD_TESTING=ON.
Base/method: PR #8658 feat/macos-port @ c5fa39620a (current main plus the macOS port), not main, because main does not build on macOS. This head was merged onto it with git merge-tree, with no conflicts, and the ':!docs' diff applied. Full rebuild first. This was done both on its own (with #9717's test added) and together with #9717, #9443 and #7705.
Results on both drivers, every run:
agc_driver_native_depth_retirement,_clears,_clear_refusals,_bda_clear,_stencil,_separate_stencil,_aliased_stenciland_expand_gatepass, and so doesagc_driver_native_multisample_depth.agc_driver_native_depth_driver_pathandagc_driver_native_depth_driver_queued_fillend asSubprocess aborted, after their summary lines:
Native depth on the driver's device cases checked=4 unavailable=2
libc++abi: terminating due to uncaught exception of type std::__1::system_error: recursive_mutex lock failed: Invalid argument
The macOS crash report has the stack:
exit -> __cxa_finalize_ranges
-> AgcDriver::DriverDetail::Driver::~Driver -> Driver::stop -> DevicePointer::Reset
-> AgcDriver::VulkanDevice::~VulkanDevice -> VulkanDevice::State::~State -> std::terminate
CheckDriverPath passes its device to the driver with DriverTestAccess::UseDevice and never takes it back. So the last reference goes away in the driver singleton's destructor at exit, and ~State runs after function-local statics it locks have already been destroyed. glibc lets you lock a destroyed mutex; macOS's pthread returns EINVAL. This is the same kind of failure as #8658's a036c56b8 (GuestMemory::GpuMutex). As a probe, I changed surfacesMutex() in DepthSurface.cpp to a mutex that is never freed. The abort then moved to mutex lock failed: Invalid argument, a plain std::mutex, in the same ~State. So more than one static is involved. A fix in the test, for example releasing the driver's device before CheckDriverPath returns, might avoid all of them. I haven't tried that.
Queued fill on macOS: the probe reports host imports resolve write protection: no ... imported ranges stay watched, and this file forces Watch outside Windows. So the queued case does not skip here. All its cases run and pass, at 2 and 4 samples (samples=2/4 clear=0/1: cleared by a queued DMA_DATA fill of 128 KiB from its HTILE through the driver and sampled). The abort comes only after that.
Full ^agc suite (877 tests, this PR with #9717, #9443 and #7705), both drivers: the failures from the #8658 base, plus these two, plus #7705's depth_plane_sampling_evicting, which I reported there.
GPUs tested: Apple M2 Max (MoltenVK 1.4.2; and MoltenVK main + SPIRV-Cross #2704).
Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.
…return agc_driver_native_depth_driver_path and agc_driver_native_depth_driver_queued_fill hand their Vulkan device to the driver singleton and never take it back. The device's last reference therefore died in Driver::~Driver at static destruction, after function-local statics that the device's state locks were already destroyed. glibc and Windows let a destroyed mutex be locked; macOS returns EINVAL, so both tests aborted after their summary lines with "recursive_mutex lock failed: Invalid argument" (Driver::~Driver -> Driver::stop -> DevicePointer::Reset -> VulkanDevice::~VulkanDevice -> std::terminate). jotitadev found this running the tests on an Apple M2 Max (macOS 27.2 under Rosetta 2, MoltenVK 1.4.2): boykopovar#9533 (review) CheckDriverPath now runs its cases in a lambda, drops its own reference to the device and stops the driver through a new DriverTestAccess::Stop. The driver then releases the device inside Driver::stop, under the GPU lock as at a normal shutdown, before main returns. The lambda ends first because the Context it copies holds the device's buffer pool: releasing the device while that copy is alive leaves the pool's buffers and memory to be freed after vkDestroyDevice. Both returns after UseDevice, the Windows queued-fill skip and the pass, go through the release. A failing Require still throws to main and leaves the device to static destruction, as before; the test has failed by then.
|
@jotitadev thank you for the macOS run and the stack. Your reading was right: the two driver-path tests handed their device to the driver and never took it back, so the driver singleton released it at exit, after the statics its teardown locks were gone. 5388641 (test only) gives the driver's device back before Could you rerun those two tests on your M2 Max with 5388641? A run with MoltenVK 1.4.2 alone is enough. |
Keeps both includes in DrawPrecheck.cpp: main's DeferredLabels.hpp and this branch's DepthSurface.hpp.
What
Stacked on #6300 (Gashrod1), which imports cleared native multisample D32S8 targets whose stencil lives in HTILE, and takes whole HTILE fills as clears. This branch carries #6300's two commits unchanged, merges
maininto them, and adds fourteen commits for a shape #6300 doesn't cover: a D32S8 target whose stencil is a separate plane and whose HTILE is depth-only.Titles with this shape, all stopping on
mainat the native depth import:native multisample stencil or depth format import is not implemented(BunnyFl's report).native multisample stencil import requires HTILE stencil metadata(milescoviello on feat(agc): import cleared native multisample D32S8 targets and whole HTILE fills #6300: 1, 2).The changes:
maininto feat(agc): import cleared native multisample D32S8 targets and whole HTILE fills #6300's head c11074b. Three conflicts, each resolved by keeping both sides:prepareDepthSampling: feat(agc): import cleared native multisample D32S8 targets and whole HTILE fills #6300's stencil checks, withmain's HTILE line (752cca1 dropped the ITERATE_256 requirement).NoteHtileDepthClearandNoteDepthMetadataFill: feat(agc): import cleared native multisample D32S8 targets and whole HTILE fills #6300's proofs, written withmain'sDepthSamplingState::Refuse(the first refusal wins), ahead ofmain'sForgetClearand plane-fill paths.CheckDepthTargettakes both feat(agc): import cleared native multisample D32S8 targets and whole HTILE fills #6300'sClearSourceandmain'siterate256.mainsamples a native target through a shadow refreshed at view lookup.DB_STENCIL_CLEAR. The plane is read once, between taking the ranges' generations and the final check, so a racing write still refuses.dccAddress0, not pipe-aligned), as well as the target's HTILE, when address, format, XOR and ITERATE_256 match. Any other metadata still refuses.HtileMetadataBytes(extent)is the same word and proves the clear.MultisampleTargetgains a query that doesn't throw: the active colour target whose guarded range overlaps a range, with its format, samples, footprint and newest content. A fill the target absorbed, a CMASK fast clear, or a clear with no draw since is a known value; a draw, a storage write or refused metadata is not.prepareDepthSamplingasks it for the depth, HTILE and plane ranges before reading guest memory. An R8 UNORM or UINT target with the depth's sample count over exactly the plane, holding a known value, gives the plane's stencil.CheckCurrentruns the same query: a plane fill over an aliased plane is proven from the colour target's value, not by reading the plane.DB_RENDER_CONTROL's depth compress-disable bit (bit 6), and the stencil one (bit 5) when the target has a stencil plane, marks the surface expanded, as radeonsi's in-place decompress sets them. A clear draw, an HTILE clear or fill, and a plane fill clear the mark.CheckResourcetakes a descriptor without metadata only while the surface is marked. Otherwise it refuses with "native multisample depth sampled metadata or XOR mismatch" and prints the lastDB_RENDER_CONTROLseen, at most eight times.NoteDepthRenderControlbefore an expand draw, which has no depth test and no colour writes, is dropped as drawing nothing.VUID-VkImageMemoryBarrier-image-03320withoutseparateDepthStencilLayouts. The transition now names the stencil aspect too when the host format has one. JJenkx found the same on an RX 6650 XT.Co-authored-by: JJenkx).enqueueDmaPacket's large-fill branch queuedstoreBufferFill(..., false, false), whose last argument isnoteMetadata, so a fill over 64 KiB never noted HTILE or colour metadata, and the next sample took this PR's fill transition for an external GPU write. dd7ad46 notes it, as the synchronous and small queued paths do. 6bc1899 adds a test seam,friend struct DriverTestAccess;(asVulkanDeviceTestAccessdoes), so the test runs native multisample depth through the driver's own device, following JJenkx's approach. Onmaina metadata fill over a live native multisample target's HTILE refuses anyway, so the gap shows only with this PR's fill transition.main8b3a6ba: clean. The PR's changed lines are the same as before the merge (git diff -U0patch-id); only their context moved.main3ca07d0, which brings fix(agc): separate possible writes from complete coverage #7233 (MarcZX10): possible writes, an HTILE clear's note, arm and complete steps, and the drain inDriver::WaitIdle. Each conflict keeps both sides:CheckCurrent:main's "native multisample depth clear has not been recorded" check comes first, then this PR's checks, unchanged.NoteHtileDepthClear: this PR's refusals for a stencil surface and an unproven target come first, thenmain's overlap check and pending flag, which now also set this PR's clear aspects.main'sArmHtileDepthCleartakes the clear's generation, in place of this PR's immediate one.main'sClearFaultcases andDriverTestAccess::GetDevicebeside this PR'sClearSourceandUseDevice, with oneCheckDepthTargetsignature.main's model needs. Without it: "native multisample depth clear has not been recorded".--driver-queued-fillwaits only for the driver queue, throughDriverTestAccess::WaitQueue.main's 71decdc makesDriver::WaitIdlealso wait for the device, so the case no longer sampled while its fill was queued. Without it: "CPU writes raced native multisample depth clear".git diff -U0patch-id changes), by these resolutions and adaptations.main's model a dispatch clear is pending from its note until it's armed. A whole-HTILE fill noted in between took the clear as its own, and the arm kept the fill's pattern, so the dispatch clear was proven as a fill. Such a fill now refuses: "native multisample depth metadata fill over a pending HTILE clear dispatch is not implemented". It's the refusal from the composition with fix(agc): settle queued HTILE clears before native depth use #7371 (5e8a1cd), which Amoenus asked to keep with this PR's fill support (comment).main8b3e398, which brings fix(agc): resolve and render a multisampled target through its sRGB twin format #8847 (JJenkx's sRGB twin). One conflict, inMultisampleTargetView: each overload keeps this PR'sdrawnmark and returnsmain'sView(target.format). The PR's changed lines are otherwise the same, less one thatmainnow makes too (auto& acquiredin place ofconst auto&).mainb7d1d47, which brings fix(agc): settle queued HTILE clears before native depth use #7371 (Amoenus's queued HTILE clear handoff). InDepthSurface.cpp, fix(agc): settle queued HTILE clears before native depth use #7371'sclearCompletionQueuedfield and its reset sit beside this PR's clear fields, both kept. The PR's changed lines are the same as before this merge (git diff -U0patch-id), and the mergedDepthSurface.cppis byte for byte the composition posted in fix(agc): settle queued HTILE clears before native depth use #7371's thread (5e8a1cdb83).maind6e7ab4, which brings fix(agc): retire an unwritten native multisample depth surface on guest access #6727 (simonbronk). InDraw.cppeachDepthSurfaceViewcall keeps this PR'sstencilTestand gains fix(agc): retire an unwritten native multisample depth surface on guest access #6727'sNoteDepthSurfaceWrite, and in the debt entry fix(agc): retire an unwritten native multisample depth surface on guest access #6727's sentence follows this PR's. fix(agc): retire an unwritten native multisample depth surface on guest access #6727 retires an unwritten native multisample depth surface on a guest read instead of refusing it (#6727), and its own fixtures note a host write withNoteDepthSurfaceWritebefore they expect a refusal.CheckStencilTargetnow does the same before it reads the stencil plane, so--stencilstill checks that a written D32S8 target refuses. Apart from that line, the PR's changed lines are the same as before the merge, with thestencilTestarguments now inside fix(agc): retire an unwritten native multisample depth surface on guest access #6727's blocks.agc_driver_native_depth_driver_queued_fillnow skips with that reason whenPrepareImportWatchreports compared imports. Linux still forces watched imports, so the case keeps running there. The debt entry records that such a fill is refused wherever host imports are compared.Overlap:
prepareDepthSamplingandNoteHtileDepthClearas well, and conflicts withmainitself. None of them imports a separate stencil plane.DepthSurface.cppkeeps fix(agc): settle queued HTILE clears before native depth use #7371's pending, armed and completed order and its range-limitedSyncThroughoutsidesurfacesMutex, with this PR's clear-aspect and plane checks after fix(agc): settle queued HTILE clears before native depth use #7371's pending-clear refusal.DepthSurfaceViewand inMultisampleTarget.cpp'sguard. This PR goes after it and rebases onto it, agreed in fix(agc): retire a multisampled color target the title wrote over #8223's thread (comment), keeping its claims and retires. At that rebase, a retired colour target over a native stencil plane keeps its known fill value, or else leaves the plane unproven, so a stale guest plane is never taken as the clear value.MultisampleTarget.cpp, where this PR records the target's clear forAlias(). Composed,clearedtakes the initial value only when it's a clear (the known clear, DCC or CMASK), so a plane under a target that starts from the guest's contents stays unproven. This PR goes after feat(agc): preserve initial native multisample color contents #6973 and rebases over it, agreed in its thread (comment), keepingensureGeneralLayout()beside theclearedanddrawnassignments inRecreate.NoteDepthSurfaceWritefollows the twoDepthSurfaceViewcalls inDraw.cppthat this PR gives the draw'sstencilTest, both debt edits are kept, and this PR's stencil fixture notes a host write as fix(agc): retire an unwritten native multisample depth surface on guest access #6727's fixtures do.guardedColorBytes, which the guard and the alias query share. This PR goes after it (order note in its thread).DepthSurface.cppondepthCopySourceActive. This PR'sRequireStencilProvengoes only in itselsebranch, afterCheckCurrent(): a DB depth copy never reads the stencil plane, sinceDecodeDepthCopyPassrefusesSTENCIL_COPY(milescoviello). This PR goes after it, agreed in its thread (comment).DrawPrecheck.cpp, and both stay. This PR goes after it (note).add_library_testand moves test files. The order is proposed in its thread (comment): this PR first; if test: organize library tests and label CTest suites #6044 lands first, this PR's new native depth registrations move toadd_library_test(graphics ...)at its next merge ofmain.DepthSurface.cpp's includes (it addsMultisampleTextureLayout.hppwhere this PR addsPipeline.hpp) and the native multisampled depth debt entry, so they conflict in text only. They compose: both includes stay, and the two sentences merge. This PR goes after it (note).vkCmdClearDepthStencilImagecall when aDepthSurfaceis created: it widens the range toviewInfo.subresourceRange, and this PR takes the stencil's clear value from an aliased stencil plane. Composed, the call takes this PR's clear value and fix(agc): transition both aspects of combined depth/stencil images an… #9807's range. This PR goes after it (note).Tested
On Linux with lavapipe (llvmpipe, LLVM 20.1.2), which samples D32S8 only at four samples, each case below runs at four samples and the two- and eight-sample cases report unavailable. The RTX 3070 run covers two and eight samples.
New ctest
agc_driver_native_depth_separate_stencil(--separate-stencil). Each red below reverts that change's driver hunk and keeps the test:clearAspectsline reverted)After every commit:
ctest -R 'native_multisample|native_depth|depth|htile|stencil'40/40, with 2 skipped as onmain(agc_driver_native_depth_bda_clearandagc_driver_sample_order_recipe_depth_locations).Linux, as CI runs it, at 5daa8cb (Ubuntu 24.04, GCC 13.3, unprivileged user):
guest_socket_stream_options,guest_socket_address_lengthandguest_tcpfail the same way onmainthere, because that machine has no usable sockets.check_test_registration.py: none new.check_skips.py:guest_sce_net, for the same reason.GitHub's runners at 5daa8cb (run): on Linux,
agc_driver_native_depth_separate_stencilandagc_driver_native_depth_stencilpass ×3. On Windows the build succeeds and both skip, since that runner has no Vulkan device. The libc and libkernel suites pass on both.check_conventions.pyat 514643a: no errors and no comment lines added. One warning,debt-length, on the native multisampled depth entry: 3,192 characters, against 1,403 onmain.New ctests for 2d4c1da and 439557b:
agc_driver_native_depth_aliased_stencil(2d4c1da): a 4-sample R8 target over the plane with an absorbed fill imports, and the next stencil test passes the fill value and no other. A second absorbed fill is proven and taken, and a colour draw after it refuses. A target drawn after its fill, and an R8G8 target over the plane, refuse with the new reason. The guest plane keeps its 0xa5 bytes throughout. With the product change reverted the cleared case throws the guard text (1 of 1); with it the mode passes 5 of 5.agc_driver_native_depth_expand_gate(439557b), for D32 and for D32S8 with a separate plane: a bare sample before any expand is refused, and on D32S8 also after only the depth bit. After the expand draw it gets the cleared and then the drawn depth. An HTILE fill, a clear draw and a plane fill (an HTILE mask clear on D32) each refuse it again until the next expand. With the gate reverted the first bare sample is accepted (1 of 1); with it the mode passes 5 of 5. The separate-stencil test now draws an expand before its bare sample.NVIDIA GeForce RTX 3070 Laptop GPU at 514643a (driver 617.42, the only device enumerated, Windows 11, WinLibs GCC 15.2.0, Release,
ANYPS5_REQUIRE_VULKAN=1; GPU clocks weren't held, pass/fail only): the eight native depth tests,agc_driver_native_multisample_depthandagc_driver_native_depth_{retirement,clears,clear_refusals,stencil,separate_stencil,aliased_stencil,expand_gate}, pass 5 runs in a row, with their 2-, 4- and 8-sample cases.Validation layer,
mainagainst this PR (CONTRIBUTING's AGC rule), on one GitHub Linux runner (run). Both runs usedVK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation,ANYPS5_NO_SHADER_CACHE=1,ANYPS5_REQUIRE_VULKAN=1andctest -V, withVK_LOADER_DEBUG=layerto show the layer loading. The device was llvmpipe (LLVM 20.1.2) on Mesa 25.2.8, Ubuntu 24.04.5, Khronos validation layers 1.3.275.agc_driver_native_multisample_depth,agc_driver_native_depth_{retirement,clears,clear_refusals}andagc_driver_msaa_dcc_clear_4on both trees, plus this PR'sagc_driver_native_depth_{stencil,separate_stencil,aliased_stencil,expand_gate}, whichmaindoesn't have.main's tree (a6dcea9) ran its five once and this head's nine three times.VK_LAYER_KHRONOS_validation9 times onmainand 51 with this PR, and neither log haswas not found but was requested by env var VK_INSTANCE_LAYERS.VUID-VkDeviceCreateInfo-pNext-pNext, for a device-creation structure newer than that layer version. This PR adds noVUID-message.precise_wait(libc, Linux) andguest_raise_in_system_call(libkernel, Windows), which other PRs' runs on those runners have hit too.Validation layer, the previous head against this one, on one GitHub Linux runner (run), with the same settings and device. The previous head's 6 native depth tests log
VUID-VkImageMemoryBarrier-image-0332039 times, inagc_driver_native_depth_stencil:vkCmdPipelineBarrier()on aVK_FORMAT_D32_SFLOAT_S8_UINTimage with onlyVK_IMAGE_ASPECT_DEPTH_BIT, the sample shadow's barrier. This head's 8 don't log it, and add noVUID-message.Title runs, on 5daa8cb:
maind6eafa5, the title relinked with the same build (1, 2). Onmainit aborts about 2 s in, before its first frame. With this PR it doesn't stop:main's libs rebuilt for both, 600 s each; comment). Onmainit stops atnative multisample stencil or depth format import is not implemented. With this PR nonative multisamplerefusal appears, and the run stops later at the CPU read of the stencil plane that a 2-sample colour target covers. 514643a doesn't make that read.mainplus other open PRs it needs (comment): both of its stops clear, the format refusal and the HTILE stencil requirement, and its two whole fills are taken as clears. The next stop is a per-sampleR8_UINTread of the stencil plane, refused byCheckResource, which feat(agc): sample the stencil plane of a native multisampled D32S8 target #9717, stacked on this PR, covers.Title run, on 514643a: Ghost of Tsushima Director's Cut (PPSA02225), milescoviello, Linux, RTX 4070 Ti, NVIDIA 615.71.09, warm and cold, with a pad script cycling through the menu buttons (comment).
native multisample depth 0x1544ed0000+0x1fe0000 aliases multisampled colour target 0x1544ed0000+0x1fe0000 (vk format 100, 2 samples), newest clear 0x00000000 ..., thennative multisample depth or HTILE aliases a multisampled colour target whose samples are only on the host.Ghost of Tsushima Director's Cut (PPSA02225) with the stacked fix(agc): accept a colour alias over a native multisample depth plane when HTILE proves its clear #9742 and feat(agc): sample the stencil plane of a native multisampled D32S8 target #9717, and milescoviello's feat(agc): draw one-sample color targets beside a multisampled depth target with sample 0's coverage #8115 and fix(agc): draw a PS_ITER_SAMPLE program once per pixel into a one-sample color target #8121, on the test branch
test/ghost-9742-9717(3ec696f, on 514643a) with those two merged on top (comment): milescoviello, Linux, RTX 4070 Ti, NVIDIA 615.71.09, 20 GiB cap. Warm and cold both reach the 600 s limit with no refusal and no crash. In their words, the game shows its brightness calibration screen, with the mask rendered correctly, and then its intro. The only native depth line left is fix(agc): accept a colour alias over a native multisample depth plane when HTILE proves its clear #9742's alias line, printed once and accepted.Focused tests on other GPUs, on 5daa8cb:
agc_driver_native_multisample_depthpasses 3 of 3, and fails 3 of 3 withDepthSurface.cppfrom the merge-base.maind6eafa5 (comment): the 7 focused tests pass, 5 of them onmaintoo. This PR's stencil tests loggedVUID-VkImageMemoryBarrier-image-03320, which 514643a removes. Their production-DMA diagnostic found a queued DMA fill over native multisample depth that the next sample refuses. dd7ad46 takes their fix, with them as co-author: onmaina metadata fill over a live native multisample target's HTILE refuses anyway, so the gap shows only with this PR's fill transition.VUID-(comment).6bc1899 and dd7ad46, the queued DMA fill, on GitHub's runners (run), against 6bc1899, so that only dd7ad46's driver hunk is reverted:
agc_driver_native_depth_driver_queued_fillfails 3 of 3 without it, with "AGC graphics: external GPU writes over native multisample depth are not implemented", and passes 10 of 10 with it, for clears 0 and 1. With fix(agc): import native multisample D32S8 targets with a separate stencil plane and a depth-only HTILE #9533's native depth tests,agc_driver_native_depth_driver_pathandagc_driver_pipelined_dma, 11 tests pass 10 of 10 on Linux. On Windows they build and pass, with the Vulkan tests skipping.agc_driver_native_depth_driver_pathpasses, and the two new tests pass until-fail:20.VUID-VkDeviceCreateInfo-pNext-pNext, and the two commits add noVUID-message.1e07a65,
main8b3a6ba merged in (run): the 13 native depth, DCC clear and pipelined DMA tests pass 10 of 10 on Linux, none skipped. On Windows they build and pass, with the 12 Vulkan tests skipping. The libc and libkernel suites pass on both.mainagainst this head, in the same run: one GitHub Linux runner, Ubuntu 24.04.5, llvmpipe (Mesa 25.2.8, LLVM 20.1.2), withANYPS5_REQUIRE_VULKAN=1,ANYPS5_NO_SHADER_CACHE=1,VK_LAYER_KHRONOS_validationandctest -V.main's arm runs the 7 of the 13 tests it has, and this head's arm runs all 13. The layer loads in both runs, with no "was not found" line. Both log onlyVUID-VkDeviceCreateInfo-pNext-pNext, and this head adds noVUID-message.check_conventions.pyon the merged head: no errors and no comment lines added. The one warning is the samedebt-lengthon the native multisampled depth entry, at 3,192 characters.8b2b308 and a6b6274, on a cloud Linux machine (CI's configure flags, lavapipe on Mesa 25.2.8, unprivileged user): both build, and the 14 native depth, DCC clear and pipelined DMA tests pass; on a6b6274 they pass
--repeat until-fail:10.DepthSurface.cpphunk reverted and the test kept,agc_driver_native_depth_clear_refusalsaccepts the fill ("multisample target refusal did not match metadata fill over a pending HTILE clear dispatch").^agcset, once each: 880 of 881 on a6b6274 and 875 of 875 onmain3ca07d0, with 60 skipped on both. The six extra tests are this PR's. The one failure,agc_driver_sgpr_pattern_fill_keys("the dispatch completed 17 times without a pending write over the keys"), passed 20 of 20 alone and 881 of 881 in a second sweep, failed the same way onmainin a third sweep, and isn't in a file this merge touches.229d718 (run): the 13 native depth, DCC clear and pipelined DMA tests pass 10 of 10 on Linux, none skipped. On Windows they build and pass, with the 12 Vulkan tests skipping. Validation against
mainin the same run: the layer loads in both runs, with no "was not found" line, and both log onlyVUID-VkDeviceCreateInfo-pNext-pNext. In that run's libc suite,precise_waitfailed on the Linux runner with this head, under its strict median bounds;main's arm passed it.1d16d50,
mainb7d1d47 merged in (run): the 13 native depth, DCC clear and pipelined DMA tests pass 10 of 10 on Linux, none skipped. On Windows they build and pass, with the 12 Vulkan tests skipping. Validation againstmainin the same run, on the same Linux runner:main's arm runs the 7 of the 13 tests it has, and this head's arm runs all 13. The layer loads in both runs, with no "was not found" line. Both log onlyVUID-VkDeviceCreateInfo-pNext-pNext, and this head adds noVUID-message. The libc and libkernel suites pass on both runners. The libc and libkernel suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.check_conventions.pyon 1d16d50: no errors and no comment lines added. The one warning isdebt-lengthon the native multisampled depth entry, now 3,308 characters with a6b6274's clause.9afaa90,
main11f976b merged in (clean; the PR's own diff is unchanged) (run): the 13 native depth, DCC clear and pipelined DMA tests pass 10 of 10 on Linux, none skipped. On Windows they build and pass, with the 12 Vulkan tests skipping. In the same run, validation againstmain:main's arm runs the 7 of the 13 tests it has, the layer loads in both runs with no "was not found" line, and both log onlyVUID-VkDeviceCreateInfo-pNext-pNext, so this head adds noVUID-message. The libc and libkernel suites pass on both runners. The libc and libkernel suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.a45dff8,
maind6e7ab4 merged in (run): on GitHub's Linux runner, the 13 native depth, DCC clear and pipelined DMA tests pass 10 of 10, none skipped. Without the fixture line,agc_driver_native_depth_stencilfailed on this merge with an empty refusal where it expects "sample-preserving guest publication" (run). In the same run, validation againstmain:main's arm runs the 7 of the 13 tests it has, the layer loads in both runs (11 and 210 times) with no "was not found" line, and both log onlyVUID-VkDeviceCreateInfo-pNext-pNext, so this head adds noVUID-message. On GitHub's Windows runner they build and the 12 Vulkan tests skip, so its lines are the suites only. The libc and libkernel suites pass on both runners. The libc and libkernel suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.NVIDIA GeForce RTX 3070 Laptop GPU at 082ef25, the fix(agc): import native multisample D32S8 targets with a separate stencil plane and a depth-only HTILE #9533, fix(agc): accept a colour alias over a native multisample depth plane when HTILE proves its clear #9742 and feat(agc): sample the stencil plane of a native multisampled D32S8 target #9717 stack before the fix(agc): retire an unwritten native multisample depth surface on guest access #6727 merge (driver 617.42, Windows 11, WinLibs GCC 15.2.0, Release,
ANYPS5_REQUIRE_VULKAN=1; GPU clocks weren't held, pass/fail only): 11 of the 12 native depth tests pass 5 of 5 at 2, 4 and 8 samples.agc_driver_native_depth_driver_queued_fillfailed 4 of 4 with "AGC graphics: native multisample depth metadata fill over unwatched memory is not implemented". On Windows the queued fill still refuses, as onmain; 1582cf6 makes the test skip there with that reason. A run of 1582cf6 on that GPU is pending.1582cf6 (run): on GitHub's Linux runner, the 13 native depth, DCC clear and pipelined DMA tests pass 10 of 10, none skipped,
agc_driver_native_depth_driver_queued_fillamong them with watched imports. In the same run, validation againstmain:main's arm runs the 7 of the 13 tests it has, the layer loads in both runs (11 and 210 times) with no "was not found" line, and both log onlyVUID-VkDeviceCreateInfo-pNext-pNext, so this head adds noVUID-message. On GitHub's Windows runner the change builds and the 12 Vulkan tests skip, so its lines are the suites only. The libc and libkernel suites pass on both runners. The libc and libkernel suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.tools/check_skips.pyaccepts the new skip line on the Windows job, where anyagc*skip is expected; on Linux the case can't skip, since it forces watched imports.check_conventions.py: no errors and no comment lines added; the one warning isdebt-lengthon the native multisampled depth entry, now 3,990 characters.5388641, after @jotitadev's macOS run of 1582cf6 (review): on an Apple M2 Max with MoltenVK 1.4.2, on feat: macOS host support (Apple Silicon via Rosetta 2, Vulkan on MoltenVK) #8658's macOS port, the eight native depth tests and
agc_driver_native_multisample_depthpass.agc_driver_native_depth_driver_pathandagc_driver_native_depth_driver_queued_fillpass every case and then abort at exit withrecursive_mutex lock failed: Invalid argument. The test handed its device to the driver and never took it back, so the driver singleton released it at exit, after statics its teardown locks had been destroyed.^agc_driver_native_depthandagc_driver_native_multisample_depth: on Linux 10 tests pass 10 of 10, andagc_driver_native_depth_bda_clearskips as onmain. On Windows the 11 build and skip, since that runner has no Vulkan device. The libc and libkernel suites pass on both runners. They ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.Not tested: Spirit of the Island (PPSA13934), and The Grinch and PPSA03208 on 514643a and later.
Next stops to expect:
R32_SFLOATcolour target cleared to 0 covers exactly the depth range, so the depth import refuses with the alias text (milescoviello's run above). fix(agc): accept a colour alias over a native multisample depth plane when HTILE proves its clear #9742, stacked on this PR, covers it. As JJenkx's source review notes, the colour clear alone doesn't show that the depth agrees with it: that needs the target'sclearDepthand its HTILE.R8_UINTread of the stencil plane refuses (PPSA03208); feat(agc): sample the stencil plane of a native multisampled D32S8 target #9717, stacked on this PR, covers it.APS5_PIPELINE_DMAset, a large queued DMA fill over the depth's metadata isn't noted, so the next sample refused it as an external write (JJenkx). Fixed in this PR by dd7ad46 (Co-authored-by: JJenkx) where host imports stay write-watched, as on Linux in our runs. The queued fill is stored through a host import, and where host imports are compared rather than watched, as Windows' direct imports always are, the fill still refuses, as onmain: on an NVIDIA GeForce RTX 3070 Laptop GPU,agc_driver_native_depth_driver_queued_fillfailed 4 of 4 with "native multisample depth metadata fill over unwatched memory is not implemented". 1582cf6 makes that case skip on Windows with the reason, and a run of it on the RTX 3070 is pending. Back-to-back HTILE fills of one pattern still refuse as overlapping clear transitions, queued or not.main0db47b2. The only conflict wasDrawPrecheck.cpp's include block:mainaddedDeferredLabels.hpp(perf(agc): draw finisher pipeline (APS5_DRAW_PIPELINE) #6946) and this branchDepthSurface.hpp, and both are kept. On GitHub's runners (run), theagc_driver_native_depth*andagc_driver_native_multisample_depth*tests pass 10 runs in a row on Linux and on Windows. The libc and libkernel suites pass on both, run withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.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)