diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index 4b1fc3d98..168bcd3b9 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -1280,8 +1280,10 @@ if(BUILD_TESTING) add_test(NAME agc_driver_pm4_failure COMMAND agc_driver_pm4_tests failure) set_tests_properties(agc_driver_pm4_failure PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77) add_test(NAME agc_descriptor_pool_reset_failure COMMAND agc_driver_graphics_tests --descriptor-pool-reset-failure) + add_test(NAME agc_driver_address_space_teardown COMMAND agc_driver_graphics_tests --address-space-teardown) + set_tests_properties(agc_driver_address_space_teardown PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") if(WIN32) - set_tests_properties(agc_driver_pm4_failure agc_descriptor_pool_reset_failure PROPERTIES ENVIRONMENT_MODIFICATION + set_tests_properties(agc_driver_pm4_failure agc_descriptor_pool_reset_failure agc_driver_address_space_teardown PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() if(NOT WIN32) diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp index ec5d3a4f5..878fa0698 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp @@ -1784,6 +1784,10 @@ MirrorStats MirrorCounters() { } void ClearImageMirrors(VkDevice device) { + auto space = Spaces().current.load(); + if (space != nullptr && space->device == device) { + Spaces().current.compare_exchange_strong(space, std::shared_ptr{}); + } auto& state = Mirrors(); std::map> entries; { @@ -1794,7 +1798,6 @@ void ClearImageMirrors(VkDevice device) { state.heapBytes = 0; state.device = VK_NULL_HANDLE; } - Spaces().current.store(nullptr); } void ClearHostImports(VkDevice device) { diff --git a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp index 7bfbc5a0d..4e219ae0a 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp @@ -7,6 +7,7 @@ #include "prx/libSceAgcDriver/Graphics/include/VertexInput.hpp" #include "prx/libSceAgcDriver/Graphics/include/Draw.hpp" #include "prx/libSceAgcDriver/Graphics/include/BufferPool.hpp" +#include "prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp" #include "prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp" #include "prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp" #include "prx/libSceAgcDriver/Graphics/include/ShaderInputState.hpp" @@ -22,6 +23,7 @@ #include "BdaAbi.hpp" #include "prx/libc/include/GuestAllocations.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include "prx/libc/include/GuestHeap.hpp" #include #include #include @@ -2725,6 +2727,32 @@ AgcDriver::Graphics::Context mockContext() { return context; } +void addressSpaceTeardownTests() { +#ifdef _WIN32 + _putenv_s("APS5_NO_LEASE_MIRROR", "1"); +#else + setenv("APS5_NO_LEASE_MIRROR", "1", 1); +#endif + auto context = mockContext(); + context.device = makeHandle(); + context.bufferDeviceAddress = true; + context.limits.maxStorageBufferRange = 1u << 27; + void* block = GuestHeap::GuestHeapAlignForGpu_nid_postfix(16, 64); + const auto before = AgcDriver::Graphics::LeaseCounters().cacheDrops; + { + AgcDriver::Graphics::GuestBufferMemory memory(context); + memory.AcquireRegistered(); + Require(memory.HoldsLease(), "address-based build holds no lease before device teardown"); + memory.Upload(true); + memory.WriteBack(); + Require(!memory.HoldsLease(), "completed address-based build kept its own lease"); + } + AgcDriver::Graphics::ClearImageMirrors(context.device); + GuestHeap::GuestHeapFree_nid_postfix(block); + Require(AgcDriver::Graphics::LeaseCounters().cacheDrops == before, "device teardown left the cached address space pinning guest allocations"); + Require(mock.live == 0, "address-space teardown test leaked Vulkan objects"); +} + using Role = ShaderRecompiler::DescriptorRole; using Kind = ShaderRecompiler::DescriptorKind; @@ -5317,6 +5345,11 @@ int main(int argc, char** argv) { std::cout << "sparse buffer hole tests " << (passed ? "passed" : "failed") << '\n'; return passed ? 0 : 1; } + if (argc == 2 && std::string_view(argv[1]) == "--address-space-teardown") { + addressSpaceTeardownTests(); + std::cout << "address-space device teardown releases cached guest allocations\n"; + return 0; + } if (argc == 2 && std::string_view(argv[1]) == "--descriptor-layout-flags") { descriptorLayoutFlagTests(); std::cout << "Descriptor layout native and captured binding flags passed\n";