fix(texture_cache): handle GPU-modified ignored textures

Fix UNIMPLEMENTED assertion when handling GPU-modified ignored textures
in texture cache. When ignored textures (remapped or same address/size)
have GpuModified flag set, now properly copies data to new image if
formats match, or marks new image as modified otherwise.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-12-13 10:43:22 +10:00
parent 7db12d7e80
commit 10daa1e625
2 changed files with 25 additions and 2 deletions

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <span> #include <span>
@@ -302,7 +303,8 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
ctx.AddExtension("SPV_NV_geometry_shader_passthrough"); ctx.AddExtension("SPV_NV_geometry_shader_passthrough");
ctx.AddCapability(spv::Capability::GeometryShaderPassthroughNV); ctx.AddCapability(spv::Capability::GeometryShaderPassthroughNV);
} else { } else {
LOG_WARNING(Shader_SPIRV, "Geometry shader passthrough used with no support"); // Geometry shader passthrough not supported, will use regular geometry shader
LOG_DEBUG(Shader_SPIRV, "Geometry shader passthrough used with no support");
} }
} }
break; break;

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project // SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#pragma once #pragma once
@@ -1493,7 +1494,27 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA
for (const ImageId overlap_id : join_ignore_textures) { for (const ImageId overlap_id : join_ignore_textures) {
Image& overlap = slot_images[overlap_id]; Image& overlap = slot_images[overlap_id];
if (True(overlap.flags & ImageFlagBits::GpuModified)) { if (True(overlap.flags & ImageFlagBits::GpuModified)) {
UNIMPLEMENTED(); // For ignored textures that are GPU modified, try to preserve the data
// by copying it to the new image if possible, otherwise mark as modified
const auto base_opt = new_image.TryFindBase(overlap.gpu_addr);
if (base_opt.has_value() && overlap.info.format == new_info.format &&
overlap.info.num_samples == new_info.num_samples) {
// Formats match, copy the data
new_image.flags |= ImageFlagBits::GpuModified;
const auto& resolution = Settings::values.resolution_info;
const u32 up_scale = can_rescale ? resolution.up_scale : 1;
const u32 down_shift = can_rescale ? resolution.down_shift : 0;
auto copies = MakeShrinkImageCopies(new_info, overlap.info, base_opt.value(),
up_scale, down_shift);
runtime.CopyImage(new_image, overlap, std::move(copies));
new_image.modification_tick =
std::max(new_image.modification_tick, overlap.modification_tick);
} else {
// Formats don't match or can't find base, just mark as modified
new_image.flags |= ImageFlagBits::GpuModified;
new_image.modification_tick =
std::max(new_image.modification_tick, overlap.modification_tick);
}
} }
if (True(overlap.flags & ImageFlagBits::Tracked)) { if (True(overlap.flags & ImageFlagBits::Tracked)) {
UntrackImage(overlap, overlap_id); UntrackImage(overlap, overlap_id);