mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-31 12:35:51 +00:00
Merge pull request #12207 from XairRrR/fix/agc-depth-cube-array-planes
fix(agc): sample a cube array over depth surfaces through their depth planes
This commit is contained in:
3 files changed
+52
-6
No files matched your search
@@ -2657,7 +2657,7 @@ std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<c
|
||||
const bool layered = cube || (resource.dimension == TextureDimension::k2DArray && resource.depthOrLastArray != 0);
|
||||
const bool sampled = stencil || (!layered && !integer);
|
||||
const auto copyFormat = integer ? VK_FORMAT_R16_UINT : d16 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R32_SFLOAT;
|
||||
const bool planes = (format == copyFormat || depthBits) && resource.width == base.extent.width && resource.height == base.extent.height && resource.baseLevel == 0 && resource.lastLevel == 0 && !(resource.baseArray != 0 && (cube || !layered || resource.baseArray > resource.depthOrLastArray)) && !(cube && resource.depthOrLastArray != 0 && resource.depthOrLastArray != 5) && (resource.dimension == TextureDimension::k2D || resource.dimension == TextureDimension::k2DArray || cube);
|
||||
const bool planes = (format == copyFormat || depthBits) && resource.width == base.extent.width && resource.height == base.extent.height && resource.baseLevel == 0 && resource.lastLevel == 0 && !(resource.baseArray != 0 && (cube || !layered || resource.baseArray > resource.depthOrLastArray)) && !(cube && resource.depthOrLastArray != 0 && (resource.depthOrLastArray + 1u) % 6u != 0u) && (resource.dimension == TextureDimension::k2D || resource.dimension == TextureDimension::k2DArray || cube);
|
||||
if (!(sampled ? found->SampledAccepts(words, resource) : planes) && found->OverwrittenInMemory()) {
|
||||
retireStoringStale(*found);
|
||||
return nullptr;
|
||||
@@ -2665,10 +2665,10 @@ std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<c
|
||||
found->ApplyFastClear();
|
||||
if (sampled) return found->Sampled(words, resource, components, found == drawnDepth);
|
||||
Require(found->hostFormat == base.format, "sampling several slices or an integer view of a depth plane that the device stores in another depth format is not implemented");
|
||||
const auto layers = cube ? 6u : layered ? resource.depthOrLastArray + 1u : 1u;
|
||||
const auto layers = cube ? std::max(resource.depthOrLastArray + 1u, 6u) : layered ? resource.depthOrLastArray + 1u : 1u;
|
||||
if (!planes) {
|
||||
char text[320];
|
||||
std::snprintf(text, sizeof(text), "AGC graphics: sampling the depth planes of depth surface 0x%llx (%ux%u, vk format %d) as a %ux%u texture of guest format %u (vk %d), dimension %d, %u slices, levels %u-%u, base slice %u is not implemented", static_cast<unsigned long long>(base.address), base.extent.width, base.extent.height, static_cast<int>(base.format), resource.width, resource.height, resource.format, static_cast<int>(format), static_cast<int>(resource.dimension), layers, resource.baseLevel, resource.lastLevel, resource.baseArray);
|
||||
char text[400];
|
||||
std::snprintf(text, sizeof(text), "AGC graphics: sampling the depth planes of depth surface 0x%llx (%ux%u, vk format %d) as a %ux%u texture of guest format %u (vk %d), dimension %d, %u slices, levels %u-%u, base slice %u is not implemented (last array %u, depth bits %d, copy format %d)", static_cast<unsigned long long>(base.address), base.extent.width, base.extent.height, static_cast<int>(base.format), resource.width, resource.height, resource.format, static_cast<int>(format), static_cast<int>(resource.dimension), layers, resource.baseLevel, resource.lastLevel, resource.baseArray, resource.depthOrLastArray, depthBits ? 1 : 0, static_cast<int>(copyFormat));
|
||||
throw std::runtime_error(text);
|
||||
}
|
||||
std::vector<DepthPlaneSlice> slices;
|
||||
|
||||
@@ -39,7 +39,7 @@ using namespace AgcDriver::Graphics;
|
||||
constexpr std::uint32_t Side = 256;
|
||||
constexpr std::uint32_t Format32Float = 22;
|
||||
constexpr std::size_t LayerBytes = std::size_t{Side} * Side * 4u;
|
||||
constexpr std::size_t BlockBytes = 2u * LayerBytes;
|
||||
constexpr std::size_t BlockBytes = 4u * LayerBytes;
|
||||
constexpr int Skipped = 77;
|
||||
|
||||
PFN_vkGetDeviceProcAddr realDeviceProc = nullptr;
|
||||
@@ -594,6 +594,51 @@ void RunCubeTiledSlice(const Context& base, const WatchedBlock& block) {
|
||||
ClearDepthSurfaces(context.device);
|
||||
}
|
||||
|
||||
|
||||
void RunCubeArrayGather(const Context& base, const WatchedBlock& block) {
|
||||
TextureDetiler detiler(base);
|
||||
auto context = base;
|
||||
context.detiler = &detiler;
|
||||
constexpr VkExtent2D extent{64, 64};
|
||||
constexpr std::uint32_t faces = 12;
|
||||
GuestTextureResource resource{};
|
||||
resource.width = extent.width;
|
||||
resource.height = extent.height;
|
||||
resource.depthOrLastArray = faces - 1u;
|
||||
resource.mipCount = 1;
|
||||
resource.tileMode = TextureTileMode::kZ64KBX;
|
||||
resource.dimension = TextureDimension::kCube;
|
||||
resource.format = Format32Float;
|
||||
resource.dstSelX = 4;
|
||||
resource.dstSelY = 5;
|
||||
resource.dstSelZ = 6;
|
||||
resource.dstSelW = 7;
|
||||
const auto geometry = DescribeSurface(resource);
|
||||
Require(geometry.guestBytes <= BlockBytes, "the cube array fixture does not fit the guest block");
|
||||
const auto address = block.Address();
|
||||
resource.baseAddress = address;
|
||||
ClearDepthSurfaces(context.device);
|
||||
for (std::uint32_t layer = 0; layer < faces; ++layer) {
|
||||
DepthSurfaceView(context, DepthTarget{address + geometry.GuestLayerOffset(layer), 0, extent, VK_FORMAT_D32_SFLOAT, 1.0f, 0, 0});
|
||||
}
|
||||
imageToBufferCopies = 0;
|
||||
bufferToImageCopies = 0;
|
||||
const auto texture = DepthSurfaceTexture(context, words, resource, components);
|
||||
Require(texture != nullptr, "a cube array of two cubes over twelve depth surfaces was not sampled through their depth planes");
|
||||
if (imageToBufferCopies.load() != faces || bufferToImageCopies.load() != 1) {
|
||||
throw std::runtime_error("sampling a cube array over twelve depth surfaces recorded " + std::to_string(imageToBufferCopies.load()) + " depth surface copies and " + std::to_string(bufferToImageCopies.load()) + " plane copy fills, expected 12 and 1");
|
||||
}
|
||||
resource.depthOrLastArray = 7;
|
||||
bool refused = false;
|
||||
try {
|
||||
static_cast<void>(DepthSurfaceTexture(context, words, resource, components));
|
||||
} catch (const std::runtime_error&) {
|
||||
refused = true;
|
||||
}
|
||||
Require(refused, "a cube whose array slice count is not a multiple of six was sampled through the depth planes");
|
||||
ClearDepthSurfaces(context.device);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
@@ -630,6 +675,7 @@ int main() {
|
||||
SharedLayerRanges(context, block);
|
||||
RunCubeGather(context, block);
|
||||
RunCubeTiledSlice(context, block);
|
||||
RunCubeArrayGather(context, block);
|
||||
SparseGuestLayers(context);
|
||||
}
|
||||
device.reset();
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
- [Stencil planes in guest memory](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver): the stencil plane of a single-sample surface with the 64 KiB Z swizzle is stored and reloaded as a whole plane, not in units. Binding the surface for a draw marks it drawn whether or not the draw writes stencil; a read that overlaps it stores it; a guest write collected when the surface is next bound or its stencil sampled reloads it unless a stencil clear is pending. Its layout is taken to be the depth plane's swizzle at one byte per texel; that is not measured. PPSA05684 moves stencil between depth targets with buffer copies every frame.
|
||||
- [Depth surfaces over compared shared memory](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver): a depth surface over Windows direct memory that is compared once it is shared sees CPU writes made after the sharing no more than one over unwatched memory does. Its generations come from refused collects (0) or `TrackerGeneration()`, and nothing stamps compared memory after the one report at the sharing.
|
||||
- [Unmapped depth planes](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver): a drawn depth plane whose guest memory the title unmapped before it was stored is not stored; its pending depth is dropped with a one-time warning. What the console does with such a store is not known. Readable planes without write permission retain the unsupported-store failure and their pending results.
|
||||
- [Depth plane copies](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver): a depth plane sampled as a 2D array or a cube, or a D16 plane read as `R16_UINT`, is copied into an image of its own (`DepthPlaneCopy`), kept per base address, extent, format and slice count; a slice comes from the live depth surface when one is bound at the slice's address and from guest memory (detiled) otherwise. A draw or dispatch that binds the plane copies again only the slices that changed and records nothing when none did: a surface slice when its image or write serial differs from the one copied (the serial is bumped when the surface is created, when a draw binds it as its depth target, when a pending fast clear is applied and when a written storage view of the plane is copied back), a guest-memory slice when its bytes were written since they were last read (`GuestMemory::UnchangedSince`), a snapshot write overlaps them, or its address, size or tile mode changed. The surface of the latest depth draw is copied at every use until another depth target is bound, since that draw may still be recorded after the copy. A slice's address is the base plus a whole 64 KiB-block depth slice per layer (`DepthSliceBytes`), and the cube face order is the array order; both are inferred from the titles' use, not measured on hardware. A 2D-array T# whose `BASE_ARRAY` is past slice 0 reads slices `BASE_ARRAY` to `LAST_ARRAY` of the copy, which holds slices 0 to `LAST_ARRAY`, and a 2D binding of it reads slice `BASE_ARRAY`; that follows the colour 2D-array semantics and the titles that hit it (PPSA01556, PPSA03912), and was not measured on hardware for depth surfaces. Planes with mips, a cube or a 2D T# with a base slice other than 0, a `BASE_ARRAY` past `LAST_ARRAY`, a cube with other than 1 or 6 slices, and other views of the planes still throw, and so do these copies of a 16-bit plane with stencil that the device stores as D24 or D32 (16-bit depth with stencil, below).
|
||||
- [Depth plane copies](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver): a depth plane sampled as a 2D array, a cube or a cube array, or a D16 plane read as `R16_UINT`, is copied into an image of its own (`DepthPlaneCopy`), kept per base address, extent, format and slice count; a slice comes from the live depth surface when one is bound at the slice's address and from guest memory (detiled) otherwise. A draw or dispatch that binds the plane copies again only the slices that changed and records nothing when none did: a surface slice when its image or write serial differs from the one copied (the serial is bumped when the surface is created, when a draw binds it as its depth target, when a pending fast clear is applied and when a written storage view of the plane is copied back), a guest-memory slice when its bytes were written since they were last read (`GuestMemory::UnchangedSince`), a snapshot write overlaps them, or its address, size or tile mode changed. The surface of the latest depth draw is copied at every use until another depth target is bound, since that draw may still be recorded after the copy. A slice's address is the base plus a whole 64 KiB-block depth slice per layer (`DepthSliceBytes`), and the cube face order is the array order; both are inferred from the titles' use, not measured on hardware. A 2D-array T# whose `BASE_ARRAY` is past slice 0 reads slices `BASE_ARRAY` to `LAST_ARRAY` of the copy, which holds slices 0 to `LAST_ARRAY`, and a 2D binding of it reads slice `BASE_ARRAY`; that follows the colour 2D-array semantics and the titles that hit it (PPSA01556, PPSA03912), and was not measured on hardware for depth surfaces. Planes with mips, a cube or a 2D T# with a base slice other than 0, a `BASE_ARRAY` past `LAST_ARRAY`, a cube whose last array slice is neither 0 nor 6n - 1, and other views of the planes still throw, and so do these copies of a 16-bit plane with stencil that the device stores as D24 or D32 (16-bit depth with stencil, below).
|
||||
- [New depth surface from storage writes](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver) - `TakeStorage` discards the depth aspect (`UNDEFINED` to `TRANSFER_DST_OPTIMAL`) before copying the storage image over the whole surface. On AMD's Windows driver 32.0.31041.1004 (RX 7800 XT) a copy into the depth image after its creation clear left one or two 8x8 blocks testing as the clear value in about 1 of 10 runs, although a copy back read the copied values (#6630); not seen on a Radeon 860M or RX 6700 XT. A surface with a stencil plane keeps the clear before the copy, since its depth aspect is not discarded alone.
|
||||
- [Repacked format-43 copies](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) (libSceAgcDriver): a sampled texture of format 43 (10-bit R, 11-bit G and B unsigned floats from bit 0) is uploaded into a `B10G11R11_UFLOAT` image with its R and B fields swapped (`RepackTextureWord`) and viewed with R and B swapped back. A texture whose results a storage image still holds is copied from it again, whole, whenever the image changed (`RefreshDepthCopy`); a 3D one is flushed to guest memory and uploaded instead. Storage reads and writes of format 43 keep the packed `R32_UINT` path.
|
||||
- [SW_64KB_Z_X color targets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/ColorTargetLayout.cpp) (libSceAgcDriver) use the texture equations and 64 KiB block geometry of `SW_64KB_Z_X`, whose addresses are checked against [AMD addrlib GFX10](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32f68b6ccc4422936d96167c6e0728/src/core/imported/addrlib/src/gfx10/gfx10addrlib.cpp) in the texture tiling tests. Any 256-byte pipe/bank XOR below the block size is accepted, as for `SW_64KB_R_X` targets and Z_X textures; which of those bits the console honours, and the render results, are not measured.
|
||||
|
||||
Reference in new issue
Block a user