[texture_cache] Enforce conservative 3D texture aliasing. Consistently merge/lookup images.

Previously, the merging strategy is permissive but the lookup strategy is strict. Together they create a infinite merge loop because lookup always fails and merges are always executed.
The last attempt to fix this issue made the lookup strategy more permissive which created unexpected aliased textures.
This commit implements an alternative: make the merging strategy strict.
This commit is contained in:
weakboson 2025-08-04 01:50:06 +08:00
parent 6f9216c20d
commit fa102f7e83
2 changed files with 17 additions and 9 deletions

View file

@ -1426,7 +1426,6 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA
if (solution) { if (solution) {
gpu_addr = solution->gpu_addr; gpu_addr = solution->gpu_addr;
cpu_addr = solution->cpu_addr; cpu_addr = solution->cpu_addr;
// TODO: properly update new_info.size.depth.
new_info.resources = solution->resources; new_info.resources = solution->resources;
join_overlap_ids.push_back(overlap_id); join_overlap_ids.push_back(overlap_id);
join_copies_to_do.emplace_back(JoinCopy{false, overlap_id}); join_copies_to_do.emplace_back(JoinCopy{false, overlap_id});

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-FileCopyrightText: Ryujinx Team and Contributors // SPDX-FileCopyrightText: Ryujinx Team and Contributors
// SPDX-License-Identifier: GPL-2.0-or-later AND MIT // SPDX-License-Identifier: GPL-2.0-or-later AND MIT
@ -343,7 +346,7 @@ template <u32 GOB_EXTENT>
if (!IsBlockLinearSizeCompatible(new_info, info, base.level, 0, strict_size)) { if (!IsBlockLinearSizeCompatible(new_info, info, base.level, 0, strict_size)) {
return std::nullopt; return std::nullopt;
} }
const u32 mip_depth = std::max(1U, new_info.size.depth << base.level); const u32 mip_depth = AdjustMipSize(new_info.size.depth, base.level);
if (mip_depth < info.size.depth + base.layer) { if (mip_depth < info.size.depth + base.layer) {
return std::nullopt; return std::nullopt;
} }
@ -428,8 +431,14 @@ template <u32 GOB_EXTENT>
return std::nullopt; return std::nullopt;
} }
const SubresourceExtent resources = new_info.resources; const SubresourceExtent resources = new_info.resources;
s32 layers = 1; s32 layers;
if (info.type != ImageType::e3D) { if (info.type == ImageType::e3D) {
const u32 mip_depth = AdjustMipSize(info.size.depth, base->level);
if (mip_depth < new_info.size.depth + base->layer) {
return std::nullopt;
}
layers = 1;
} else {
layers = std::max(resources.layers, info.resources.layers + base->layer); layers = std::max(resources.layers, info.resources.layers + base->layer);
} }
return OverlapResult{ return OverlapResult{
@ -1216,10 +1225,10 @@ std::optional<SubresourceBase> FindSubresource(const ImageInfo& candidate, const
return std::nullopt; return std::nullopt;
} }
if (existing.type == ImageType::e3D) { if (existing.type == ImageType::e3D) {
// const u32 mip_depth = std::max(1U, existing.size.depth << base->level); const u32 mip_depth = AdjustMipSize(existing.size.depth, base->level);
// if (mip_depth < candidate.size.depth + base->layer) { if (mip_depth < candidate.size.depth + base->layer) {
// return std::nullopt; return std::nullopt;
// } }
} else if (existing.resources.layers < candidate.resources.layers + base->layer) { } else if (existing.resources.layers < candidate.resources.layers + base->layer) {
return std::nullopt; return std::nullopt;
} }
@ -1247,7 +1256,7 @@ bool IsSubCopy(const ImageInfo& candidate, const ImageBase& image, GPUVAddr cand
return false; return false;
} }
if (existing.type == ImageType::e3D) { if (existing.type == ImageType::e3D) {
const u32 mip_depth = std::max(1U, existing.size.depth << base->level); const u32 mip_depth = AdjustMipSize(existing.size.depth, base->level);
if (mip_depth < candidate.size.depth + base->layer) { if (mip_depth < candidate.size.depth + base->layer) {
return false; return false;
} }