From 258f35515d61d01049d2e433146cab808837bb7d Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 18 Jul 2021 21:07:12 -0300
Subject: [PATCH] shader_environment: Receive cache version from outside

This allows us invalidating OpenGL and Vulkan separately in the future.
---
 src/video_core/renderer_opengl/gl_shader_cache.cpp   | 10 +++++++---
 src/video_core/renderer_vulkan/vk_pipeline_cache.cpp |  9 ++++++---
 src/video_core/shader_environment.cpp                | 11 +++++------
 src/video_core/shader_environment.h                  |  9 +++++----
 4 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 7ecafc862a..8d6cc074c3 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -48,9 +48,12 @@ using VideoCommon::ComputeEnvironment;
 using VideoCommon::FileEnvironment;
 using VideoCommon::GenericEnvironment;
 using VideoCommon::GraphicsEnvironment;
+using VideoCommon::LoadPipelines;
 using VideoCommon::SerializePipeline;
 using Context = ShaderContext::Context;
 
+constexpr u32 CACHE_VERSION = 5;
+
 template <typename Container>
 auto MakeSpan(Container& container) {
     return std::span(container.data(), container.size());
@@ -287,7 +290,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
             });
         ++state.total;
     }};
-    VideoCommon::LoadPipelines(stop_loading, shader_cache_filename, load_compute, load_graphics);
+    LoadPipelines(stop_loading, shader_cache_filename, CACHE_VERSION, load_compute, load_graphics);
 
     std::unique_lock lock{state.mutex};
     callback(VideoCore::LoadCallbackStage::Build, 0, state.total);
@@ -394,7 +397,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() {
             env_ptrs.push_back(&environments.envs[index]);
         }
     }
-    SerializePipeline(graphics_key, env_ptrs, shader_cache_filename);
+    SerializePipeline(graphics_key, env_ptrs, shader_cache_filename, CACHE_VERSION);
     return pipeline;
 }
 
@@ -492,7 +495,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
     if (!pipeline || shader_cache_filename.empty()) {
         return pipeline;
     }
-    SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env}, shader_cache_filename);
+    SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env}, shader_cache_filename,
+                      CACHE_VERSION);
     return pipeline;
 }
 
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 39db351750..2ce8b4156d 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -54,6 +54,8 @@ using VideoCommon::FileEnvironment;
 using VideoCommon::GenericEnvironment;
 using VideoCommon::GraphicsEnvironment;
 
+constexpr u32 CACHE_VERSION = 5;
+
 template <typename Container>
 auto MakeSpan(Container& container) {
     return std::span(container.data(), container.size());
@@ -434,7 +436,8 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
         });
         ++state.total;
     }};
-    VideoCommon::LoadPipelines(stop_loading, pipeline_cache_filename, load_compute, load_graphics);
+    VideoCommon::LoadPipelines(stop_loading, pipeline_cache_filename, CACHE_VERSION, load_compute,
+                               load_graphics);
 
     std::unique_lock lock{state.mutex};
     callback(VideoCore::LoadCallbackStage::Build, 0, state.total);
@@ -562,7 +565,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() {
                 env_ptrs.push_back(&envs[index]);
             }
         }
-        SerializePipeline(key, env_ptrs, pipeline_cache_filename);
+        SerializePipeline(key, env_ptrs, pipeline_cache_filename, CACHE_VERSION);
     });
     return pipeline;
 }
@@ -581,7 +584,7 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
     }
     serialization_thread.QueueWork([this, key, env = std::move(env)] {
         SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
-                          pipeline_cache_filename);
+                          pipeline_cache_filename, CACHE_VERSION);
     });
     return pipeline;
 }
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 429cab30de..8a4581c192 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -22,7 +22,6 @@
 namespace VideoCommon {
 
 constexpr std::array<char, 8> MAGIC_NUMBER{'y', 'u', 'z', 'u', 'c', 'a', 'c', 'h'};
-constexpr u32 CACHE_VERSION = 5;
 
 constexpr size_t INST_SIZE = sizeof(u64);
 
@@ -370,7 +369,7 @@ std::array<u32, 3> FileEnvironment::WorkgroupSize() const {
 }
 
 void SerializePipeline(std::span<const char> key, std::span<const GenericEnvironment* const> envs,
-                       const std::filesystem::path& filename) try {
+                       const std::filesystem::path& filename, u32 cache_version) try {
     std::ofstream file(filename, std::ios::binary | std::ios::ate | std::ios::app);
     file.exceptions(std::ifstream::failbit);
     if (!file.is_open()) {
@@ -381,7 +380,7 @@ void SerializePipeline(std::span<const char> key, std::span<const GenericEnviron
     if (file.tellp() == 0) {
         // Write header
         file.write(MAGIC_NUMBER.data(), MAGIC_NUMBER.size())
-            .write(reinterpret_cast<const char*>(&CACHE_VERSION), sizeof(CACHE_VERSION));
+            .write(reinterpret_cast<const char*>(&cache_version), sizeof(cache_version));
     }
     if (!std::ranges::all_of(envs, &GenericEnvironment::CanBeSerialized)) {
         return;
@@ -402,7 +401,7 @@ void SerializePipeline(std::span<const char> key, std::span<const GenericEnviron
 }
 
 void LoadPipelines(
-    std::stop_token stop_loading, const std::filesystem::path& filename,
+    std::stop_token stop_loading, const std::filesystem::path& filename, u32 expected_cache_version,
     Common::UniqueFunction<void, std::ifstream&, FileEnvironment> load_compute,
     Common::UniqueFunction<void, std::ifstream&, std::vector<FileEnvironment>> load_graphics) try {
     std::ifstream file(filename, std::ios::binary | std::ios::ate);
@@ -417,13 +416,13 @@ void LoadPipelines(
     u32 cache_version;
     file.read(magic_number.data(), magic_number.size())
         .read(reinterpret_cast<char*>(&cache_version), sizeof(cache_version));
-    if (magic_number != MAGIC_NUMBER || cache_version != CACHE_VERSION) {
+    if (magic_number != MAGIC_NUMBER || cache_version != expected_cache_version) {
         file.close();
         if (Common::FS::RemoveFile(filename)) {
             if (magic_number != MAGIC_NUMBER) {
                 LOG_ERROR(Common_Filesystem, "Invalid pipeline cache file");
             }
-            if (cache_version != CACHE_VERSION) {
+            if (cache_version != expected_cache_version) {
                 LOG_INFO(Common_Filesystem, "Deleting old pipeline cache");
             }
         } else {
diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h
index d26dbfaab6..2079979db1 100644
--- a/src/video_core/shader_environment.h
+++ b/src/video_core/shader_environment.h
@@ -164,18 +164,19 @@ private:
 };
 
 void SerializePipeline(std::span<const char> key, std::span<const GenericEnvironment* const> envs,
-                       const std::filesystem::path& filename);
+                       const std::filesystem::path& filename, u32 cache_version);
 
 template <typename Key, typename Envs>
-void SerializePipeline(const Key& key, const Envs& envs, const std::filesystem::path& filename) {
+void SerializePipeline(const Key& key, const Envs& envs, const std::filesystem::path& filename,
+                       u32 cache_version) {
     static_assert(std::is_trivially_copyable_v<Key>);
     static_assert(std::has_unique_object_representations_v<Key>);
     SerializePipeline(std::span(reinterpret_cast<const char*>(&key), sizeof(key)),
-                      std::span(envs.data(), envs.size()), filename);
+                      std::span(envs.data(), envs.size()), filename, cache_version);
 }
 
 void LoadPipelines(
-    std::stop_token stop_loading, const std::filesystem::path& filename,
+    std::stop_token stop_loading, const std::filesystem::path& filename, u32 expected_cache_version,
     Common::UniqueFunction<void, std::ifstream&, FileEnvironment> load_compute,
     Common::UniqueFunction<void, std::ifstream&, std::vector<FileEnvironment>> load_graphics);