From dfd8ded206c87102022bb4d665b8943e659cffa9 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Mon, 27 Feb 2023 19:07:51 +0200 Subject: [PATCH] vk_pipeline_cache: Improve async pipeline android fallback * When VK_EXT_pipeline_creation_feedback is unavailable don't synchronously compile the pipeline, this is slow * Compile the pipeline asynchrounsly instead and have the record thread wait for it. This way we can have multiple pipelines compiling at once --- .../renderer_vulkan/vk_pipeline_cache.cpp | 42 ++++++++++--------- .../renderer_vulkan/vk_pipeline_cache.h | 5 ++- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 180591332..f2c0018f2 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -112,12 +112,12 @@ PipelineCache::Shader::~Shader() { PipelineCache::GraphicsPipeline::GraphicsPipeline( const Instance& instance_, RenderpassCache& renderpass_cache_, const PipelineInfo& info_, vk::PipelineCache pipeline_cache_, vk::PipelineLayout layout_, std::array stages_, - Common::ThreadWorker* worker_) + Common::ThreadWorker* worker_, bool& wait_built) : instance{instance_}, renderpass_cache{renderpass_cache_}, worker{worker_}, pipeline_layout{layout_}, pipeline_cache{pipeline_cache_}, info{info_}, stages{stages_} { // Ask the driver if it can give us the pipeline quickly - if (Build(true)) { + if (ShouldTryCompile(wait_built) && Build(true)) { return; } @@ -135,27 +135,29 @@ PipelineCache::GraphicsPipeline::~GraphicsPipeline() { } } -bool PipelineCache::GraphicsPipeline::Build(bool fail_on_compile_required) { - if (fail_on_compile_required) { - // Check if all shader modules are ready - for (auto& shader : stages) { - if (shader && !shader->IsDone()) { - return false; - } - } - - if (!instance.IsPipelineCreationCacheControlSupported()) { -#if ANDROID - // Many android devices do not support the above extension. - // To avoid having lots of flickering, if all shaders are - // ready compile the pipeline anyway. - return Build(); -#else +bool PipelineCache::GraphicsPipeline::ShouldTryCompile(bool& wait_built) { + // Check if all shader modules are ready + for (auto& shader : stages) { + if (shader && !shader->IsDone()) { return false; -#endif } } + if (!instance.IsPipelineCreationCacheControlSupported()) { +#ifdef ANDROID + // Many android devices do not support the above extension. + // To avoid having lots of flickering, if all shaders are + // ready compile the pipeline anyway and have the record thread + // wait for it. + wait_built = true; +#endif + return false; + } + + return true; +} + +bool PipelineCache::GraphicsPipeline::Build(bool fail_on_compile_required) { MICROPROFILE_SCOPE(Vulkan_Pipeline); const vk::Device device = instance.GetDevice(); @@ -485,7 +487,7 @@ bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) { if (new_pipeline) { it->second = std::make_unique( instance, renderpass_cache, info, pipeline_cache, desc_manager.GetPipelineLayout(), - current_shaders, &workers); + current_shaders, &workers, wait_built); } GraphicsPipeline* const pipeline{it->second.get()}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index e3769595f..625cf5d95 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -151,7 +151,7 @@ class PipelineCache { GraphicsPipeline(const Instance& instance, RenderpassCache& renderpass_cache, const PipelineInfo& info, vk::PipelineCache pipeline_cache, vk::PipelineLayout layout, std::array stages, - Common::ThreadWorker* worker); + Common::ThreadWorker* worker, bool& wait_built); ~GraphicsPipeline(); bool Build(bool fail_on_compile_required = false); @@ -160,6 +160,9 @@ class PipelineCache { return pipeline; } + private: + bool ShouldTryCompile(bool& wait_built); + private: const Instance& instance; RenderpassCache& renderpass_cache;