From 0ed5d728ca12e407685b62802dec69b455f1a528 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 13 Jan 2019 22:05:53 -0300 Subject: rasterizer_interface: Add disk cache entry for the rasterizer --- src/core/core.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core') diff --git a/src/core/core.cpp b/src/core/core.cpp index 572814e4b..c8d7c442a 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -175,6 +175,9 @@ struct System::Impl { return static_cast(static_cast(ResultStatus::ErrorLoader) + static_cast(load_result)); } + + renderer->Rasterizer().LoadDiskResources(); + status = ResultStatus::Success; return status; } -- cgit v1.2.3 From e78da8dc1f8b6fbb6e9c1aeff9e54fe7f879d3b1 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 14 Jan 2019 02:14:27 -0300 Subject: settings: Hide shader cache behind a setting --- src/core/settings.h | 1 + src/core/telemetry_session.cpp | 2 ++ .../renderer_opengl/gl_shader_disk_cache.cpp | 21 +++++++++++++++++++++ src/yuzu/configuration/config.cpp | 3 +++ src/yuzu/configuration/configure_graphics.cpp | 2 ++ src/yuzu/configuration/configure_graphics.ui | 7 +++++++ src/yuzu_cmd/config.cpp | 2 ++ src/yuzu_cmd/default_ini.h | 4 ++++ 8 files changed, 42 insertions(+) (limited to 'src/core') diff --git a/src/core/settings.h b/src/core/settings.h index c97387fc7..7e76e0466 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -391,6 +391,7 @@ struct Values { float resolution_factor; bool use_frame_limit; u16 frame_limit; + bool use_disk_shader_cache; bool use_accurate_gpu_emulation; float bg_red; diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 09ed74d78..58dfcc4df 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -158,6 +158,8 @@ TelemetrySession::TelemetrySession() { AddField(Telemetry::FieldType::UserConfig, "Renderer_UseFrameLimit", Settings::values.use_frame_limit); AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimit", Settings::values.frame_limit); + AddField(Telemetry::FieldType::UserConfig, "Renderer_UseDiskShaderCache", + Settings::values.use_disk_shader_cache); AddField(Telemetry::FieldType::UserConfig, "Renderer_UseAccurateGpuEmulation", Settings::values.use_accurate_gpu_emulation); AddField(Telemetry::FieldType::UserConfig, "System_UseDockedMode", 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 4b0e50b90..6a23b8fe2 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -17,6 +17,7 @@ #include "core/core.h" #include "core/hle/kernel/process.h" +#include "core/settings.h" #include "video_core/renderer_opengl/gl_shader_cache.h" #include "video_core/renderer_opengl/gl_shader_disk_cache.h" @@ -78,6 +79,10 @@ void ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const { bool ShaderDiskCacheOpenGL::LoadTransferable(std::vector& raws, std::vector& usages) { + if (!Settings::values.use_disk_shader_cache) { + return false; + } + FileUtil::IOFile file(GetTransferablePath(), "rb"); if (!file.IsOpen()) { LOG_INFO(Render_OpenGL, "No transferable shader cache found for game with title id={}", @@ -129,6 +134,10 @@ bool ShaderDiskCacheOpenGL::LoadTransferable(std::vector& ra } std::vector ShaderDiskCacheOpenGL::LoadPrecompiled() { + if (!Settings::values.use_disk_shader_cache) { + return {}; + } + FileUtil::IOFile file(GetPrecompiledPath(), "rb"); if (!file.IsOpen()) { LOG_INFO(Render_OpenGL, "No precompiled shader cache found for game with title id={}", @@ -173,6 +182,10 @@ void ShaderDiskCacheOpenGL::InvalidatePrecompiled() const { } void ShaderDiskCacheOpenGL::SaveRaw(const ShaderDiskCacheRaw& entry) { + if (!Settings::values.use_disk_shader_cache) { + return; + } + const u64 id = entry.GetUniqueIdentifier(); if (transferable.find(id) != transferable.end()) { // The shader already exists @@ -190,6 +203,10 @@ void ShaderDiskCacheOpenGL::SaveRaw(const ShaderDiskCacheRaw& entry) { } void ShaderDiskCacheOpenGL::SaveUsage(const ShaderDiskCacheUsage& usage) { + if (!Settings::values.use_disk_shader_cache) { + return; + } + const auto it = transferable.find(usage.unique_identifier); if (it == transferable.end()) { LOG_CRITICAL(Render_OpenGL, "Saving shader usage without storing raw previously"); @@ -208,6 +225,10 @@ void ShaderDiskCacheOpenGL::SaveUsage(const ShaderDiskCacheUsage& usage) { } void ShaderDiskCacheOpenGL::SavePrecompiled(const ShaderDiskCacheUsage& usage, GLuint program) { + if (!Settings::values.use_disk_shader_cache) { + return; + } + FileUtil::IOFile file = AppendPrecompiledFile(); if (!file.IsOpen()) { return; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index ddf4cf552..e9546dadf 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -370,6 +370,8 @@ void Config::ReadValues() { Settings::values.resolution_factor = qt_config->value("resolution_factor", 1.0).toFloat(); Settings::values.use_frame_limit = qt_config->value("use_frame_limit", true).toBool(); Settings::values.frame_limit = qt_config->value("frame_limit", 100).toInt(); + Settings::values.use_disk_shader_cache = + qt_config->value("use_disk_shader_cache", false).toBool(); Settings::values.use_accurate_gpu_emulation = qt_config->value("use_accurate_gpu_emulation", false).toBool(); @@ -629,6 +631,7 @@ void Config::SaveValues() { qt_config->setValue("resolution_factor", (double)Settings::values.resolution_factor); qt_config->setValue("use_frame_limit", Settings::values.use_frame_limit); qt_config->setValue("frame_limit", Settings::values.frame_limit); + qt_config->setValue("use_disk_shader_cache", Settings::values.use_disk_shader_cache); qt_config->setValue("use_accurate_gpu_emulation", Settings::values.use_accurate_gpu_emulation); // Cast to double because Qt's written float values are not human-readable diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index d21f95469..0f5dd534b 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -73,6 +73,7 @@ void ConfigureGraphics::setConfiguration() { static_cast(FromResolutionFactor(Settings::values.resolution_factor))); ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit); ui->frame_limit->setValue(Settings::values.frame_limit); + ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache); ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation); UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue)); @@ -83,6 +84,7 @@ void ConfigureGraphics::applyConfiguration() { ToResolutionFactor(static_cast(ui->resolution_factor_combobox->currentIndex())); Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked(); Settings::values.frame_limit = ui->frame_limit->value(); + Settings::values.use_disk_shader_cache = ui->use_disk_shader_cache->isChecked(); Settings::values.use_accurate_gpu_emulation = ui->use_accurate_gpu_emulation->isChecked(); Settings::values.bg_red = static_cast(bg_color.redF()); Settings::values.bg_green = static_cast(bg_color.greenF()); diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index e278cdd05..824f5810a 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -49,6 +49,13 @@ + + + + Use disk shader cache + + + diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 7a77f76e8..ff05b3179 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -350,6 +350,8 @@ void Config::ReadValues() { Settings::values.use_frame_limit = sdl2_config->GetBoolean("Renderer", "use_frame_limit", true); Settings::values.frame_limit = static_cast(sdl2_config->GetInteger("Renderer", "frame_limit", 100)); + Settings::values.use_disk_shader_cache = + sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false); Settings::values.use_accurate_gpu_emulation = sdl2_config->GetBoolean("Renderer", "use_accurate_gpu_emulation", false); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index ba51a4a51..a81986f8e 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -110,6 +110,10 @@ use_frame_limit = # 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) frame_limit = +# Whether to use disk based shader cache +# 0 (default): Off, 1 : On +use_disk_shader_cache = + # Whether to use accurate GPU emulation # 0 (default): Off (fast), 1 : On (slow) use_accurate_gpu_emulation = -- cgit v1.2.3 From 7fefec585c805fa09951da11890bb90afb8a42a9 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 15 Jan 2019 16:28:42 -0300 Subject: gl_shader_disk_cache: Pass core system as argument and guard against games without title ids --- src/core/core.cpp | 2 +- src/video_core/renderer_opengl/gl_rasterizer.cpp | 5 +++-- src/video_core/renderer_opengl/gl_rasterizer.h | 7 ++++++- src/video_core/renderer_opengl/gl_shader_cache.cpp | 3 ++- src/video_core/renderer_opengl/gl_shader_cache.h | 6 +++++- src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | 14 ++++++++++---- src/video_core/renderer_opengl/gl_shader_disk_cache.h | 13 ++++++++++++- src/video_core/renderer_opengl/renderer_opengl.cpp | 6 +++--- src/video_core/renderer_opengl/renderer_opengl.h | 8 +++++++- src/video_core/video_core.cpp | 5 +++-- src/video_core/video_core.h | 7 ++++++- 11 files changed, 58 insertions(+), 18 deletions(-) (limited to 'src/core') diff --git a/src/core/core.cpp b/src/core/core.cpp index c8d7c442a..1d71312aa 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -123,7 +123,7 @@ struct System::Impl { Service::Init(service_manager, *virtual_filesystem); GDBStub::Init(); - renderer = VideoCore::CreateRenderer(emu_window); + renderer = VideoCore::CreateRenderer(emu_window, system); if (!renderer->Init()) { return ResultStatus::ErrorVideoCore; } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 48e003fa1..94a5058de 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -100,8 +100,9 @@ struct FramebufferCacheKey { } }; -RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info) - : res_cache{*this}, shader_cache{*this}, emu_window{window}, screen_info{info}, +RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, Core::System& system, + ScreenInfo& info) + : res_cache{*this}, shader_cache{*this, system}, emu_window{window}, screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE), global_cache{*this} { // Create sampler objects for (std::size_t i = 0; i < texture_samplers.size(); ++i) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index ed7091f18..ebabf80d1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -33,6 +33,10 @@ #include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/gl_stream_buffer.h" +namespace Core { +class System; +} + namespace Core::Frontend { class EmuWindow; } @@ -45,7 +49,8 @@ struct FramebufferCacheKey; class RasterizerOpenGL : public VideoCore::RasterizerInterface { public: - explicit RasterizerOpenGL(Core::Frontend::EmuWindow& renderer, ScreenInfo& info); + explicit RasterizerOpenGL(Core::Frontend::EmuWindow& window, Core::System& system, + ScreenInfo& info); ~RasterizerOpenGL() override; void DrawArrays() override; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 6acfd1649..b2b5c2aa5 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -342,7 +342,8 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode, return {unique_identifier, base_bindings, primitive_mode}; } -ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} {} +ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system) + : RasterizerCache{rasterizer}, disk_cache{system} {} void ShaderCacheOpenGL::LoadDiskCache() { const auto transferable = disk_cache.LoadTransferable(); diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index c6a621ae3..6914127c3 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -20,6 +20,10 @@ #include "video_core/renderer_opengl/gl_shader_disk_cache.h" #include "video_core/renderer_opengl/gl_shader_gen.h" +namespace Core { +class System; +} // namespace Core + namespace OpenGL { class CachedShader; @@ -107,7 +111,7 @@ private: class ShaderCacheOpenGL final : public RasterizerCache { public: - explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer); + explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system); /// Loads disk cache for the current game void LoadDiskCache(); 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 f8bdb7779..d88fff388 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -43,9 +43,6 @@ static_assert(sizeof(BaseBindings) == 12); static_assert(sizeof(ShaderDiskCacheUsage) == 24); namespace { -std::string GetTitleID() { - return fmt::format("{:016X}", Core::CurrentProcess()->GetTitleID()); -} ShaderCacheVersionHash GetShaderCacheVersionHash() { ShaderCacheVersionHash hash{}; @@ -82,6 +79,7 @@ std::vector DecompressData(const std::vector& compressed, std::size_t un } return uncompressed; } + } // namespace ShaderDiskCacheRaw::ShaderDiskCacheRaw(u64 unique_identifier, Maxwell::ShaderProgram program_type, @@ -137,9 +135,13 @@ bool ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const { return true; } +ShaderDiskCacheOpenGL::ShaderDiskCacheOpenGL(Core::System& system) : system{system} {} + std::optional, std::vector>> ShaderDiskCacheOpenGL::LoadTransferable() { - if (!Settings::values.use_disk_shader_cache) + // Skip games without title id + const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0; + if (!Settings::values.use_disk_shader_cache || !has_title_id) return {}; tried_to_load = true; @@ -643,4 +645,8 @@ std::string ShaderDiskCacheOpenGL::GetBaseDir() const { return FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir) + DIR_SEP "opengl"; } +std::string ShaderDiskCacheOpenGL::GetTitleID() const { + return fmt::format("{:016X}", system.CurrentProcess()->GetTitleID()); +} + } // namespace OpenGL \ No newline at end of file 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 ddcd4cf51..061c4f204 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.h @@ -18,9 +18,13 @@ #include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_opengl/gl_shader_gen.h" +namespace Core { +class System; +} + namespace FileUtil { class IOFile; -} // namespace FileUtil +} namespace OpenGL { @@ -148,6 +152,8 @@ struct ShaderDiskCacheDump { class ShaderDiskCacheOpenGL { public: + explicit ShaderDiskCacheOpenGL(Core::System& system); + /// Loads transferable cache. If file has a old version or on failure, it deletes the file. std::optional, std::vector>> LoadTransferable(); @@ -217,6 +223,11 @@ private: /// Get user's shader directory path std::string GetBaseDir() const; + /// Get current game's title id + std::string GetTitleID() const; + + // Copre system + Core::System& system; // Stored transferable shaders std::map> transferable; // The cache has been loaded at boot diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 5b09c38ea..6476a9e1a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -98,8 +98,8 @@ static std::array MakeOrthographicMatrix(const float width, cons return matrix; } -RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window) - : VideoCore::RendererBase{window} {} +RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window, Core::System& system) + : VideoCore::RendererBase{window}, system{system} {} RendererOpenGL::~RendererOpenGL() = default; @@ -250,7 +250,7 @@ void RendererOpenGL::CreateRasterizer() { } // Initialize sRGB Usage OpenGLState::ClearsRGBUsed(); - rasterizer = std::make_unique(render_window, screen_info); + rasterizer = std::make_unique(render_window, system, screen_info); } void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 1665018db..7e13e566b 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -12,6 +12,10 @@ #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_state.h" +namespace Core { +class System; +} + namespace Core::Frontend { class EmuWindow; } @@ -41,7 +45,7 @@ struct ScreenInfo { class RendererOpenGL : public VideoCore::RendererBase { public: - explicit RendererOpenGL(Core::Frontend::EmuWindow& window); + explicit RendererOpenGL(Core::Frontend::EmuWindow& window, Core::System& system); ~RendererOpenGL() override; /// Swap buffers (render frame) @@ -72,6 +76,8 @@ private: void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture); + Core::System& system; + OpenGLState state; // OpenGL object IDs diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 0b8ccdd44..cb82ecf3f 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -11,8 +11,9 @@ namespace VideoCore { -std::unique_ptr CreateRenderer(Core::Frontend::EmuWindow& emu_window) { - return std::make_unique(emu_window); +std::unique_ptr CreateRenderer(Core::Frontend::EmuWindow& emu_window, + Core::System& system) { + return std::make_unique(emu_window, system); } u16 GetResolutionScaleFactor(const RendererBase& renderer) { diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 5b373bcb1..3c583f195 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -6,6 +6,10 @@ #include +namespace Core { +class System; +} + namespace Core::Frontend { class EmuWindow; } @@ -20,7 +24,8 @@ class RendererBase; * @note The returned renderer instance is simply allocated. Its Init() * function still needs to be called to fully complete its setup. */ -std::unique_ptr CreateRenderer(Core::Frontend::EmuWindow& emu_window); +std::unique_ptr CreateRenderer(Core::Frontend::EmuWindow& emu_window, + Core::System& system); u16 GetResolutionScaleFactor(const RendererBase& renderer); -- cgit v1.2.3 From eb7324743372d3b94db9a915a5508d8293d45ecb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 21 Jan 2019 16:38:23 -0300 Subject: gl_shader_cache: Link loading screen with disk shader cache load --- src/core/core.cpp | 2 -- src/video_core/rasterizer_interface.h | 4 ++- src/video_core/renderer_opengl/gl_rasterizer.cpp | 7 +++--- src/video_core/renderer_opengl/gl_rasterizer.h | 4 ++- src/video_core/renderer_opengl/gl_shader_cache.cpp | 29 +++++++++++++++++++--- src/video_core/renderer_opengl/gl_shader_cache.h | 5 +++- src/yuzu/bootmanager.cpp | 9 +++++++ src/yuzu/bootmanager.h | 8 +++++- src/yuzu/main.cpp | 3 +++ src/yuzu_cmd/yuzu.cpp | 3 +++ 10 files changed, 62 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/core.cpp b/src/core/core.cpp index 1d71312aa..1dd576c26 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -176,8 +176,6 @@ struct System::Impl { static_cast(load_result)); } - renderer->Rasterizer().LoadDiskResources(); - status = ResultStatus::Success; return status; } diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index bb4bc0e36..77da135a0 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "common/common_types.h" #include "video_core/engines/fermi_2d.h" @@ -63,6 +64,7 @@ public: virtual void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) {} /// Initialize disk cached resources for the game being emulated - virtual void LoadDiskResources() {} + virtual void LoadDiskResources(const std::atomic_bool& stop_loading = false, + const DiskResourceLoadCallback& callback = {}) {} }; } // namespace VideoCore diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 94a5058de..974ca6a20 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -449,7 +449,7 @@ static constexpr auto RangeFromInterval(Map& map, const Interval& interval) { return boost::make_iterator_range(map.equal_range(interval)); } -void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { +void RasterizerOpenGL::UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) { const u64 page_start{addr >> Memory::PAGE_BITS}; const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS}; @@ -479,8 +479,9 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { cached_pages.add({pages_interval, delta}); } -void RasterizerOpenGL::LoadDiskResources() { - shader_cache.LoadDiskCache(); +void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading, + const VideoCore::DiskResourceLoadCallback& callback) { + shader_cache.LoadDiskCache(stop_loading, callback); } std::pair RasterizerOpenGL::ConfigureFramebuffers( diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index ebabf80d1..f3b607f4d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include @@ -65,7 +66,8 @@ public: u32 pixel_stride) override; bool AccelerateDrawBatch(bool is_indexed) override; void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) override; - void LoadDiskResources() override; + void LoadDiskResources(const std::atomic_bool& stop_loading, + const VideoCore::DiskResourceLoadCallback& callback) override; /// Maximum supported size that a constbuffer can have in bytes. static constexpr std::size_t MaxConstbufferSize = 0x10000; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 7eeae082a..e0e624e6f 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -345,7 +345,8 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode, ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system) : RasterizerCache{rasterizer}, disk_cache{system} {} -void ShaderCacheOpenGL::LoadDiskCache() { +void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, + const VideoCore::DiskResourceLoadCallback& callback) { const auto transferable = disk_cache.LoadTransferable(); if (!transferable) { return; @@ -355,10 +356,18 @@ void ShaderCacheOpenGL::LoadDiskCache() { auto [decompiled, dumps] = disk_cache.LoadPrecompiled(); const auto supported_formats{GetSupportedFormats()}; - const auto unspecialized{GenerateUnspecializedShaders(raws, decompiled)}; + const auto unspecialized{ + GenerateUnspecializedShaders(stop_loading, callback, raws, decompiled)}; + if (stop_loading) + return; // Build shaders + if (callback) + callback(VideoCore::LoadCallbackStage::Build, 0, usages.size()); for (std::size_t i = 0; i < usages.size(); ++i) { + if (stop_loading) + return; + const auto& usage{usages[i]}; LOG_INFO(Render_OpenGL, "Building shader {:016x} ({} of {})", usage.unique_identifier, i + 1, usages.size()); @@ -381,6 +390,9 @@ void ShaderCacheOpenGL::LoadDiskCache() { usage.bindings, usage.primitive, true); } precompiled_programs.insert({usage, std::move(shader)}); + + if (callback) + callback(VideoCore::LoadCallbackStage::Build, i + 1, usages.size()); } // TODO(Rodrigo): Do state tracking for transferable shaders and do a dummy draw before @@ -420,11 +432,19 @@ CachedProgram ShaderCacheOpenGL::GeneratePrecompiledProgram( } std::map ShaderCacheOpenGL::GenerateUnspecializedShaders( + const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback, const std::vector& raws, const std::map& decompiled) { std::map unspecialized; - for (const auto& raw : raws) { + if (callback) + callback(VideoCore::LoadCallbackStage::Decompile, 0, raws.size()); + + for (std::size_t i = 0; i < raws.size(); ++i) { + if (stop_loading) + return {}; + + const auto& raw{raws[i]}; const u64 unique_identifier = raw.GetUniqueIdentifier(); const u64 calculated_hash = GetUniqueIdentifier(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB()); @@ -454,6 +474,9 @@ std::map ShaderCacheOpenGL::GenerateUnspecializedShade unspecialized.insert( {raw.GetUniqueIdentifier(), {std::move(result.first), std::move(result.second), raw.GetProgramType()}}); + + if (callback) + callback(VideoCore::LoadCallbackStage::Decompile, i, raws.size()); } return unspecialized; } diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 6914127c3..9c6b19fc3 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -15,6 +15,7 @@ #include "common/assert.h" #include "common/common_types.h" #include "video_core/rasterizer_cache.h" +#include "video_core/renderer_base.h" #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_shader_decompiler.h" #include "video_core/renderer_opengl/gl_shader_disk_cache.h" @@ -114,13 +115,15 @@ public: explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system); /// Loads disk cache for the current game - void LoadDiskCache(); + void LoadDiskCache(const std::atomic_bool& stop_loading, + const VideoCore::DiskResourceLoadCallback& callback); /// Gets the current specified shader stage program Shader GetStageProgram(Maxwell::ShaderProgram program); private: std::map GenerateUnspecializedShaders( + const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback, const std::vector& raws, const std::map& decompiled); diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index f74cb693a..73b04b749 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -29,6 +29,15 @@ void EmuThread::run() { stop_run = false; + emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); + + Core::System::GetInstance().Renderer().Rasterizer().LoadDiskResources( + stop_run, [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { + emit LoadProgress(stage, value, total); + }); + + emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0); + // holds whether the cpu was running during the last iteration, // so that the DebugModeLeft signal can be emitted before the // next execution step diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index d1f37e503..7226e690e 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -22,6 +22,10 @@ class GGLWidgetInternal; class GMainWindow; class GRenderWindow; +namespace VideoCore { +enum class LoadCallbackStage; +} + class EmuThread : public QThread { Q_OBJECT @@ -75,7 +79,7 @@ public: private: bool exec_step = false; bool running = false; - std::atomic stop_run{false}; + std::atomic_bool stop_run{false}; std::mutex running_mutex; std::condition_variable running_cv; @@ -101,6 +105,8 @@ signals: void DebugModeLeft(); void ErrorThrown(Core::System::ResultStatus, std::string); + + void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total); }; class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 485e29de2..1d460c189 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -887,6 +887,9 @@ void GMainWindow::BootGame(const QString& filename) { connect(emu_thread.get(), &EmuThread::DebugModeLeft, waitTreeWidget, &WaitTreeWidget::OnDebugModeLeft, Qt::BlockingQueuedConnection); + connect(emu_thread.get(), &EmuThread::LoadProgress, loading_screen, + &LoadingScreen::OnLoadProgress, Qt::QueuedConnection); + // Update the GUI if (ui.action_Single_Window_Mode->isChecked()) { game_list->hide(); diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 806127b12..c34b5467f 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -28,6 +28,7 @@ #include "core/loader/loader.h" #include "core/settings.h" #include "core/telemetry_session.h" +#include "video_core/renderer_base.h" #include "yuzu_cmd/config.h" #include "yuzu_cmd/emu_window/emu_window_sdl2.h" @@ -217,6 +218,8 @@ int main(int argc, char** argv) { Core::Telemetry().AddField(Telemetry::FieldType::App, "Frontend", "SDL"); + system.Renderer().Rasterizer().LoadDiskResources(); + while (emu_window->IsOpen()) { system.RunLoop(); } -- cgit v1.2.3