diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt
index 707a1a0706..d9e792cc4a 100644
--- a/Common/CMakeLists.txt
+++ b/Common/CMakeLists.txt
@@ -179,6 +179,7 @@ add_library(Common STATIC
GPU/Vulkan/VulkanDebug.h
GPU/Vulkan/VulkanContext.cpp
GPU/Vulkan/VulkanContext.h
+ GPU/Vulkan/FixedSPIRVCache.h
GPU/Vulkan/VulkanDescSet.cpp
GPU/Vulkan/VulkanDescSet.h
GPU/Vulkan/VulkanFramebuffer.cpp
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index f38d5e2716..57d9622932 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -451,6 +451,7 @@
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index bf0eeaa929..dc9852ca52 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -305,6 +305,9 @@
GPU\Vulkan
+
+ GPU\Vulkan
+
GPU\Vulkan
diff --git a/Common/GPU/Vulkan/FixedSPIRVCache.h b/Common/GPU/Vulkan/FixedSPIRVCache.h
new file mode 100644
index 0000000000..ee4b97a478
--- /dev/null
+++ b/Common/GPU/Vulkan/FixedSPIRVCache.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "Common/File/Path.h"
+
+// The SPIR-V cache of thin3d's and other fixed shaders (g_spirvCache in VulkanContext.h), for code
+// that shouldn't include the Vulkan headers: on Linux they pull in X11, whose macros (None and
+// friends) break unrelated headers.
+void SetFixedSPIRVCachePath(const Path &path, int maxEntries);
+void SaveFixedSPIRVCache();
diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp
index 46c4581779..bddba4c225 100644
--- a/Common/GPU/Vulkan/VulkanContext.cpp
+++ b/Common/GPU/Vulkan/VulkanContext.cpp
@@ -12,6 +12,7 @@
#include "Common/GPU/MiscTypes.h"
#include "Common/GPU/Vulkan/VulkanContext.h"
#include "Common/GPU/Vulkan/VulkanDebug.h"
+#include "Common/GPU/Vulkan/FixedSPIRVCache.h"
#include "Common/StringUtils.h"
#include "Common/File/FileUtil.h"
#include "ext/xxhash.h"
@@ -1800,6 +1801,14 @@ struct SPIRVCacheEntryHeader {
SPIRVCache g_spirvCache;
+void SetFixedSPIRVCachePath(const Path &path, int maxEntries) {
+ g_spirvCache.SetPath(path, maxEntries);
+}
+
+void SaveFixedSPIRVCache() {
+ g_spirvCache.SaveIfDirty();
+}
+
SPIRVCache::Key SPIRVCache::MakeKey(VkShaderStageFlagBits stage, GLSLVariant variant, const char *source) {
const size_t length = strlen(source);
const uint32_t seed = (SPIRV_CACHE_VERSION << 16) | ((uint32_t)stage << 4) | (uint32_t)variant;
diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp
index c8031da07a..2f8a43ce88 100644
--- a/UI/NativeApp.cpp
+++ b/UI/NativeApp.cpp
@@ -62,7 +62,7 @@
#include "Common/Render/Text/draw_text.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
#include "Common/GPU/thin3d.h"
-#include "Common/GPU/Vulkan/VulkanContext.h"
+#include "Common/GPU/Vulkan/FixedSPIRVCache.h"
#include "Common/UI/UI.h"
#include "Common/UI/Screen.h"
#include "Common/UI/ScreenManager.h"
@@ -805,7 +805,7 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO
File::CreateFullPath(GetSysDirectory(DIRECTORY_APP_CACHE));
// About twice what a session compiles (menu and a game: 10, a few more with post-processing
// or texture upscaling), so it's flushed once outdated entries have piled up.
- g_spirvCache.SetPath(GetSysDirectory(DIRECTORY_APP_CACHE) / "vulkan_spirv.cache", 32);
+ SetFixedSPIRVCachePath(GetSysDirectory(DIRECTORY_APP_CACHE) / "vulkan_spirv.cache", 32);
}
#endif
@@ -979,7 +979,7 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
#if !PPSSPP_PLATFORM(UWP)
// Now, rather than only at shutdown: on mobile the app can be killed without one.
- g_spirvCache.SaveIfDirty();
+ SaveFixedSPIRVCache();
#endif
INFO_LOG(Log::System, "NativeInitGraphics completed");
@@ -1043,7 +1043,7 @@ void NativeShutdownGraphics(GraphicsContext *graphicsContext) {
INFO_LOG(Log::System, "NativeShutdownGraphics begin");
#if !PPSSPP_PLATFORM(UWP)
- g_spirvCache.SaveIfDirty();
+ SaveFixedSPIRVCache();
#endif
graphicsContext->NotifyEmuThreadExit();