fix(agc): release cached address space on device teardown

This commit is contained in:
MarcZX100 2026-10-13 00:07:29 +00:00
parent 88107b7de6
commit abc997b0da
3 changed files with 40 additions and 2 deletions

View File

@ -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:$<TARGET_FILE_DIR:libc>")
endif()
if(NOT WIN32)

View File

@ -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<const GuestBufferMemory::AddressSpace>{});
}
auto& state = Mirrors();
std::map<std::uint64_t, std::shared_ptr<ImageMirror>> 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) {

View File

@ -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 <spirv/unified1/spirv.hpp>
#include <algorithm>
#include <array>
@ -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<VkDevice>();
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";