mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 10:43:33 +00:00
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:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user