diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 163712756..a94b88297 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -346,112 +346,49 @@ std::tuple 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(image_info.size.width) * static_cast(image_info.size.height) * - static_cast(image_info.size.depth) * static_cast(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): {}", + // 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, - // Old image details - cache_image.info.guest_address, cache_image.info.guest_size, - vk::to_string(cache_image.info.pixel_format), - static_cast(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(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, + // Cached image + cache_image.info.guest_size, vk::to_string(cache_image.info.pixel_format), + static_cast(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(cache_image.info.tile_mode), - // New image details - image_info.guest_address, image_info.guest_size, - vk::to_string(image_info.pixel_format), static_cast(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(image_info.tile_mode), - image_info.num_bits, image_info.props.is_block, image_info.guest_size, + // New image + image_info.guest_size, vk::to_string(image_info.pixel_format), + static_cast(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(image_info.tile_mode)); + FreeImage(cache_image_id); + return {merged_image_id, -1, -1}; + } - // 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(image_info.guest_size) / expected_size, - static_cast(image_info.guest_size) / cache_image.info.guest_size, - - // Difference between actual and expected sizes with percentages - static_cast(cache_image.info.guest_size) - static_cast(expected_size), - (static_cast(cache_image.info.guest_size) / expected_size - 1.0) * 100.0, - - static_cast(image_info.guest_size) - static_cast(expected_size), - (static_cast(image_info.guest_size) / expected_size - 1.0) * 100.0, - - merged_image_id.index, static_cast(binding), scheduler.CurrentTick(), - scheduler.CurrentTick() - cache_image.tick_accessed_last); - - UNREACHABLE_MSG("Encountered unresolvable image overlap with equal memory address."); + // 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.