summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp92
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.h102
2 files changed, 194 insertions, 0 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index de890676e..ef8cfffd6 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -20,8 +20,16 @@
20 20
21namespace OpenGL { 21namespace OpenGL {
22 22
23enum class EntryKind : u32 {
24 Raw,
25 Usage,
26};
27
28constexpr u32 NativeVersion = 1;
29
23// Making sure sizes doesn't change by accident 30// Making sure sizes doesn't change by accident
24static_assert(sizeof(BaseBindings) == 12); 31static_assert(sizeof(BaseBindings) == 12);
32static_assert(sizeof(ShaderDiskCacheUsage) == 24);
25 33
26namespace { 34namespace {
27std::string GetTitleID() { 35std::string GetTitleID() {
@@ -29,6 +37,90 @@ std::string GetTitleID() {
29} 37}
30} // namespace 38} // namespace
31 39
40ShaderDiskCacheRaw::ShaderDiskCacheRaw(FileUtil::IOFile& file) {
41 file.ReadBytes(&unique_identifier, sizeof(u64));
42 file.ReadBytes(&program_type, sizeof(u32));
43
44 u32 program_code_size{}, program_code_size_b{};
45 file.ReadBytes(&program_code_size, sizeof(u32));
46 file.ReadBytes(&program_code_size_b, sizeof(u32));
47
48 program_code.resize(program_code_size);
49 program_code_b.resize(program_code_size_b);
50
51 file.ReadArray(program_code.data(), program_code_size);
52 if (HasProgramA()) {
53 file.ReadArray(program_code_b.data(), program_code_size_b);
54 }
55}
56
57void ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const {
58 file.WriteObject(unique_identifier);
59 file.WriteObject(static_cast<u32>(program_type));
60 file.WriteObject(program_code_size);
61 file.WriteObject(program_code_size_b);
62
63 file.WriteArray(program_code.data(), program_code_size);
64 if (HasProgramA()) {
65 file.WriteArray(program_code_b.data(), program_code_size_b);
66 }
67}
68
69void ShaderDiskCacheOpenGL::SaveRaw(const ShaderDiskCacheRaw& entry) {
70 const u64 id = entry.GetUniqueIdentifier();
71 if (transferable.find(id) != transferable.end()) {
72 // The shader already exists
73 return;
74 }
75
76 FileUtil::IOFile file = AppendTransferableFile();
77 if (!file.IsOpen()) {
78 return;
79 }
80 file.WriteObject(EntryKind::Raw);
81 entry.Save(file);
82
83 transferable.insert({id, {}});
84}
85
86void ShaderDiskCacheOpenGL::SaveUsage(const ShaderDiskCacheUsage& usage) {
87 const auto it = transferable.find(usage.unique_identifier);
88 if (it == transferable.end()) {
89 LOG_CRITICAL(Render_OpenGL, "Saving shader usage without storing raw previously");
90 UNREACHABLE();
91 }
92 auto& usages{it->second};
93 ASSERT(usages.find(usage) == usages.end());
94 usages.insert(usage);
95
96 FileUtil::IOFile file = AppendTransferableFile();
97 if (!file.IsOpen()) {
98 return;
99 }
100 file.WriteObject(EntryKind::Usage);
101 file.WriteObject(usage);
102}
103
104FileUtil::IOFile ShaderDiskCacheOpenGL::AppendTransferableFile() const {
105 if (!EnsureDirectories()) {
106 return {};
107 }
108
109 const auto transferable_path{GetTransferablePath()};
110 const bool existed = FileUtil::Exists(transferable_path);
111
112 FileUtil::IOFile file(transferable_path, "ab");
113 if (!file.IsOpen()) {
114 LOG_ERROR(Render_OpenGL, "Failed to open transferable cache in path={}", transferable_path);
115 return {};
116 }
117 if (!existed || file.GetSize() == 0) {
118 // If the file didn't exist, write its version
119 file.WriteObject(NativeVersion);
120 }
121 return file;
122}
123
32bool ShaderDiskCacheOpenGL::EnsureDirectories() const { 124bool ShaderDiskCacheOpenGL::EnsureDirectories() const {
33 const auto CreateDir = [](const std::string& dir) { 125 const auto CreateDir = [](const std::string& dir) {
34 if (!FileUtil::CreateDir(dir)) { 126 if (!FileUtil::CreateDir(dir)) {
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.h b/src/video_core/renderer_opengl/gl_shader_disk_cache.h
index 690c92cae..d4449c132 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.h
@@ -4,12 +4,18 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <set>
7#include <string> 8#include <string>
8#include <tuple> 9#include <tuple>
10#include <vector>
9 11
12#include <glad/glad.h>
13
14#include "common/assert.h"
10#include "common/common_types.h" 15#include "common/common_types.h"
11#include "common/file_util.h" 16#include "common/file_util.h"
12#include "video_core/engines/maxwell_3d.h" 17#include "video_core/engines/maxwell_3d.h"
18#include "video_core/renderer_opengl/gl_shader_gen.h"
13 19
14namespace OpenGL { 20namespace OpenGL {
15 21
@@ -40,9 +46,102 @@ public:
40 } 46 }
41}; 47};
42 48
49class ShaderDiskCacheRaw {
50public:
51 explicit ShaderDiskCacheRaw(FileUtil::IOFile& file);
52
53 explicit ShaderDiskCacheRaw(u64 unique_identifier, Maxwell::ShaderProgram program_type,
54 u32 program_code_size, u32 program_code_size_b,
55 ProgramCode program_code, ProgramCode program_code_b)
56 : unique_identifier{unique_identifier}, program_type{program_type},
57 program_code_size{program_code_size}, program_code_size_b{program_code_size_b},
58 program_code{std::move(program_code)}, program_code_b{std::move(program_code_b)} {}
59
60 void Save(FileUtil::IOFile& file) const;
61
62 u64 GetUniqueIdentifier() const {
63 return unique_identifier;
64 }
65
66 bool HasProgramA() const {
67 return program_type == Maxwell::ShaderProgram::VertexA;
68 }
69
70 Maxwell::ShaderProgram GetProgramType() const {
71 return program_type;
72 }
73
74 Maxwell::ShaderStage GetProgramStage() const {
75 switch (program_type) {
76 case Maxwell::ShaderProgram::VertexA:
77 case Maxwell::ShaderProgram::VertexB:
78 return Maxwell::ShaderStage::Vertex;
79 case Maxwell::ShaderProgram::TesselationControl:
80 return Maxwell::ShaderStage::TesselationControl;
81 case Maxwell::ShaderProgram::TesselationEval:
82 return Maxwell::ShaderStage::TesselationEval;
83 case Maxwell::ShaderProgram::Geometry:
84 return Maxwell::ShaderStage::Geometry;
85 case Maxwell::ShaderProgram::Fragment:
86 return Maxwell::ShaderStage::Fragment;
87 }
88 UNREACHABLE();
89 }
90
91 const ProgramCode& GetProgramCode() const {
92 return program_code;
93 }
94
95 const ProgramCode& GetProgramCodeB() const {
96 return program_code_b;
97 }
98
99private:
100 u64 unique_identifier{};
101 Maxwell::ShaderProgram program_type{};
102 u32 program_code_size{};
103 u32 program_code_size_b{};
104
105 ProgramCode program_code;
106 ProgramCode program_code_b;
107};
108
109struct ShaderDiskCacheUsage {
110private:
111 auto Tie() const {
112 return std::tie(unique_identifier, bindings, primitive);
113 }
114
115public:
116 u64 unique_identifier{};
117 BaseBindings bindings;
118 GLenum primitive{};
119
120 bool operator<(const ShaderDiskCacheUsage& rhs) const {
121 return Tie() < rhs.Tie();
122 }
123
124 bool operator==(const ShaderDiskCacheUsage& rhs) const {
125 return Tie() == rhs.Tie();
126 }
127
128 bool operator!=(const ShaderDiskCacheUsage& rhs) const {
129 return !this->operator==(rhs);
130 }
131};
132
43class ShaderDiskCacheOpenGL { 133class ShaderDiskCacheOpenGL {
44public: 134public:
135 /// Saves a raw dump to the transferable file. Checks for collisions.
136 void SaveRaw(const ShaderDiskCacheRaw& entry);
137
138 /// Saves shader usage to the transferable file. Does not check for collisions.
139 void SaveUsage(const ShaderDiskCacheUsage& usage);
140
45private: 141private:
142 /// Opens current game's transferable file and write it's header if it doesn't exist
143 FileUtil::IOFile AppendTransferableFile() const;
144
46 /// Create shader disk cache directories. Returns true on success. 145 /// Create shader disk cache directories. Returns true on success.
47 bool EnsureDirectories() const; 146 bool EnsureDirectories() const;
48 147
@@ -60,6 +159,9 @@ private:
60 159
61 /// Get user's shader directory path 160 /// Get user's shader directory path
62 std::string GetBaseDir() const; 161 std::string GetBaseDir() const;
162
163 // Stored transferable shaders
164 std::map<u64, std::set<ShaderDiskCacheUsage>> transferable;
63}; 165};
64 166
65} // namespace OpenGL \ No newline at end of file 167} // namespace OpenGL \ No newline at end of file