Fix OpenGL shader temp file collisions
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
@@ -72,6 +73,7 @@ bool TryResolveShaderTypeFromTarget(const char* target, ShaderType& type) {
|
||||
|
||||
constexpr uint32_t kSpirvMagic = 0x07230203u;
|
||||
constexpr uint16_t kSpirvOpEntryPoint = 15;
|
||||
std::atomic<uint64_t> g_temporaryPathCounter = 0;
|
||||
|
||||
ShaderType ToShaderType(uint32_t executionModel) {
|
||||
switch (executionModel) {
|
||||
@@ -483,19 +485,49 @@ const char* SpirvTargetName(SpirvTargetEnvironment targetEnvironment) {
|
||||
|
||||
bool CreateTemporaryPath(const wchar_t* extension, std::wstring& outPath) {
|
||||
wchar_t tempDirectory[MAX_PATH] = {};
|
||||
if (GetTempPathW(MAX_PATH, tempDirectory) == 0) {
|
||||
const DWORD tempDirectoryLength = GetTempPathW(MAX_PATH, tempDirectory);
|
||||
if (tempDirectoryLength == 0 || tempDirectoryLength >= MAX_PATH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wchar_t tempFile[MAX_PATH] = {};
|
||||
if (GetTempFileNameW(tempDirectory, L"XCV", 0, tempFile) == 0) {
|
||||
return false;
|
||||
const std::wstring extensionSuffix = extension != nullptr ? extension : L"";
|
||||
const DWORD processId = GetCurrentProcessId();
|
||||
|
||||
for (uint32_t attempt = 0; attempt < 256u; ++attempt) {
|
||||
const uint64_t counter =
|
||||
g_temporaryPathCounter.fetch_add(1u, std::memory_order_relaxed) + 1u;
|
||||
|
||||
wchar_t fileName[128] = {};
|
||||
swprintf_s(
|
||||
fileName,
|
||||
L"XCE_%08X_%016llX%ls",
|
||||
processId,
|
||||
static_cast<unsigned long long>(counter),
|
||||
extensionSuffix.c_str());
|
||||
|
||||
const std::filesystem::path candidatePath =
|
||||
std::filesystem::path(tempDirectory) / fileName;
|
||||
const HANDLE handle = CreateFileW(
|
||||
candidatePath.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
nullptr,
|
||||
CREATE_NEW,
|
||||
FILE_ATTRIBUTE_TEMPORARY,
|
||||
nullptr);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(handle);
|
||||
outPath = candidatePath.wstring();
|
||||
return true;
|
||||
}
|
||||
|
||||
const DWORD error = GetLastError();
|
||||
if (error != ERROR_ALREADY_EXISTS && error != ERROR_FILE_EXISTS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteFileW(tempFile);
|
||||
outPath = tempFile;
|
||||
outPath += extension;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WriteBinaryFile(const std::filesystem::path& path, const void* data, size_t size) {
|
||||
|
||||
Reference in New Issue
Block a user