mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
textures: handle DCC memory reused as HTile
This commit is contained in:
+14
-10
@@ -328,7 +328,15 @@ void TextureCache::DeleteImage(ImageId id) {
|
|||||||
}
|
}
|
||||||
m_download_images.erase(id);
|
m_download_images.erase(id);
|
||||||
if (image->info.HasMetadata()) {
|
if (image->info.HasMetadata()) {
|
||||||
m_surface_metas.erase(image->info.metadata.range.address);
|
const auto metadata = m_surface_metas.find(image->info.metadata.range.address);
|
||||||
|
if (metadata != m_surface_metas.end() &&
|
||||||
|
((image->info.metadata.kind == ImageMetadataKind::Dcc &&
|
||||||
|
metadata->second.type == MetaDataInfo::Type::Dcc) ||
|
||||||
|
(image->info.metadata.kind == ImageMetadataKind::Htile &&
|
||||||
|
metadata->second.type == MetaDataInfo::Type::HTile))) {
|
||||||
|
// A later binding may have reused this address for another metadata type.
|
||||||
|
m_surface_metas.erase(metadata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UnregisterImage(id);
|
UnregisterImage(id);
|
||||||
if (m_scheduler.Active()) {
|
if (m_scheduler.Active()) {
|
||||||
@@ -1436,15 +1444,11 @@ vk::ImageView TextureCache::FindDepthTarget(ImageId id, const ImageDesc& desc) {
|
|||||||
m_surface_metas.try_emplace(desc.info.metadata.range.address,
|
m_surface_metas.try_emplace(desc.info.metadata.range.address,
|
||||||
MetaDataInfo {.type = MetaDataInfo::Type::HTile,
|
MetaDataInfo {.type = MetaDataInfo::Type::HTile,
|
||||||
.clear_mask = image.info.htile_clear_mask});
|
.clear_mask = image.info.htile_clear_mask});
|
||||||
if (!inserted && metadata->second.type == MetaDataInfo::Type::PendingDcc) {
|
if (!inserted && metadata->second.type != MetaDataInfo::Type::HTile) {
|
||||||
// PendingDcc fills use DCC-specific encoding. Do not reinterpret a speculative
|
// PS5 allocations can reuse DCC storage as HTile while the old color image is cached.
|
||||||
// DCC/buffer fill as HTile state if the address is later classified as depth metadata.
|
// The depth binding defines the new type; incompatible fill state cannot carry over.
|
||||||
metadata->second.type = MetaDataInfo::Type::HTile;
|
metadata->second = {.type = MetaDataInfo::Type::HTile,
|
||||||
metadata->second.clear_mask = image.info.htile_clear_mask;
|
.clear_mask = image.info.htile_clear_mask};
|
||||||
metadata->second.fill_value = 0xffffffffu;
|
|
||||||
metadata->second.fill_size = 0;
|
|
||||||
} else if (!inserted && metadata->second.type != MetaDataInfo::Type::HTile) {
|
|
||||||
EXIT("TextureCache: depth target reuses non-HTile metadata\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommitGpuWrite(image);
|
CommitGpuWrite(image);
|
||||||
|
|||||||
@@ -6025,6 +6025,56 @@ public:
|
|||||||
texture_cache.IsMetaCleared(base + metadata_b, 0),
|
texture_cache.IsMetaCleared(base + metadata_b, 0),
|
||||||
"BufferCache fill did not publish an exact-address metadata clear");
|
"BufferCache fill did not publish an exact-address metadata clear");
|
||||||
|
|
||||||
|
// R-Type Final 3 reuses an old color allocation inside a new stencil plane,
|
||||||
|
// with the same metadata address changing from DCC to HTile.
|
||||||
|
auto reused_depth = MakeMetadataDepth(0x12300, 0x13200);
|
||||||
|
reused_depth.info.pixel_format = vk::Format::eD32SfloatS8Uint;
|
||||||
|
reused_depth.info.stencil = {base + 0x12200, 0x80};
|
||||||
|
reused_depth.info.htile_clear_mask = 0;
|
||||||
|
reused_depth.view_info.format = vk::Format::eD32SfloatS8Uint;
|
||||||
|
reused_depth.view_info.aspect = vk::ImageAspectFlagBits::eDepth |
|
||||||
|
vk::ImageAspectFlagBits::eStencil;
|
||||||
|
auto reused_color = MakeLinearDesc(
|
||||||
|
base + 0x12240, sizeof(uint32_t), vk::Format::eR8G8B8A8Unorm,
|
||||||
|
Prospero::BufferFormat::k8_8_8_8UNorm, Prospero::ImageType::kColor2D,
|
||||||
|
{1, 1, 1}, 1, 4, 1);
|
||||||
|
reused_color.type = BindingType::RenderTarget;
|
||||||
|
reused_color.info.metadata.kind = ImageMetadataKind::Dcc;
|
||||||
|
reused_color.info.metadata.range = {base + 0x13200, 0x20};
|
||||||
|
reused_color.view_info.usage = vk::ImageUsageFlagBits::eColorAttachment;
|
||||||
|
const auto reused_color_id = texture_cache.FindImage(reused_color);
|
||||||
|
(void)texture_cache.FindRenderTarget(reused_color_id, reused_color);
|
||||||
|
texture_cache.TrackDccFill(base + 0x13200, 0x80, 0);
|
||||||
|
texture_cache.InvalidateMemoryFromGPU(reused_depth.info.stencil.address,
|
||||||
|
reused_depth.info.stencil.size);
|
||||||
|
const auto reused_depth_id = texture_cache.FindImage(reused_depth);
|
||||||
|
(void)texture_cache.FindDepthTarget(reused_depth_id, reused_depth);
|
||||||
|
uint32_t reused_fill = 0;
|
||||||
|
Require(
|
||||||
|
name, "DCC allocation reused as HTile",
|
||||||
|
TextureCacheTestAccess::Contains(texture_cache, reused_color_id) &&
|
||||||
|
texture_cache.GetImage(reused_color_id).IsBufferModified() &&
|
||||||
|
!texture_cache.GetImage(reused_color_id).IsGpuModified() &&
|
||||||
|
!texture_cache.IsMetaCleared(base + 0x13200, 0, &reused_fill) &&
|
||||||
|
reused_fill == UINT32_MAX &&
|
||||||
|
texture_cache.ClearMeta(base + 0x13200) &&
|
||||||
|
texture_cache.TouchMeta(base + 0x13200, 0, false),
|
||||||
|
"depth binding retained incompatible DCC clear state");
|
||||||
|
TextureCacheTestAccess::DeleteImage(texture_cache, reused_color_id);
|
||||||
|
(void)texture_cache.FindDepthTarget(reused_depth_id, reused_depth);
|
||||||
|
Require(
|
||||||
|
name, "reused metadata owner retirement",
|
||||||
|
!TextureCacheTestAccess::Contains(texture_cache, reused_color_id) &&
|
||||||
|
texture_cache.IsMeta(base + 0x13200) &&
|
||||||
|
!texture_cache.IsMetaCleared(base + 0x13200, 0) &&
|
||||||
|
texture_cache.IsMetaCleared(base + 0x13200, 1),
|
||||||
|
"retiring the old DCC image erased the live HTile slice state");
|
||||||
|
texture_cache.UnmapMemory(reused_depth.info.data.address,
|
||||||
|
reused_depth.info.data.size);
|
||||||
|
Require(name, "reused metadata final retirement",
|
||||||
|
!texture_cache.IsMeta(base + 0x13200),
|
||||||
|
"retiring the HTile image left its metadata registered");
|
||||||
|
|
||||||
constexpr uint64_t partial_unmap_image_offset = 0x2700000;
|
constexpr uint64_t partial_unmap_image_offset = 0x2700000;
|
||||||
auto partial_unmap_image =
|
auto partial_unmap_image =
|
||||||
MakeLinearDesc(base + partial_unmap_image_offset, 0x2000,
|
MakeLinearDesc(base + partial_unmap_image_offset, 0x2000,
|
||||||
|
|||||||
Reference in New Issue
Block a user