From b32ba9eeefa20e6405be215d39619c9506fa1081 Mon Sep 17 00:00:00 2001 From: Dean Galvin Date: Tue, 13 Oct 2026 16:07:32 +1300 Subject: [PATCH] fix(agc): submit tiled multisample test targets before destroying them The tiled cases of agc_multisample_guest_access destroyed each target while its layout transition and clear were still recorded, so the recorder later submitted commands for destroyed images and lavapipe crashed executing them. Each case now submits and waits first, as the linear case does. The 2x case runs only when the device renders 2x color, like the 8x case. --- .../prx/libSceAgcDriver/tests/Recorder.cpp | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp index 505f0c05d..d3acab0bc 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp @@ -4663,20 +4663,28 @@ void multisampleGuestAccessTests(const Device& device, Recorder& recorder) { { std::lock_guard gpu(GpuMutex()); Require(MultisampleTargetView(context, target) != VK_NULL_HANDLE, "the tiled multisampled target has no view"); + recorder.Submit(); + device.WaitQueue(); + recorder.Sync(); } refused([&] { AgcDriver::GuestMemory::Read(address + targetBytes - texels.size(), texels); }, "a CPU read", "a CPU read inside the tiled multisampled target"); AgcDriver::GuestMemory::Read(address + targetBytes, texels); ClearMultisampleTargets(context.device); - target.extent = {128, 64}; - target.surfaceExtent = target.extent; - target.samples = 2; - { - std::lock_guard gpu(GpuMutex()); - Require(MultisampleTargetView(context, target) != VK_NULL_HANDLE, "the 2x tiled multisampled target has no view"); + if ((base.limits.framebufferColorSampleCounts & VK_SAMPLE_COUNT_2_BIT) != 0) { + target.extent = {128, 64}; + target.surfaceExtent = target.extent; + target.samples = 2; + { + std::lock_guard gpu(GpuMutex()); + Require(MultisampleTargetView(context, target) != VK_NULL_HANDLE, "the 2x tiled multisampled target has no view"); + recorder.Submit(); + device.WaitQueue(); + recorder.Sync(); + } + refused([&] { AgcDriver::GuestMemory::Read(address + 2u * targetBytes - texels.size(), texels); }, "a CPU read", "a CPU read inside the 2x tile-height padding"); + AgcDriver::GuestMemory::Read(address + 2u * targetBytes, texels); + ClearMultisampleTargets(context.device); } - refused([&] { AgcDriver::GuestMemory::Read(address + 2u * targetBytes - texels.size(), texels); }, "a CPU read", "a CPU read inside the 2x tile-height padding"); - AgcDriver::GuestMemory::Read(address + 2u * targetBytes, texels); - ClearMultisampleTargets(context.device); if ((base.limits.framebufferColorSampleCounts & VK_SAMPLE_COUNT_8_BIT) != 0) { target.extent = {64, 32}; target.surfaceExtent = target.extent; @@ -4684,6 +4692,9 @@ void multisampleGuestAccessTests(const Device& device, Recorder& recorder) { { std::lock_guard gpu(GpuMutex()); Require(MultisampleTargetView(context, target) != VK_NULL_HANDLE, "the 8x tiled multisampled target has no view"); + recorder.Submit(); + device.WaitQueue(); + recorder.Sync(); } refused([&] { AgcDriver::GuestMemory::Read(address + 2u * targetBytes - texels.size(), texels); }, "a CPU read", "a CPU read inside the 8x tile-height padding"); AgcDriver::GuestMemory::Read(address + 2u * targetBytes, texels);