diff --git a/src/core/host_interface_progress_callback.cpp b/src/core/host_interface_progress_callback.cpp index d53a097c9..6bb0295f9 100644 --- a/src/core/host_interface_progress_callback.cpp +++ b/src/core/host_interface_progress_callback.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "host_interface_progress_callback.h" @@ -60,6 +60,9 @@ void HostInterfaceProgressCallback::SetProgressValue(u32 value) void HostInterfaceProgressCallback::Redraw(bool force) { + if (m_last_progress_percent < 0 && m_open_time.GetTimeSeconds() < m_open_delay) + return; + const int percent = static_cast((static_cast(m_progress_value) / static_cast(m_progress_range)) * 100.0f); if (percent == m_last_progress_percent && !force) diff --git a/src/core/host_interface_progress_callback.h b/src/core/host_interface_progress_callback.h index 22afce997..9b96b2867 100644 --- a/src/core/host_interface_progress_callback.h +++ b/src/core/host_interface_progress_callback.h @@ -1,14 +1,18 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once + #include "common/progress_callback.h" +#include "common/timer.h" class HostInterfaceProgressCallback final : public BaseProgressCallback { public: HostInterfaceProgressCallback(); + ALWAYS_INLINE void SetOpenDelay(float delay) { m_open_delay = delay; } + void PushState() override; void PopState() override; @@ -26,9 +30,11 @@ public: void ModalError(const char* message) override; bool ModalConfirmation(const char* message) override; void ModalInformation(const char* message) override; - + private: void Redraw(bool force); + Common::Timer m_open_time; + float m_open_delay = 1.0f; int m_last_progress_percent = -1; }; diff --git a/src/util/postprocessing.cpp b/src/util/postprocessing.cpp index 70d2c8d5f..67fa86943 100644 --- a/src/util/postprocessing.cpp +++ b/src/util/postprocessing.cpp @@ -11,6 +11,7 @@ // TODO: Remove me #include "core/host.h" +#include "core/host_interface_progress_callback.h" #include "core/settings.h" #include "IconsFontAwesome5.h" @@ -19,6 +20,7 @@ #include "common/file_system.h" #include "common/log.h" #include "common/path.h" +#include "common/progress_callback.h" #include "common/small_string.h" #include "common/string_util.h" #include "common/timer.h" @@ -464,6 +466,8 @@ void PostProcessing::LoadStages() return; Error error; + HostInterfaceProgressCallback progress; + progress.SetProgressRange(stage_count); for (u32 i = 0; i < stage_count; i++) { @@ -476,6 +480,7 @@ void PostProcessing::LoadStages() } lock.unlock(); + progress.SetFormattedStatusText("Loading shader %s...", stage_name.c_str()); std::unique_ptr shader = TryLoadingShader(stage_name, false, &error); if (!shader) @@ -487,6 +492,8 @@ void PostProcessing::LoadStages() lock.lock(); shader->LoadOptions(si, GetStageConfigSection(i)); s_stages.push_back(std::move(shader)); + + progress.IncrementProgressValue(); } if (stage_count > 0) @@ -494,6 +501,13 @@ void PostProcessing::LoadStages() s_timer.Reset(); Log_DevPrintf("Loaded %u post-processing stages.", stage_count); } + + // precompile shaders + if (g_gpu_device && g_gpu_device->GetWindowFormat() != GPUTexture::Format::Unknown) + { + CheckTargets(g_gpu_device->GetWindowFormat(), g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight(), + &progress); + } } void PostProcessing::UpdateSettings() @@ -514,6 +528,11 @@ void PostProcessing::UpdateSettings() s_stages.resize(stage_count); + HostInterfaceProgressCallback progress; + progress.SetProgressRange(stage_count); + + const GPUTexture::Format prev_format = s_target_format; + for (u32 i = 0; i < stage_count; i++) { std::string stage_name = Config::GetStageShaderName(si, i); @@ -552,6 +571,9 @@ void PostProcessing::UpdateSettings() s_stages[i]->LoadOptions(si, GetStageConfigSection(i)); } + if (prev_format != GPUTexture::Format::Unknown) + CheckTargets(prev_format, s_target_width, s_target_height, &progress); + if (stage_count > 0) { s_timer.Reset(); @@ -645,7 +667,8 @@ GPUTexture* PostProcessing::GetDummyTexture() return s_dummy_texture.get(); } -bool PostProcessing::CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height) +bool PostProcessing::CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height, + ProgressCallback* progress) { if (s_target_format == target_format && s_target_width == target_width && s_target_height == target_height) return true; @@ -661,9 +684,19 @@ bool PostProcessing::CheckTargets(GPUTexture::Format target_format, u32 target_w return false; } - for (auto& shader : s_stages) + if (!progress) + progress = ProgressCallback::NullProgressCallback; + + progress->SetProgressRange(static_cast(s_stages.size())); + progress->SetProgressValue(0); + + for (size_t i = 0; i < s_stages.size(); i++) { - if (!shader->CompilePipeline(target_format, target_width, target_height) || + Shader* const shader = s_stages[i].get(); + + progress->SetFormattedStatusText("Compiling %s...", shader->GetName().c_str()); + + if (!shader->CompilePipeline(target_format, target_width, target_height, progress) || !shader->ResizeOutput(target_format, target_width, target_height)) { Log_ErrorPrintf("Failed to compile one or more post-processing shaders, disabling."); @@ -673,6 +706,8 @@ bool PostProcessing::CheckTargets(GPUTexture::Format target_format, u32 target_w s_enabled = false; return false; } + + progress->SetProgressValue(static_cast(i + 1)); } s_target_format = target_format; @@ -696,12 +731,6 @@ bool PostProcessing::Apply(GPUTexture* final_target, s32 final_left, s32 final_t { GL_SCOPE("PostProcessing Apply"); - const u32 target_width = final_target ? final_target->GetWidth() : g_gpu_device->GetWindowWidth(); - const u32 target_height = final_target ? final_target->GetHeight() : g_gpu_device->GetWindowHeight(); - const GPUTexture::Format target_format = final_target ? final_target->GetFormat() : g_gpu_device->GetWindowFormat(); - if (!CheckTargets(target_format, target_width, target_height)) - return false; - GPUTexture* input = s_input_texture.get(); GPUTexture* output = s_output_texture.get(); input->MakeReadyForSampling(); diff --git a/src/util/postprocessing.h b/src/util/postprocessing.h index 53d740c12..fe1642e7d 100644 --- a/src/util/postprocessing.h +++ b/src/util/postprocessing.h @@ -19,6 +19,7 @@ class GPUTexture; class Error; class SettingsInterface; +class ProgressCallback; namespace PostProcessing { struct ShaderOption @@ -124,7 +125,7 @@ void Shutdown(); GPUTexture* GetInputTexture(); const Common::Timer& GetTimer(); -bool CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height); +bool CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height, ProgressCallback* progress = nullptr); bool Apply(GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width, s32 orig_height); diff --git a/src/util/postprocessing_shader.h b/src/util/postprocessing_shader.h index 9358cf1a1..e53530d0e 100644 --- a/src/util/postprocessing_shader.h +++ b/src/util/postprocessing_shader.h @@ -20,6 +20,7 @@ class GPUPipeline; class GPUTexture; +class ProgressCallback; namespace PostProcessing { @@ -45,7 +46,7 @@ public: virtual bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height) = 0; - virtual bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height) = 0; + virtual bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) = 0; virtual bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, u32 target_width, u32 target_height) = 0; diff --git a/src/util/postprocessing_shader_fx.cpp b/src/util/postprocessing_shader_fx.cpp index 46f676a33..fb00f4f6c 100644 --- a/src/util/postprocessing_shader_fx.cpp +++ b/src/util/postprocessing_shader_fx.cpp @@ -15,6 +15,7 @@ #include "common/image.h" #include "common/log.h" #include "common/path.h" +#include "common/progress_callback.h" #include "common/string_util.h" #include "effect_codegen.hpp" @@ -1123,7 +1124,8 @@ GPUTexture* PostProcessing::ReShadeFXShader::GetTextureByID(TextureID id, GPUTex return m_textures[static_cast(id)].texture.get(); } -bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, u32 width, u32 height) +bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, u32 width, u32 height, + ProgressCallback* progress) { const RenderAPI api = g_gpu_device->GetRenderAPI(); const bool needs_main_defn = (api != RenderAPI::D3D11 && api != RenderAPI::D3D12); @@ -1219,6 +1221,14 @@ bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, plconfig.samples = 1; plconfig.per_sample_shading = false; + progress->PushState(); + + size_t total_passes = 0; + for (const reshadefx::technique_info& tech : mod.techniques) + total_passes += tech.passes.size(); + progress->SetProgressRange(static_cast(total_passes)); + progress->SetProgressValue(0); + u32 passnum = 0; for (const reshadefx::technique_info& tech : mod.techniques) { @@ -1230,7 +1240,10 @@ bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, auto vs = get_shader(info.vs_entry_point, pass.samplers, GPUShaderStage::Vertex); auto fs = get_shader(info.ps_entry_point, pass.samplers, GPUShaderStage::Fragment); if (!vs || !fs) + { + progress->PopState(); return false; + } for (size_t i = 0; i < pass.render_targets.size(); i++) { @@ -1247,17 +1260,25 @@ bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, plconfig.fragment_shader = fs.get(); plconfig.geometry_shader = nullptr; if (!plconfig.vertex_shader || !plconfig.fragment_shader) + { + progress->PopState(); return false; + } pass.pipeline = g_gpu_device->CreatePipeline(plconfig); if (!pass.pipeline) { Log_ErrorPrintf("Failed to create pipeline for pass '%s'", info.name.c_str()); + progress->PopState(); return false; } + + progress->SetProgressValue(passnum); } } + progress->PopState(); + m_valid = true; return true; } diff --git a/src/util/postprocessing_shader_fx.h b/src/util/postprocessing_shader_fx.h index c00c33aec..d6fa941f3 100644 --- a/src/util/postprocessing_shader_fx.h +++ b/src/util/postprocessing_shader_fx.h @@ -29,7 +29,7 @@ public: bool LoadFromString(std::string name, std::string filename, std::string code, bool only_config, Error* error); bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height) override; - bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height) override; + bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) override; bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, u32 target_width, u32 target_height) override; diff --git a/src/util/postprocessing_shader_glsl.cpp b/src/util/postprocessing_shader_glsl.cpp index bba75b3f4..a3f90c7af 100644 --- a/src/util/postprocessing_shader_glsl.cpp +++ b/src/util/postprocessing_shader_glsl.cpp @@ -112,7 +112,7 @@ void PostProcessing::GLSLShader::FillUniformBuffer(void* buffer, u32 texture_wid } } -bool PostProcessing::GLSLShader::CompilePipeline(GPUTexture::Format format, u32 width, u32 height) +bool PostProcessing::GLSLShader::CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) { if (m_pipeline) m_pipeline.reset(); diff --git a/src/util/postprocessing_shader_glsl.h b/src/util/postprocessing_shader_glsl.h index f4c2bf3bf..ec6d99ce3 100644 --- a/src/util/postprocessing_shader_glsl.h +++ b/src/util/postprocessing_shader_glsl.h @@ -22,7 +22,7 @@ public: bool LoadFromString(std::string name, std::string code, Error* error); bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height) override; - bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height) override; + bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) override; bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, u32 target_width, u32 target_height) override;