From 402a1d0556785ae7616ec98c25ceb670c88f51f6 Mon Sep 17 00:00:00 2001 From: Itamar Medyoni Date: Wed, 14 Oct 2026 22:14:21 +0300 Subject: [PATCH] test(agc): delete mapped shader cache entries with POSIX semantics on Windows The disk cache keeps loaded and persisted entries mapped for the life of the process. On Windows 10 DeleteFileW refuses a file that still has a mapped view with ERROR_ACCESS_DENIED, so agc_shader_disk_cache failed in its final remove_all after every check had passed and left its directory in the temp folder. Delete each file with FILE_DISPOSITION_FLAG_POSIX_SEMANTICS before removing the directories, as WriteFileAtomically already renames with POSIX semantics. The mapped views stay valid, and the test still fails when a file or the directory cannot be removed. Linux is unchanged. --- .../libSceAgcDriver/tests/ShaderDiskCache.cpp | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp b/core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp index 3c7743b54e..8be16e84ae 100644 --- a/core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp @@ -56,6 +56,30 @@ void setEnvironment(const char* name, const std::string& value) { #endif } +void removeCacheDirectory(const std::filesystem::path& directory) { + std::error_code error; +#ifdef _WIN32 + std::vector files; + for (const auto& entry : std::filesystem::recursive_directory_iterator(directory)) { + if (!entry.is_directory()) files.push_back(entry.path()); + } + constexpr auto dispositionInfoEx = static_cast(21); + constexpr DWORD deleteFile = 0x00000001, posixSemantics = 0x00000002; + for (const auto& file : files) { + const auto handle = CreateFileW(file.c_str(), DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (handle == INVALID_HANDLE_VALUE) error.assign(static_cast(GetLastError()), std::system_category()); + require(!error, "cannot open " + file.string() + " for deletion: " + error.message()); + struct Close { HANDLE file; ~Close() { CloseHandle(file); } } close{handle}; + DWORD flags = deleteFile | posixSemantics; + if (!SetFileInformationByHandle(handle, dispositionInfoEx, &flags, sizeof(flags))) error.assign(static_cast(GetLastError()), std::system_category()); + require(!error, "cannot delete " + file.string() + ": " + error.message()); + } +#endif + std::filesystem::remove_all(directory, error); + require(!error, "cannot remove the shader cache test directory: " + error.message()); +} + bool sameBinding(const DescriptorBinding& left, const DescriptorBinding& right) { return left.kind == right.kind && left.role == right.role && left.descriptorSet == right.descriptorSet && left.binding == right.binding && left.count == right.count && left.guestDescriptor == right.guestDescriptor && left.readOnly == right.readOnly && left.imageShape == right.imageShape && left.samplerDepthCompare == right.samplerDepthCompare && left.imageWritten == right.imageWritten && left.imageDepthCompare == right.imageDepthCompare && left.imageAtomic == right.imageAtomic && left.imageShapes == right.imageShapes && left.bufferAtomic == right.bufferAtomic && left.bufferWritten == right.bufferWritten && left.bufferRead == right.bufferRead && left.samplerUnnormalized == right.samplerUnnormalized && left.samplerIntegerBorder == right.samplerIntegerBorder && left.imageUnnormalized == right.imageUnnormalized && left.imageUnnormalizedBaseLevel == right.imageUnnormalizedBaseLevel && left.imageSamplers == right.imageSamplers; } @@ -2128,9 +2152,7 @@ int main(int argc, char** argv) { verifyBuiltinSpecialization(); verifySpecializationLiveness(); ShaderRecompiler::ShaderDiskCache::Flush(); - std::error_code error; - std::filesystem::remove_all(directory, error); - require(!error, "cannot remove the shader cache test directory: " + error.message()); + removeCacheDirectory(directory); std::cout << "shader disk cache tests passed\n"; return 0; } catch (const std::exception& error) {