mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
fix(agc): sample a native multisample depth target through a descriptor 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".
This commit is contained in:
1 parent
7d6e968d6b
commit
5be005ea13
3 files changed
+21
-3
No files matched your search
@@ -401,7 +401,9 @@ public:
|
||||
if (target.samples == 1u) return;
|
||||
Require(resource.baseAddress == target.address && resource.width == target.extent.width && resource.height == target.extent.height && resource.samples == target.samples && resource.format == (target.format == VK_FORMAT_D16_UNORM ? 7u : 22u), "native multisample depth sampled identity or format mismatch");
|
||||
Require(resource.dimension == TextureDimension::k2DMsaa && resource.tileMode == TextureTileMode::kZ64KBX && resource.depthOrLastArray == 0u && resource.baseArray == 0u && resource.baseLevel == 0u && resource.lastLevel == 0u && resource.mipCount == 1u && resource.allocatedMipCount == 1u && resource.minLod == 0u, "native multisample depth sampled array, mip or layout is not implemented");
|
||||
Require(resource.pipeBankXor == target.pipeBankXor && resource.dccAddress == target.htileAddress && resource.iterate256 == target.iterate256 && resource.dccPipeAligned == target.htilePipeAligned && !resource.dccAlphaOnMsb, "native multisample depth sampled metadata or XOR mismatch");
|
||||
const bool htile = resource.dccAddress == target.htileAddress && resource.dccPipeAligned == target.htilePipeAligned;
|
||||
const bool bare = resource.dccAddress == 0u && !resource.dccPipeAligned;
|
||||
Require(resource.pipeBankXor == target.pipeBankXor && (htile || bare) && resource.iterate256 == target.iterate256 && !resource.dccAlphaOnMsb, "native multisample depth sampled metadata or XOR mismatch");
|
||||
}
|
||||
|
||||
void ApplyFastClear() {
|
||||
|
||||
@@ -1050,6 +1050,18 @@ void CheckSeparateStencilTarget(Context context, std::uint32_t fragments, bool o
|
||||
const auto count = extent.width * extent.height * fragments;
|
||||
Buffer output(context, (count + 2u) * 16u, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
const Fetch fetch(context, *texture, output, FetchShader(extent.width, extent.height, fragments, false, true));
|
||||
auto bareWords = words;
|
||||
bareWords[6] &= ~((0xffu << 24u) | (1u << 21u) | (1u << 19u));
|
||||
bareWords[7] = 0u;
|
||||
auto bare = CachedSampledTexture(context, bareWords);
|
||||
Require(bare != nullptr && bare != texture && CachedSampledTexture(context, bareWords) == bare, "native depth sampled through a descriptor without HTILE was not given its own reused view");
|
||||
const Fetch bareFetch(context, *bare, output, FetchShader(extent.width, extent.height, fragments, false, true));
|
||||
auto xorWords = bareWords;
|
||||
xorWords[0] ^= 0x04u;
|
||||
TargetRefuses([&] { CachedSampledTexture(context, xorWords); }, "native multisample depth sampled metadata or XOR mismatch");
|
||||
auto otherWords = words;
|
||||
otherWords[7] += 1u;
|
||||
TargetRefuses([&] { CachedSampledTexture(context, otherWords); }, "native multisample depth sampled metadata or XOR mismatch");
|
||||
const auto sample = [&](const Fetch& reader, const DepthRaster* raster, float offset, std::optional<float> drawn) {
|
||||
std::memset(output.Bytes().data(), 0xa5, output.Bytes().size());
|
||||
if (raster != nullptr) {
|
||||
@@ -1072,11 +1084,13 @@ void CheckSeparateStencilTarget(Context context, std::uint32_t fragments, bool o
|
||||
}
|
||||
};
|
||||
sample(fetch, nullptr, 0.0f, std::nullopt);
|
||||
sample(bareFetch, nullptr, 0.0f, std::nullopt);
|
||||
{
|
||||
const DepthRaster miss(context, target, view, StencilUse{VK_COMPARE_OP_EQUAL, VK_STENCIL_OP_KEEP, static_cast<std::uint8_t>(clearStencil + 1u)});
|
||||
sample(fetch, &miss, 0.375f, std::nullopt);
|
||||
const DepthRaster hit(context, target, view, StencilUse{VK_COMPARE_OP_EQUAL, VK_STENCIL_OP_KEEP, clearStencil});
|
||||
sample(fetch, &hit, 0.25f, 0.25f);
|
||||
sample(bareFetch, nullptr, 0.0f, 0.25f);
|
||||
}
|
||||
if (filling) {
|
||||
const DepthRaster replace(context, target, view, StencilUse{VK_COMPARE_OP_ALWAYS, VK_STENCIL_OP_REPLACE, 0xc3u});
|
||||
@@ -1090,10 +1104,12 @@ void CheckSeparateStencilTarget(Context context, std::uint32_t fragments, bool o
|
||||
sample(fetch, &kept, 0.25f, 0.25f);
|
||||
const DepthRaster cleared(context, target, view, StencilUse{VK_COMPARE_OP_EQUAL, VK_STENCIL_OP_KEEP, clearStencil});
|
||||
sample(fetch, &cleared, 0.375f, 0.25f);
|
||||
sample(bareFetch, nullptr, 0.0f, 0.25f);
|
||||
}
|
||||
Require(std::equal(imported.begin(), imported.end(), stencil.Data()), "native depth sampling with a separate stencil plane changed the guest stencil plane");
|
||||
bare.reset();
|
||||
texture.reset();
|
||||
std::printf("Native depth with a separate stencil plane samples=%u clear=%u fill=%u: imported, stencil-tested and sampled%s\n", fragments, one, filling, filling ? " across a depth-only HTILE fill" : "");
|
||||
std::printf("Native depth with a separate stencil plane samples=%u clear=%u fill=%u: imported, stencil-tested and sampled with and without HTILE%s; other metadata and XOR refused\n", fragments, one, filling, filling ? " across a depth-only HTILE fill" : "");
|
||||
}
|
||||
|
||||
void CheckEligibility(Context context) {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
- [Native multisampled depth clears](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) accept the recognized HTILE mask kernel's direct full-range dispatch after its GPU writes complete. Every metadata byte needs tracked driver-store coverage since notification, no intervening CPU or depth write, and HTILE words proving the current clear value of zero or one. Partial, overlapping, indirect and unproven producers remain unsupported. Existing sampled views retain the native image; guest depth publication and metadata-fill transitions remain unimplemented. Windows shared imports retain write tracking through separate aliases; private host imports that lose tracking and copied or mirrored HTILE uploads remain unsupported. Clear-word encoding and console equivalence remain unmeasured on PS5 hardware.
|
||||
- [Native depth allocation retirement](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) covers sampling-eligible multisampled owners only. Successful release notifications must cumulatively cover both complete depth and HTILE ranges; protection changes, failed releases and partial coverage keep the original guards. Retired owners leave lookup and metadata routing, while held views and recorded work retain their images. Retirement of single-sample or sampling-ineligible depth attachments and console equivalence remain unimplemented or unmeasured. The regression uses real allocation-registry operations with a no-op host-release callback, so it does not validate the host unmap backend.
|
||||
- [Native MSAA depth attachment feedback](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp) is not implemented. A draw sampling a native multisampled depth view while attaching its source image throws before pipeline creation or render-pass recording, including read-only attachment feedback. Sampling that image in a separate draw or dispatch remains supported. The refusal compares the held native image views and their device and attachment identity; single-sample depth behavior is retained.
|
||||
- [Native multisampled depth sampling](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) accepts numeric D16 or D32, and D32 with an 8-bit stencil plane whose state is in HTILE or, with a depth-only HTILE, in the plane, two/four/eight samples, one Z_X slice and mip, and pipe-aligned HTILE without VRS, with ITERATE_256 on or off: the initial import reads no compressed Z planes, and Mesa's HTILE clear words (`radv_get_htile_fast_clear_value`) and Addrlib's HTILE footprint do not depend on ITERATE_256, which `ac_descriptors.c` ties to TC reads of compressed MSAA HTILE. Sampling eligibility is recorded before the attachment's first host clear: every HTILE word must prove the same initial clear of zero or one and, with the stencil in HTILE, SMem 0 (the stencil holds `DB_STENCIL_CLEAR`), or with a depth-only HTILE every stencil plane byte must equal it; and the complete sample-aware depth, stencil and HTILE ranges must be accessible and write-watched. Unsupported initial state or device sampling support retains attachment rendering but sampling throws; eligibility is never retried. Sampling rejects later guest writes, queued external GPU writes, and unproven HTILE clear/fill transitions. A fill of the whole HTILE is proven at the next sample like an HTILE mask clear: complete tracked stores since the fill and every word proving the depth and, with the stencil in HTILE, the stencil clear; a partial fill and an HTILE mask clear of a target with stencil are refused. Guest publication, arbitrary guest depth import, stencil/raw-bit sampling, arrays and storage access remain unimplemented. The block footprint follows main's AMD Addrlib thin-block rule; the accepted HTILE clear words and PS5 equivalence are not measured on console hardware. PPSA99902's historical resident eight-sample D32 reader is documented in [#419](https://github.com/boykopovar/AnyPS5/pull/419#issuecomment-6105597729).
|
||||
- [Native multisampled depth sampling](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) accepts numeric D16 or D32, and D32 with an 8-bit stencil plane whose state is in HTILE or, with a depth-only HTILE, in the plane, two/four/eight samples, one Z_X slice and mip, and pipe-aligned HTILE without VRS, with ITERATE_256 on or off: the initial import reads no compressed Z planes, and Mesa's HTILE clear words (`radv_get_htile_fast_clear_value`) and Addrlib's HTILE footprint do not depend on ITERATE_256, which `ac_descriptors.c` ties to TC reads of compressed MSAA HTILE. Sampling eligibility is recorded before the attachment's first host clear: every HTILE word must prove the same initial clear of zero or one and, with the stencil in HTILE, SMem 0 (the stencil holds `DB_STENCIL_CLEAR`), or with a depth-only HTILE every stencil plane byte must equal it; and the complete sample-aware depth, stencil and HTILE ranges must be accessible and write-watched. Unsupported initial state or device sampling support retains attachment rendering but sampling throws; eligibility is never retried. Sampling rejects later guest writes, queued external GPU writes, and unproven HTILE clear/fill transitions. A fill of the whole HTILE is proven at the next sample like an HTILE mask clear: complete tracked stores since the fill and every word proving the depth and, with the stencil in HTILE, the stencil clear; a partial fill and an HTILE mask clear of a target with stencil are refused. A descriptor without metadata whose XOR and ITERATE_256 match is sampled from the decompressed host image, which assumes the guest expanded the plane first; other metadata is refused. Guest publication, arbitrary guest depth import, stencil/raw-bit sampling, arrays and storage access remain unimplemented. The block footprint follows main's AMD Addrlib thin-block rule; the accepted HTILE clear words and PS5 equivalence are not measured on console hardware. PPSA99902's historical resident eight-sample D32 reader is documented in [#419](https://github.com/boykopovar/AnyPS5/pull/419#issuecomment-6105597729).
|
||||
- [sceAgcDriverSetSubmitValidationMode, sceAgcDriverGetSubmitValidationMode, sceAgcDriverSetSubmitValidationConfig, sceAgcDriverGetSubmitValidationConfig, sceAgcDriverSetValidationErrorOutputFrequency, sceAgcDriverGetShaderDebuggingStatus](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) - the five validation calls return `0x8A6C1000` without reading their arguments or writing caller memory, and `sceAgcDriverGetShaderDebuggingStatus` returns 1, as [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c#L250-L291) reads them from Sony's libSceAgcDriver.sprx: each validation export is `mov eax, 0x8a6c1000; ret` in the copy Dragon Quest VII Reimagined bundles (0x7bb0-0x7bf0), and the debugging status is 1 in the firmware 5.50 library (0x6740). The parameters (a 32-bit mode or frequency, a mode output, a configuration pointer) follow OpenAGC and are never read. Whether later retail firmware enables submit validation or shader debugging is unverified; no title in this repository is known to call them
|
||||
- [sceAgcDriver retail constant results](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) - the debug, capture, GPU printf, register access, GPU reset, suspend point and user data exports taken from the retail `libSceAgcDriver.sprx`, and `sceAgcDriverRegisterOwnerForSystem`, `sceAgcDriverInitResourceRegistrationInterface` and `sceAgcDriverSetResourceRegistrationInfo` in [Registration.cpp](../../../core/libs/prx/libSceAgcDriver/Resource/src/Registration.cpp), are declared without parameters: the console bodies return a constant without reading any argument, so their signatures are unknown. `sceAgcDriverAllocateToolMemoryForGpuReset` and `sceAgcDriverGetAllocatedToolMemoryForGpuReset` read only the output pointer (fourth and second argument, a 12-byte range the console zeroes); the other arguments are declared as `uint64_t`.
|
||||
- [Indices far past every vertex fetch](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp) (libSceAgcDriver) - when a draw's highest index is at least 64Ki vertices past the largest per-vertex record count, every index past that count is moved to it in a copy of the indices, so the zero-padded vertex copies are not sized to the original index (PPSA04159 draws a list of `0xffffffff` with primitive restart off, which asked for 160 GiB). Each attribute fetched by vertex index reads zeros there as at the original index (out-of-bounds select 0 or 1); a draw with another out-of-bounds select keeps its indices. The vertex index the shader sees changes for the moved indices, which a shader that reads it directly would notice
|
||||
|
||||
Reference in new issue
Block a user