فهرست منبع

gl_shader_disk_cache: Add transferable stores

ReinUsesLisp 7 سال پیش
والد
کامیت
b1efceec89
2فایلهای تغییر یافته به همراه194 افزوده شده و 0 حذف شده
  1. 92 0
      src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
  2. 102 0
      src/video_core/renderer_opengl/gl_shader_disk_cache.h

+ 92 - 0
src/video_core/renderer_opengl/gl_shader_disk_cache.cpp

@@ -20,8 +20,16 @@
 
 
 namespace OpenGL {
 namespace OpenGL {
 
 
+enum class EntryKind : u32 {
+    Raw,
+    Usage,
+};
+
+constexpr u32 NativeVersion = 1;
+
 // Making sure sizes doesn't change by accident
 // Making sure sizes doesn't change by accident
 static_assert(sizeof(BaseBindings) == 12);
 static_assert(sizeof(BaseBindings) == 12);
+static_assert(sizeof(ShaderDiskCacheUsage) == 24);
 
 
 namespace {
 namespace {
 std::string GetTitleID() {
 std::string GetTitleID() {
@@ -29,6 +37,90 @@ std::string GetTitleID() {
 }
 }
 } // namespace
 } // namespace
 
 
+ShaderDiskCacheRaw::ShaderDiskCacheRaw(FileUtil::IOFile& file) {
+    file.ReadBytes(&unique_identifier, sizeof(u64));
+    file.ReadBytes(&program_type, sizeof(u32));
+
+    u32 program_code_size{}, program_code_size_b{};
+    file.ReadBytes(&program_code_size, sizeof(u32));
+    file.ReadBytes(&program_code_size_b, sizeof(u32));
+
+    program_code.resize(program_code_size);
+    program_code_b.resize(program_code_size_b);
+
+    file.ReadArray(program_code.data(), program_code_size);
+    if (HasProgramA()) {
+        file.ReadArray(program_code_b.data(), program_code_size_b);
+    }
+}
+
+void ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const {
+    file.WriteObject(unique_identifier);
+    file.WriteObject(static_cast<u32>(program_type));
+    file.WriteObject(program_code_size);
+    file.WriteObject(program_code_size_b);
+
+    file.WriteArray(program_code.data(), program_code_size);
+    if (HasProgramA()) {
+        file.WriteArray(program_code_b.data(), program_code_size_b);
+    }
+}
+
+void ShaderDiskCacheOpenGL::SaveRaw(const ShaderDiskCacheRaw& entry) {
+    const u64 id = entry.GetUniqueIdentifier();
+    if (transferable.find(id) != transferable.end()) {
+        // The shader already exists
+        return;
+    }
+
+    FileUtil::IOFile file = AppendTransferableFile();
+    if (!file.IsOpen()) {
+        return;
+    }
+    file.WriteObject(EntryKind::Raw);
+    entry.Save(file);
+
+    transferable.insert({id, {}});
+}
+
+void ShaderDiskCacheOpenGL::SaveUsage(const ShaderDiskCacheUsage& usage) {
+    const auto it = transferable.find(usage.unique_identifier);
+    if (it == transferable.end()) {
+        LOG_CRITICAL(Render_OpenGL, "Saving shader usage without storing raw previously");
+        UNREACHABLE();
+    }
+    auto& usages{it->second};
+    ASSERT(usages.find(usage) == usages.end());
+    usages.insert(usage);
+
+    FileUtil::IOFile file = AppendTransferableFile();
+    if (!file.IsOpen()) {
+        return;
+    }
+    file.WriteObject(EntryKind::Usage);
+    file.WriteObject(usage);
+}
+
+FileUtil::IOFile ShaderDiskCacheOpenGL::AppendTransferableFile() const {
+    if (!EnsureDirectories()) {
+        return {};
+    }
+
+    const auto transferable_path{GetTransferablePath()};
+    const bool existed = FileUtil::Exists(transferable_path);
+
+    FileUtil::IOFile file(transferable_path, "ab");
+    if (!file.IsOpen()) {
+        LOG_ERROR(Render_OpenGL, "Failed to open transferable cache in path={}", transferable_path);
+        return {};
+    }
+    if (!existed || file.GetSize() == 0) {
+        // If the file didn't exist, write its version
+        file.WriteObject(NativeVersion);
+    }
+    return file;
+}
+
 bool ShaderDiskCacheOpenGL::EnsureDirectories() const {
 bool ShaderDiskCacheOpenGL::EnsureDirectories() const {
     const auto CreateDir = [](const std::string& dir) {
     const auto CreateDir = [](const std::string& dir) {
         if (!FileUtil::CreateDir(dir)) {
         if (!FileUtil::CreateDir(dir)) {

+ 102 - 0
src/video_core/renderer_opengl/gl_shader_disk_cache.h

@@ -4,12 +4,18 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <set>
 #include <string>
 #include <string>
 #include <tuple>
 #include <tuple>
+#include <vector>
 
 
+#include <glad/glad.h>
+
+#include "common/assert.h"
 #include "common/common_types.h"
 #include "common/common_types.h"
 #include "common/file_util.h"
 #include "common/file_util.h"
 #include "video_core/engines/maxwell_3d.h"
 #include "video_core/engines/maxwell_3d.h"
+#include "video_core/renderer_opengl/gl_shader_gen.h"
 
 
 namespace OpenGL {
 namespace OpenGL {
 
 
@@ -40,9 +46,102 @@ public:
     }
     }
 };
 };
 
 
+class ShaderDiskCacheRaw {
+public:
+    explicit ShaderDiskCacheRaw(FileUtil::IOFile& file);
+
+    explicit ShaderDiskCacheRaw(u64 unique_identifier, Maxwell::ShaderProgram program_type,
+                                u32 program_code_size, u32 program_code_size_b,
+                                ProgramCode program_code, ProgramCode program_code_b)
+        : unique_identifier{unique_identifier}, program_type{program_type},
+          program_code_size{program_code_size}, program_code_size_b{program_code_size_b},
+          program_code{std::move(program_code)}, program_code_b{std::move(program_code_b)} {}
+
+    void Save(FileUtil::IOFile& file) const;
+
+    u64 GetUniqueIdentifier() const {
+        return unique_identifier;
+    }
+
+    bool HasProgramA() const {
+        return program_type == Maxwell::ShaderProgram::VertexA;
+    }
+
+    Maxwell::ShaderProgram GetProgramType() const {
+        return program_type;
+    }
+
+    Maxwell::ShaderStage GetProgramStage() const {
+        switch (program_type) {
+        case Maxwell::ShaderProgram::VertexA:
+        case Maxwell::ShaderProgram::VertexB:
+            return Maxwell::ShaderStage::Vertex;
+        case Maxwell::ShaderProgram::TesselationControl:
+            return Maxwell::ShaderStage::TesselationControl;
+        case Maxwell::ShaderProgram::TesselationEval:
+            return Maxwell::ShaderStage::TesselationEval;
+        case Maxwell::ShaderProgram::Geometry:
+            return Maxwell::ShaderStage::Geometry;
+        case Maxwell::ShaderProgram::Fragment:
+            return Maxwell::ShaderStage::Fragment;
+        }
+        UNREACHABLE();
+    }
+
+    const ProgramCode& GetProgramCode() const {
+        return program_code;
+    }
+
+    const ProgramCode& GetProgramCodeB() const {
+        return program_code_b;
+    }
+
+private:
+    u64 unique_identifier{};
+    Maxwell::ShaderProgram program_type{};
+    u32 program_code_size{};
+    u32 program_code_size_b{};
+
+    ProgramCode program_code;
+    ProgramCode program_code_b;
+};
+
+struct ShaderDiskCacheUsage {
+private:
+    auto Tie() const {
+        return std::tie(unique_identifier, bindings, primitive);
+    }
+
+public:
+    u64 unique_identifier{};
+    BaseBindings bindings;
+    GLenum primitive{};
+
+    bool operator<(const ShaderDiskCacheUsage& rhs) const {
+        return Tie() < rhs.Tie();
+    }
+
+    bool operator==(const ShaderDiskCacheUsage& rhs) const {
+        return Tie() == rhs.Tie();
+    }
+
+    bool operator!=(const ShaderDiskCacheUsage& rhs) const {
+        return !this->operator==(rhs);
+    }
+};
+
 class ShaderDiskCacheOpenGL {
 class ShaderDiskCacheOpenGL {
 public:
 public:
+    /// Saves a raw dump to the transferable file. Checks for collisions.
+    void SaveRaw(const ShaderDiskCacheRaw& entry);
+
+    /// Saves shader usage to the transferable file. Does not check for collisions.
+    void SaveUsage(const ShaderDiskCacheUsage& usage);
+
 private:
 private:
+    /// Opens current game's transferable file and write it's header if it doesn't exist
+    FileUtil::IOFile AppendTransferableFile() const;
+
     /// Create shader disk cache directories. Returns true on success.
     /// Create shader disk cache directories. Returns true on success.
     bool EnsureDirectories() const;
     bool EnsureDirectories() const;
 
 
@@ -60,6 +159,9 @@ private:
 
 
     /// Get user's shader directory path
     /// Get user's shader directory path
     std::string GetBaseDir() const;
     std::string GetBaseDir() const;
+
+    // Stored transferable shaders
+    std::map<u64, std::set<ShaderDiskCacheUsage>> transferable;
 };
 };
 
 
 } // namespace OpenGL
 } // namespace OpenGL