From eb7324743372d3b94db9a915a5508d8293d45ecb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 21 Jan 2019 16:38:23 -0300 Subject: [PATCH] gl_shader_cache: Link loading screen with disk shader cache load --- src/core/core.cpp | 2 -- src/video_core/rasterizer_interface.h | 4 ++- .../renderer_opengl/gl_rasterizer.cpp | 7 +++-- .../renderer_opengl/gl_rasterizer.h | 4 ++- .../renderer_opengl/gl_shader_cache.cpp | 29 +++++++++++++++++-- .../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(-) 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(); }