diff --git a/src/graphics/host_gpu/renderer/cache/textureCache.cpp b/src/graphics/host_gpu/renderer/cache/textureCache.cpp index 00e1e8fa7..8d086ef42 100644 --- a/src/graphics/host_gpu/renderer/cache/textureCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/textureCache.cpp @@ -88,15 +88,34 @@ TextureCache::~TextureCache() { bool TextureCache::SameBacking(const ImageInfo& cached, const ImageInfo& requested, bool exact_format) { - const bool unit_extent = - requested.extent.width == 1 && requested.extent.height == 1 && requested.extent.depth == 1; - return cached.data == requested.data && cached.extent == requested.extent && - cached.samples == requested.samples && - cached.bytes_per_block == requested.bytes_per_block && - (cached.type == requested.type || unit_extent) && - (exact_format - ? cached.pixel_format == requested.pixel_format - : ImageViewOps::FormatsCompatible(cached.pixel_format, requested.pixel_format)); + if (cached.data.address != requested.data.address) { + return false; + } + if (cached.data.size != requested.data.size) { + return false; + } + if (cached.extent != requested.extent) { + return false; + } + if (cached.samples != requested.samples) { + return false; + } + if (cached.bytes_per_block != requested.bytes_per_block) { + return false; + } + if (cached.tile_mode != requested.tile_mode) { + return false; + } + if (!ImageViewOps::FormatsCompatible(cached.pixel_format, requested.pixel_format)) { + return false; + } + if (cached.type != requested.type && requested.extent != vk::Extent3D {1, 1, 1}) { + return false; + } + if (exact_format && cached.pixel_format != requested.pixel_format) { + return false; + } + return true; } TextureCache::BindingType TextureCache::UploadBinding(const Image& image) { @@ -735,6 +754,12 @@ TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& reques (requested.IsVolume() || cached.info.IsVolume())) { return {ExpandImage(requested, cached_id)}; } + if (requested.tile_mode != cached.info.tile_mode) { + if (safe_to_delete) { + DeleteImages(std::array {cached_id}, cached_id); + } + return {merged_id}; + } if (requested.pixel_format != cached.info.pixel_format || requested.data.size <= cached.info.data.size) { const auto result_id = merged_id ? merged_id : cached_id; @@ -747,12 +772,6 @@ TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& reques if (requested.type == cached.info.type && requested.resources > cached.info.resources) { return {ExpandImage(requested, cached_id)}; } - if (requested.tile_mode != cached.info.tile_mode) { - if (safe_to_delete) { - DeleteImages(std::array {cached_id}, cached_id); - } - return {merged_id}; - } EXIT("TextureCache: unresolvable equal-address image overlap, address=0x%016" PRIx64 " requested=%ux%u " "cached=%ux%u requested_size=0x%016" PRIx64 " cached_size=0x%016" PRIx64 @@ -1122,7 +1141,7 @@ ImageId TextureCache::FindImage(ImageDesc& desc, bool exact_format) { for (const auto id: candidates) { const auto owner = ResolveOwner(id); - if (owner == nullptr || owner->info.data != desc.info.data) { + if (owner == nullptr) { continue; } if (SameBacking(owner->info, desc.info, exact_format)) { diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 1e22110b0..ceab29ea5 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -4772,6 +4772,52 @@ public: "successive near-capacity image transfers replaced the shared " "download buffer"); + constexpr uint64_t tile_alias_offset = 0x2000000; + constexpr uint64_t tile_alias_size = 0x400000; + constexpr uint32_t tile_alias_extent = 1024; + std::memset(memory + tile_alias_offset, 0, + static_cast(tile_alias_size)); + auto render_target_alias = MakeLinearDesc( + base + tile_alias_offset, tile_alias_size, + vk::Format::eR8G8B8A8Unorm, + Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UNorm), + Prospero::ImageType::kColor2D, + {tile_alias_extent, tile_alias_extent, 1}, 1, 4, 1); + render_target_alias.type = BindingType::Storage; + render_target_alias.info.tile_mode = + Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget); + render_target_alias.view_info.usage = + vk::ImageUsageFlagBits::eStorage; + const auto render_target_alias_image = + texture_cache.FindImage(render_target_alias); + + auto standard_4kb_alias = render_target_alias; + standard_4kb_alias.type = BindingType::Texture; + standard_4kb_alias.info.tile_mode = + Prospero::GpuEnumValue(Prospero::TileMode::kStandard4KB); + standard_4kb_alias.view_info.usage = + vk::ImageUsageFlagBits::eSampled; + const auto standard_4kb_alias_image = + texture_cache.FindImage(standard_4kb_alias); + auto repeated_standard_4kb_alias = standard_4kb_alias; + const auto repeated_standard_4kb_alias_image = + texture_cache.FindImage(repeated_standard_4kb_alias); + Require( + name, "equal-size tile-mode alias", + render_target_alias_image && standard_4kb_alias_image && + standard_4kb_alias_image != render_target_alias_image && + repeated_standard_4kb_alias_image == + standard_4kb_alias_image && + texture_cache.GetImage(render_target_alias_image) + .info.tile_mode == + Prospero::GpuEnumValue( + Prospero::TileMode::kRenderTarget) && + texture_cache.GetImage(standard_4kb_alias_image) + .info.tile_mode == + Prospero::GpuEnumValue( + Prospero::TileMode::kStandard4KB), + "equal address/size lookup reused an incompatible tiled backing"); + for (auto &output : ms_observer_outputs) { DestroyBuffer(&output); }