Graphics: preserve rendered contents across 1D and 2D texture aliases

This commit is contained in:
nmzik
2026-09-27 12:55:10 +04:00
parent 7b6bfdec64
commit f53f0ca483
2 changed files with 59 additions and 9 deletions
+15 -9
View File
@@ -193,7 +193,7 @@ bool TextureCache::SameBacking(const ImageInfo& cached, const ImageInfo& request
return false;
}
if (!ImageViewOps::FormatsCompatible(cached.pixel_format, requested.pixel_format) ||
(cached.type != requested.type && requested.extent != vk::Extent3D {1, 1, 1})) {
cached.type != requested.type) {
return false;
}
if (exact_format && cached.pixel_format != requested.pixel_format) {
@@ -639,9 +639,12 @@ void TextureCache::CopyImage(ImageId destination_id, ImageId source_id) {
const bool source_depth = source.info.IsDepth();
const bool dest_depth = destination.info.IsDepth();
const bool direct_copy =
source.backing.format == destination.backing.format ||
(!source_depth && !dest_depth &&
vk::blockSize(source.backing.format) == vk::blockSize(destination.backing.format));
(source.backing.image_type == destination.backing.image_type ||
(source.backing.image_type != vk::ImageType::e1D &&
destination.backing.image_type != vk::ImageType::e1D)) &&
(source.backing.format == destination.backing.format ||
(!source_depth && !dest_depth &&
vk::blockSize(source.backing.format) == vk::blockSize(destination.backing.format)));
if (direct_copy) {
destination.CopyImage(source);
} else if (!CopyD16(destination, source)) {
@@ -810,12 +813,15 @@ TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& reques
return {merged_id};
}
// PPSA08394
// A view cannot change the native image type or grow its extent.
if (requested.data.size == cached.info.data.size &&
requested.resources == cached.info.resources && requested.type == cached.info.type &&
requested.extent.width > cached.info.extent.width &&
requested.extent.height >= cached.info.extent.height &&
requested.extent.depth >= cached.info.extent.depth &&
ImageViewOps::FormatsCompatible(cached.info.pixel_format, requested.pixel_format)) {
requested.resources == cached.info.resources &&
ImageViewOps::FormatsCompatible(cached.info.pixel_format, requested.pixel_format) &&
(requested.type != cached.info.type
? requested.extent == cached.info.extent
: requested.extent.width > cached.info.extent.width &&
requested.extent.height >= cached.info.extent.height &&
requested.extent.depth >= cached.info.extent.depth)) {
return {ExpandImage(requested, cached_id)};
}
// PS5 mip tails can expose more levels without increasing the guest allocation.
+44
View File
@@ -8478,6 +8478,50 @@ public:
{1, 1, 1}, 0, mip) == expected,
"the sampled target lost its GPU-written final texel");
}
if (width == 1 && height == 1) {
for (const bool uint_view : {true, false}) {
descriptor.fields[1] = static_cast<uint32_t>(
uint_view ? Prospero::BufferFormat::k16_16_16_16UInt
: Prospero::BufferFormat::k16_16_16_16Float) << 20u;
descriptor.fields[3] = 0x81b00facu; // Captured 1D view, tile27, RGBA swizzle.
std::copy_n(descriptor.fields, 8, value.dwords.begin());
resource.numeric_class = uint_view ? Prospero::TextureNumericClass::Uint
: Prospero::TextureNumericClass::Float;
resource.dimension = ShaderRecompiler::Decoder::ImageDimension::Dim1D;
const auto one_d =
RenderExecutorTestAccess::ResolveTexture(executor, resource, value);
const auto one_d_view = texture_cache.FindTexture(one_d.image_id, one_d.desc);
const auto repeated =
RenderExecutorTestAccess::ResolveTexture(executor, resource, value);
Require(name, "1D sampled backing and reuse",
one_d.image_id != color.image_id && one_d_view != nullptr &&
one_d.desc.view_info.type == vk::ImageViewType::e1D &&
texture_cache.GetImage(one_d.image_id).backing.image_type ==
vk::ImageType::e1D &&
repeated.image_id == one_d.image_id &&
texture_cache.FindTexture(repeated.image_id, repeated.desc) == one_d_view &&
ReadCachedTexel(name, context, one_d.image_id) == expected,
"the 1D alias reused an incompatible backing or lost the rendered texel");
RenderExecutorTestAccess::ResetBindings(executor);
RenderExecutorTestAccess::ResolveRenderColorTarget(
executor, scheduler.Current(), color, 0);
const auto restored = RenderExecutorTestAccess::AcquireRenderTargets(
executor, scheduler.Current(), &color, 1, no_depth);
scheduler.Current().BeginRendering(restored);
scheduler.Current().EndRendering();
Require(name, "2D target restoration",
color.image_id != one_d.image_id &&
restored.color_attachments[0].image_view != nullptr &&
texture_cache.GetImage(color.image_id).backing.image_type ==
vk::ImageType::e2D &&
texture_cache.GetImage(color.image_id).info.pixel_format ==
vk::Format::eR16G16B16A16Sfloat &&
ReadCachedTexel(name, context, color.image_id) == expected,
"restoring the 2D target lost its view type or GPU-written texel");
RenderExecutorTestAccess::ResetBindings(executor);
}
}
}
RenderExecutorTestAccess::ResetBindings(executor);