texture_cache: fix exact-match reuse across different tile modes

This commit is contained in:
nmzik
2026-07-30 00:10:40 +02:00
parent c508c4a9c0
commit 3965d41d36
2 changed files with 81 additions and 16 deletions
+35 -16
View File
@@ -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)) {
+46
View File
@@ -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<size_t>(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);
}