mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
Preserve image contents across unrelated buffer alias writes
This commit is contained in:
+1
-1
@@ -1838,7 +1838,7 @@ void TextureCache::InvalidateMemoryFromGPU(uint64_t address, uint64_t size) {
|
|||||||
std::scoped_lock lock {m_lock};
|
std::scoped_lock lock {m_lock};
|
||||||
for (const auto id: FindImagesInRegion(address, size, true)) {
|
for (const auto id: FindImagesInRegion(address, size, true)) {
|
||||||
auto& image = m_slot_images[id];
|
auto& image = m_slot_images[id];
|
||||||
if (!image.Overlaps(address, size)) {
|
if (image.info.data.address != address) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (image.IsGpuModified()) {
|
if (image.IsGpuModified()) {
|
||||||
|
|||||||
@@ -6248,6 +6248,43 @@ public:
|
|||||||
"to the image");
|
"to the image");
|
||||||
texture_cache.MarkGpuWritten(mirror_refresh);
|
texture_cache.MarkGpuWritten(mirror_refresh);
|
||||||
|
|
||||||
|
// A write through a separate buffer must not replace untouched image
|
||||||
|
// texels with stale backing bytes. Exact-base writes still refresh it.
|
||||||
|
constexpr uint64_t buffer_alias_offset = 0x1a00000;
|
||||||
|
constexpr uint32_t buffer_alias_image_value = 0x13579bdfu;
|
||||||
|
constexpr uint32_t buffer_alias_write_value = 0x2468ace0u;
|
||||||
|
std::memset(memory + buffer_alias_offset, 0, 4 * sizeof(uint32_t));
|
||||||
|
auto buffer_alias_desc = MakeLinearDesc(
|
||||||
|
base + buffer_alias_offset, 4 * sizeof(uint32_t), vk::Format::eR32Uint,
|
||||||
|
Prospero::BufferFormat::k32UInt, Prospero::ImageType::kColor2D,
|
||||||
|
{4, 1, 1}, 1, 4, 1);
|
||||||
|
const auto buffer_alias_image = texture_cache.FindImage(buffer_alias_desc);
|
||||||
|
for (const uint32_t write_offset : {0u, 12u}) {
|
||||||
|
vk::ClearValue painted{};
|
||||||
|
painted.color.uint32 = std::array{buffer_alias_image_value, 0u, 0u, 0u};
|
||||||
|
TextureCacheTestAccess::ClearImage(
|
||||||
|
texture_cache, scheduler.Current(), buffer_alias_image,
|
||||||
|
{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}, painted);
|
||||||
|
const auto write_address = buffer_alias_desc.info.data.address + write_offset;
|
||||||
|
auto writable = resources.GetBufferCache().ObtainBuffer(
|
||||||
|
write_address, sizeof(uint32_t), true, false);
|
||||||
|
Require(name, "image alias buffer allocation", writable.first != nullptr,
|
||||||
|
"failed to allocate the image alias write buffer");
|
||||||
|
writable.first->Fill(writable.second, sizeof(uint32_t), buffer_alias_write_value);
|
||||||
|
texture_cache.InvalidateMemoryFromGPU(write_address, sizeof(uint32_t));
|
||||||
|
(void)texture_cache.FindTexture(buffer_alias_image, buffer_alias_desc);
|
||||||
|
const bool exact_base = write_offset == 0;
|
||||||
|
const uint32_t read_texels = exact_base ? 1 : 3;
|
||||||
|
Require(name, exact_base ? "exact-base buffer write refresh"
|
||||||
|
: "overlapping buffer preserves untouched texels",
|
||||||
|
ReadCachedTexel(name, context, buffer_alias_image, {},
|
||||||
|
{read_texels, 1, 1}) ==
|
||||||
|
std::vector<u32>(read_texels, exact_base ? buffer_alias_write_value
|
||||||
|
: buffer_alias_image_value),
|
||||||
|
exact_base ? "exact-base buffer write did not refresh the native image"
|
||||||
|
: "overlapping buffer write replaced untouched GPU image texels");
|
||||||
|
}
|
||||||
|
|
||||||
constexpr uint64_t exact_buffer_offset = 0x90000;
|
constexpr uint64_t exact_buffer_offset = 0x90000;
|
||||||
constexpr uint32_t exact_buffer_value = 0x3f234567u;
|
constexpr uint32_t exact_buffer_value = 0x3f234567u;
|
||||||
std::memcpy(memory + exact_buffer_offset, &exact_buffer_value,
|
std::memcpy(memory + exact_buffer_offset, &exact_buffer_value,
|
||||||
@@ -6851,20 +6888,17 @@ public:
|
|||||||
"a same-value CPU metadata write lost its clear after rendering");
|
"a same-value CPU metadata write lost its clear after rendering");
|
||||||
}
|
}
|
||||||
WriteMetadata(context, base + 0x28000, 0x1000, 0);
|
WriteMetadata(context, base + 0x28000, 0x1000, 0);
|
||||||
texture_cache.InvalidateMemoryFromGPU(reused_depth.info.stencil.address,
|
|
||||||
reused_depth.info.stencil.size);
|
|
||||||
const auto reused_depth_id = texture_cache.FindImage(reused_depth);
|
const auto reused_depth_id = texture_cache.FindImage(reused_depth);
|
||||||
(void)texture_cache.FindDepthTarget(reused_depth_id, reused_depth);
|
(void)texture_cache.FindDepthTarget(reused_depth_id, reused_depth);
|
||||||
Require(
|
Require(
|
||||||
name, "DCC allocation reused as HTile",
|
name, "DCC allocation reused as HTile",
|
||||||
TextureCacheTestAccess::Contains(texture_cache, reused_color_id) &&
|
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 + 0x28000, 0) &&
|
!texture_cache.IsMetaCleared(base + 0x28000, 0) &&
|
||||||
texture_cache.ClearMeta(base + 0x28000) &&
|
texture_cache.ClearMeta(base + 0x28000) &&
|
||||||
texture_cache.TouchMeta(base + 0x28000, 0, false),
|
texture_cache.TouchMeta(base + 0x28000, 0, false),
|
||||||
"depth binding retained incompatible DCC clear state");
|
"depth binding retained incompatible DCC clear state");
|
||||||
TextureCacheTestAccess::DeleteImage(texture_cache, reused_color_id);
|
texture_cache.UnmapMemory(reused_color.info.data.address,
|
||||||
|
reused_color.info.data.size);
|
||||||
(void)texture_cache.FindDepthTarget(reused_depth_id, reused_depth);
|
(void)texture_cache.FindDepthTarget(reused_depth_id, reused_depth);
|
||||||
Require(
|
Require(
|
||||||
name, "reused metadata owner retirement",
|
name, "reused metadata owner retirement",
|
||||||
|
|||||||
Reference in New Issue
Block a user