texture_cache: Avoid associating color images with stencil (#5118)

* vk_rasterizer: Only redirect stencil reads for stencil-compatible formats

The stencil-to-depth association is keyed on the stencil plane address
alone, so it also lands on unrelated surfaces that reuse that memory.
Following it for a non-stencil format builds a view of the depth-stencil
image in another compatibility class with a Depth|Stencil aspect, and
storage writes through that view corrupt the depth buffer. Only redirect
when the request can actually be a stencil view.

Together with readbacks set to Precise this fixes the missing world
geometry in Uncharted: Drake's Fortune Remastered (CUSA03280).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* texture_cache: Only link stencil images with a stencil format

Don't associate a color image with the depth buffer in the first place,
as suggested in review, instead of skipping the redirect in BindTextures.
FindDepthTarget now only links the placeholder or an image with a stencil
compatible format at the stencil address, and doesn't create a
placeholder over a color image. The BindTextures check is reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* texture_cache: Keep dummy stencil associations at reused addresses

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
artemkaVGandClaude Opus 5.5 authored and GitHub committed 2026-10-01 17:08:11 +03:00
1 parent dd43d1cac9
commit fecfbed092
1 file changed
+11 -6
+11 -6
View File
@@ -12,6 +12,7 @@
#include "core/memory.h"
#include "video_core/buffer_cache/buffer_cache.h"
#include "video_core/page_manager.h"
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_runtime.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
@@ -671,12 +672,16 @@ ImageView& TextureCache::FindDepthTarget(ImageId image_id, const ImageDesc& desc
// If there is a stencil attachment, link depth and stencil.
if (desc.info.stencil_addr != 0) {
ImageId stencil_id{};
ForEachImageInRegion(desc.info.stencil_addr, desc.info.stencil_size,
[&](ImageId image_id, Image& image) {
if (image.info.guest_address == desc.info.stencil_addr) {
stencil_id = image_id;
}
});
ForEachImageInRegion(
desc.info.stencil_addr, desc.info.stencil_size, [&](ImageId image_id, Image& image) {
if (image.info.guest_address != desc.info.stencil_addr) {
return;
}
if (image.info.pixel_format == vk::Format::eUndefined ||
Vulkan::LiverpoolToVK::IsFormatStencilCompatible(image.info.pixel_format)) {
stencil_id = image_id;
}
});
if (!stencil_id) {
ImageInfo info{};
info.guest_address = desc.info.stencil_addr;