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
This commit is contained in:
GPUCode
2023-02-27 19:07:51 +02:00
parent 06caa535d6
commit dfd8ded206
2 changed files with 26 additions and 21 deletions

View File

@@ -112,12 +112,12 @@ PipelineCache::Shader::~Shader() {
PipelineCache::GraphicsPipeline::GraphicsPipeline( PipelineCache::GraphicsPipeline::GraphicsPipeline(
const Instance& instance_, RenderpassCache& renderpass_cache_, const PipelineInfo& info_, const Instance& instance_, RenderpassCache& renderpass_cache_, const PipelineInfo& info_,
vk::PipelineCache pipeline_cache_, vk::PipelineLayout layout_, std::array<Shader*, 3> stages_, vk::PipelineCache pipeline_cache_, vk::PipelineLayout layout_, std::array<Shader*, 3> stages_,
Common::ThreadWorker* worker_) Common::ThreadWorker* worker_, bool& wait_built)
: instance{instance_}, renderpass_cache{renderpass_cache_}, worker{worker_}, : instance{instance_}, renderpass_cache{renderpass_cache_}, worker{worker_},
pipeline_layout{layout_}, pipeline_cache{pipeline_cache_}, info{info_}, stages{stages_} { pipeline_layout{layout_}, pipeline_cache{pipeline_cache_}, info{info_}, stages{stages_} {
// Ask the driver if it can give us the pipeline quickly // Ask the driver if it can give us the pipeline quickly
if (Build(true)) { if (ShouldTryCompile(wait_built) && Build(true)) {
return; return;
} }
@@ -135,27 +135,29 @@ PipelineCache::GraphicsPipeline::~GraphicsPipeline() {
} }
} }
bool PipelineCache::GraphicsPipeline::Build(bool fail_on_compile_required) { bool PipelineCache::GraphicsPipeline::ShouldTryCompile(bool& wait_built) {
if (fail_on_compile_required) { // Check if all shader modules are ready
// Check if all shader modules are ready for (auto& shader : stages) {
for (auto& shader : stages) { if (shader && !shader->IsDone()) {
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
return false; 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); MICROPROFILE_SCOPE(Vulkan_Pipeline);
const vk::Device device = instance.GetDevice(); const vk::Device device = instance.GetDevice();
@@ -485,7 +487,7 @@ bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) {
if (new_pipeline) { if (new_pipeline) {
it->second = std::make_unique<GraphicsPipeline>( it->second = std::make_unique<GraphicsPipeline>(
instance, renderpass_cache, info, pipeline_cache, desc_manager.GetPipelineLayout(), instance, renderpass_cache, info, pipeline_cache, desc_manager.GetPipelineLayout(),
current_shaders, &workers); current_shaders, &workers, wait_built);
} }
GraphicsPipeline* const pipeline{it->second.get()}; GraphicsPipeline* const pipeline{it->second.get()};

View File

@@ -151,7 +151,7 @@ class PipelineCache {
GraphicsPipeline(const Instance& instance, RenderpassCache& renderpass_cache, GraphicsPipeline(const Instance& instance, RenderpassCache& renderpass_cache,
const PipelineInfo& info, vk::PipelineCache pipeline_cache, const PipelineInfo& info, vk::PipelineCache pipeline_cache,
vk::PipelineLayout layout, std::array<Shader*, 3> stages, vk::PipelineLayout layout, std::array<Shader*, 3> stages,
Common::ThreadWorker* worker); Common::ThreadWorker* worker, bool& wait_built);
~GraphicsPipeline(); ~GraphicsPipeline();
bool Build(bool fail_on_compile_required = false); bool Build(bool fail_on_compile_required = false);
@@ -160,6 +160,9 @@ class PipelineCache {
return pipeline; return pipeline;
} }
private:
bool ShouldTryCompile(bool& wait_built);
private: private:
const Instance& instance; const Instance& instance;
RenderpassCache& renderpass_cache; RenderpassCache& renderpass_cache;