summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp113
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h10
3 files changed, 116 insertions, 11 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 72a6dfd2a..eec01e8c2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -140,7 +140,9 @@ void RasterizerOpenGL::SyncVertexInstances() {
140} 140}
141 141
142void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_loading, 142void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
143 const VideoCore::DiskResourceLoadCallback& callback) {} 143 const VideoCore::DiskResourceLoadCallback& callback) {
144 shader_cache.LoadDiskResources(title_id, stop_loading, callback);
145}
144 146
145void RasterizerOpenGL::Clear() { 147void RasterizerOpenGL::Clear() {
146 MICROPROFILE_SCOPE(OpenGL_Clears); 148 MICROPROFILE_SCOPE(OpenGL_Clears);
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 33757938a..3aa5ac31d 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -3,17 +3,19 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <atomic> 5#include <atomic>
6#include <fstream>
6#include <functional> 7#include <functional>
7#include <mutex> 8#include <mutex>
8#include <optional>
9#include <string> 9#include <string>
10#include <thread> 10#include <thread>
11#include <unordered_set>
12 11
13#include "common/alignment.h" 12#include "common/alignment.h"
14#include "common/assert.h" 13#include "common/assert.h"
14#include "common/fs/fs.h"
15#include "common/fs/path_util.h"
15#include "common/logging/log.h" 16#include "common/logging/log.h"
16#include "common/scope_exit.h" 17#include "common/scope_exit.h"
18#include "common/thread_worker.h"
17#include "core/core.h" 19#include "core/core.h"
18#include "core/frontend/emu_window.h" 20#include "core/frontend/emu_window.h"
19#include "shader_recompiler/backend/glasm/emit_glasm.h" 21#include "shader_recompiler/backend/glasm/emit_glasm.h"
@@ -40,6 +42,8 @@ using Shader::Backend::GLASM::EmitGLASM;
40using Shader::Backend::SPIRV::EmitSPIRV; 42using Shader::Backend::SPIRV::EmitSPIRV;
41using Shader::Maxwell::TranslateProgram; 43using Shader::Maxwell::TranslateProgram;
42using VideoCommon::ComputeEnvironment; 44using VideoCommon::ComputeEnvironment;
45using VideoCommon::FileEnvironment;
46using VideoCommon::GenericEnvironment;
43using VideoCommon::GraphicsEnvironment; 47using VideoCommon::GraphicsEnvironment;
44 48
45template <typename Container> 49template <typename Container>
@@ -154,8 +158,6 @@ GLenum AssemblyStage(size_t stage_index) {
154 158
155Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, 159Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
156 const Shader::IR::Program& program) { 160 const Shader::IR::Program& program) {
157 UNIMPLEMENTED_IF_MSG(key.xfb_enabled != 0, "Transform feedbacks");
158
159 Shader::RuntimeInfo info; 161 Shader::RuntimeInfo info;
160 switch (program.stage) { 162 switch (program.stage) {
161 case Shader::Stage::TessellationEval: 163 case Shader::Stage::TessellationEval:
@@ -282,6 +284,89 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
282 284
283ShaderCache::~ShaderCache() = default; 285ShaderCache::~ShaderCache() = default;
284 286
287void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
288 const VideoCore::DiskResourceLoadCallback& callback) {
289 if (title_id == 0) {
290 return;
291 }
292 auto shader_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir)};
293 auto base_dir{shader_dir / "new_opengl"};
294 auto transferable_dir{base_dir / "transferable"};
295 auto precompiled_dir{base_dir / "precompiled"};
296 if (!Common::FS::CreateDir(shader_dir) || !Common::FS::CreateDir(base_dir) ||
297 !Common::FS::CreateDir(transferable_dir) || !Common::FS::CreateDir(precompiled_dir)) {
298 LOG_ERROR(Common_Filesystem, "Failed to create pipeline cache directories");
299 return;
300 }
301 shader_cache_filename = transferable_dir / fmt::format("{:016x}.bin", title_id);
302
303 struct Context {
304 explicit Context(Core::Frontend::EmuWindow& emu_window)
305 : gl_context{emu_window.CreateSharedContext()}, scoped{*gl_context} {}
306
307 std::unique_ptr<Core::Frontend::GraphicsContext> gl_context;
308 Core::Frontend::GraphicsContext::Scoped scoped;
309 ShaderPools pools;
310 };
311 Common::StatefulThreadWorker<Context> workers(
312 std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:ShaderBuilder",
313 [this] { return Context{emu_window}; });
314
315 struct {
316 std::mutex mutex;
317 size_t total{0};
318 size_t built{0};
319 bool has_loaded{false};
320 } state;
321
322 const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
323 ComputePipelineKey key;
324 file.read(reinterpret_cast<char*>(&key), sizeof(key));
325 workers.QueueWork(
326 [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
327 ctx->pools.ReleaseContents();
328 auto pipeline{CreateComputePipeline(ctx->pools, key, env, false)};
329
330 std::lock_guard lock{state.mutex};
331 compute_cache.emplace(key, std::move(pipeline));
332 ++state.built;
333 if (state.has_loaded) {
334 callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
335 }
336 });
337 ++state.total;
338 }};
339 const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
340 GraphicsPipelineKey key;
341 file.read(reinterpret_cast<char*>(&key), sizeof(key));
342 workers.QueueWork(
343 [this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
344 boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
345 for (auto& env : envs) {
346 env_ptrs.push_back(&env);
347 }
348 ctx->pools.ReleaseContents();
349 auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)};
350
351 std::lock_guard lock{state.mutex};
352 graphics_cache.emplace(key, std::move(pipeline));
353 ++state.built;
354 if (state.has_loaded) {
355 callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
356 }
357 });
358 ++state.total;
359 }};
360 VideoCommon::LoadPipelines(stop_loading, shader_cache_filename, load_compute, load_graphics);
361
362 std::unique_lock lock{state.mutex};
363 callback(VideoCore::LoadCallbackStage::Build, 0, state.total);
364 state.has_loaded = true;
365 lock.unlock();
366
367 workers.WaitForRequests();
368}
369
285GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { 370GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
286 if (!RefreshStages(graphics_key.unique_hashes)) { 371 if (!RefreshStages(graphics_key.unique_hashes)) {
287 return nullptr; 372 return nullptr;
@@ -332,7 +417,18 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() {
332 GetGraphicsEnvironments(environments, graphics_key.unique_hashes); 417 GetGraphicsEnvironments(environments, graphics_key.unique_hashes);
333 418
334 main_pools.ReleaseContents(); 419 main_pools.ReleaseContents();
335 return CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(), true); 420 auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(), true)};
421 if (shader_cache_filename.empty()) {
422 return pipeline;
423 }
424 boost::container::static_vector<const GenericEnvironment*, Maxwell::MaxShaderProgram> env_ptrs;
425 for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
426 if (graphics_key.unique_hashes[index] != 0) {
427 env_ptrs.push_back(&environments.envs[index]);
428 }
429 }
430 VideoCommon::SerializePipeline(graphics_key, env_ptrs, shader_cache_filename);
431 return pipeline;
336} 432}
337 433
338std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( 434std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
@@ -396,7 +492,12 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
396 env.SetCachedSize(shader->size_bytes); 492 env.SetCachedSize(shader->size_bytes);
397 493
398 main_pools.ReleaseContents(); 494 main_pools.ReleaseContents();
399 return CreateComputePipeline(main_pools, key, env, true); 495 auto pipeline{CreateComputePipeline(main_pools, key, env, true)};
496 if (!shader_cache_filename.empty()) {
497 VideoCommon::SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
498 shader_cache_filename);
499 }
500 return pipeline;
400} 501}
401 502
402std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools& pools, 503std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools& pools,
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index a56559ea9..16175318b 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -5,6 +5,8 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <filesystem>
9#include <stop_token>
8#include <unordered_map> 10#include <unordered_map>
9 11
10#include <glad/glad.h> 12#include <glad/glad.h>
@@ -23,10 +25,6 @@ namespace Tegra {
23class MemoryManager; 25class MemoryManager;
24} 26}
25 27
26namespace Core::Frontend {
27class EmuWindow;
28}
29
30namespace OpenGL { 28namespace OpenGL {
31 29
32class Device; 30class Device;
@@ -55,6 +53,9 @@ public:
55 ProgramManager& program_manager_, StateTracker& state_tracker_); 53 ProgramManager& program_manager_, StateTracker& state_tracker_);
56 ~ShaderCache(); 54 ~ShaderCache();
57 55
56 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
57 const VideoCore::DiskResourceLoadCallback& callback);
58
58 [[nodiscard]] GraphicsPipeline* CurrentGraphicsPipeline(); 59 [[nodiscard]] GraphicsPipeline* CurrentGraphicsPipeline();
59 60
60 [[nodiscard]] ComputePipeline* CurrentComputePipeline(); 61 [[nodiscard]] ComputePipeline* CurrentComputePipeline();
@@ -88,6 +89,7 @@ private:
88 std::unordered_map<ComputePipelineKey, std::unique_ptr<ComputePipeline>> compute_cache; 89 std::unordered_map<ComputePipelineKey, std::unique_ptr<ComputePipeline>> compute_cache;
89 90
90 Shader::Profile profile; 91 Shader::Profile profile;
92 std::filesystem::path shader_cache_filename;
91}; 93};
92 94
93} // namespace OpenGL 95} // namespace OpenGL