Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 43 additions & 106 deletions src/video_core/texture_cache/texture_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,112 +346,49 @@ std::tuple<ImageId, int, int> TextureCache::ResolveOverlap(const ImageInfo& imag
return {merged_image_id, -1, -1};
}

// Enhanced debug logging for unreachable case
// Calculate expected size based on format and dimensions
u64 expected_size =
(static_cast<u64>(image_info.size.width) * static_cast<u64>(image_info.size.height) *
static_cast<u64>(image_info.size.depth) * static_cast<u64>(image_info.num_bits) / 8);
LOG_ERROR(Render_Vulkan,
"Unresolvable image overlap with equal memory address:\n"
"=== OLD IMAGE (cached) ===\n"
" Address: {:#x}\n"
" Size: {:#x} bytes\n"
" Format: {}\n"
" Type: {}\n"
" Width: {}\n"
" Height: {}\n"
" Depth: {}\n"
" Pitch: {}\n"
" Mip levels: {}\n"
" Array layers: {}\n"
" Samples: {}\n"
" Tile mode: {:#x}\n"
" Block size: {} bits\n"
" Is block-comp: {}\n"
" Guest size: {:#x}\n"
" Last accessed: tick {}\n"
" Safe to delete: {}\n"
"\n"
"=== NEW IMAGE (requested) ===\n"
" Address: {:#x}\n"
" Size: {:#x} bytes\n"
" Format: {}\n"
" Type: {}\n"
" Width: {}\n"
" Height: {}\n"
" Depth: {}\n"
" Pitch: {}\n"
" Mip levels: {}\n"
" Array layers: {}\n"
" Samples: {}\n"
" Tile mode: {:#x}\n"
" Block size: {} bits\n"
" Is block-comp: {}\n"
" Guest size: {:#x}\n"
"\n"
"=== COMPARISON ===\n"
" Same format: {}\n"
" Same type: {}\n"
" Same tile mode: {}\n"
" Same block size: {}\n"
" Same BlockDim: {}\n"
" Same pitch: {}\n"
" Old resources <= new: {} (old: {}, new: {})\n"
" Old size <= new size: {}\n"
" Expected size (calc): {} bytes\n"
" Size ratio (new/expected): {:.2f}x\n"
" Size ratio (new/old): {:.2f}x\n"
" Old vs expected diff: {} bytes ({:+.2f}%)\n"
" New vs expected diff: {} bytes ({:+.2f}%)\n"
" Merged image ID: {}\n"
" Binding type: {}\n"
" Current tick: {}\n"
" Age (ticks since last access): {}",

// Old image details
cache_image.info.guest_address, cache_image.info.guest_size,
vk::to_string(cache_image.info.pixel_format),
static_cast<int>(cache_image.info.type), cache_image.info.size.width,
cache_image.info.size.height, cache_image.info.size.depth, cache_image.info.pitch,
cache_image.info.resources.levels, cache_image.info.resources.layers,
cache_image.info.num_samples, static_cast<u32>(cache_image.info.tile_mode),
cache_image.info.num_bits, cache_image.info.props.is_block,
cache_image.info.guest_size, cache_image.tick_accessed_last, safe_to_delete,

// New image details
image_info.guest_address, image_info.guest_size,
vk::to_string(image_info.pixel_format), static_cast<int>(image_info.type),
image_info.size.width, image_info.size.height, image_info.size.depth,
image_info.pitch, image_info.resources.levels, image_info.resources.layers,
image_info.num_samples, static_cast<u32>(image_info.tile_mode),
image_info.num_bits, image_info.props.is_block, image_info.guest_size,

// Comparison
(image_info.pixel_format == cache_image.info.pixel_format),
(image_info.type == cache_image.info.type),
(image_info.tile_mode == cache_image.info.tile_mode),
(image_info.num_bits == cache_image.info.num_bits),
(image_info.BlockDim() == cache_image.info.BlockDim()),
(image_info.pitch == cache_image.info.pitch),
(cache_image.info.resources <= image_info.resources),
cache_image.info.resources.levels, image_info.resources.levels,
(cache_image.info.guest_size <= image_info.guest_size), expected_size,

// Size ratios
static_cast<double>(image_info.guest_size) / expected_size,
static_cast<double>(image_info.guest_size) / cache_image.info.guest_size,

// Difference between actual and expected sizes with percentages
static_cast<s64>(cache_image.info.guest_size) - static_cast<s64>(expected_size),
(static_cast<double>(cache_image.info.guest_size) / expected_size - 1.0) * 100.0,

static_cast<s64>(image_info.guest_size) - static_cast<s64>(expected_size),
(static_cast<double>(image_info.guest_size) / expected_size - 1.0) * 100.0,

merged_image_id.index, static_cast<int>(binding), scheduler.CurrentTick(),
scheduler.CurrentTick() - cache_image.tick_accessed_last);

UNREACHABLE_MSG("Encountered unresolvable image overlap with equal memory address.");
// Size is greater with same format and tile mode, but mip levels are not greater.
// This can occur when the guest reuses an address with a different array layer count
// or memory layout, causing a different memory footprint despite identical dimensions.
// The cached image is superseded and must be replaced.
if (image_info.guest_size > cache_image.info.guest_size) {
LOG_DEBUG(Render_Vulkan,
"Image overlap at {:#x}: replacing cached image "
"(size={:#x}, fmt={}, type={}, {}x{}x{}, {} layers, {} mips, tile={:#x}) "
"with new image "
"(size={:#x}, fmt={}, type={}, {}x{}x{}, {} layers, {} mips, tile={:#x})",
image_info.guest_address,

// Cached image
cache_image.info.guest_size, vk::to_string(cache_image.info.pixel_format),
static_cast<int>(cache_image.info.type), cache_image.info.size.width,
cache_image.info.size.height, cache_image.info.size.depth,
cache_image.info.resources.layers, cache_image.info.resources.levels,
static_cast<u32>(cache_image.info.tile_mode),

// New image
image_info.guest_size, vk::to_string(image_info.pixel_format),
static_cast<int>(image_info.type), image_info.size.width,
image_info.size.height, image_info.size.depth, image_info.resources.layers,
image_info.resources.levels, static_cast<u32>(image_info.tile_mode));
FreeImage(cache_image_id);
return {merged_image_id, -1, -1};
}

// The cached image is larger or equal with same format and tile mode.
// Treat it as a compatible view source.
LOG_DEBUG(Render_Vulkan,
"Image overlap at {:#x}: using cached image as view source "
"(cached size={:#x}, {} layers vs requested size={:#x}, {} layers)",
image_info.guest_address, cache_image.info.guest_size,
cache_image.info.resources.layers, image_info.guest_size,
image_info.resources.layers);
{
auto result_id = merged_image_id ? merged_image_id : cache_image_id;
const auto& result_image = slot_images[result_id];
const bool is_compatible =
IsVulkanFormatCompatible(result_image.info.pixel_format, image_info.pixel_format);
return {is_compatible ? result_id : ImageId{}, -1, -1};
}
}

// Right overlap, the image requested is a possible subresource of the image from cache.
Expand Down
Loading