diff --git a/engine/src/flutter/impeller/entity/contents/runtime_effect_contents.cc b/engine/src/flutter/impeller/entity/contents/runtime_effect_contents.cc index 116e7d4347..b1a5ee8efb 100644 --- a/engine/src/flutter/impeller/entity/contents/runtime_effect_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/runtime_effect_contents.cc @@ -52,6 +52,13 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, std::shared_ptr function = library->GetFunction( runtime_stage_->GetEntrypoint(), ShaderStage::kFragment); + if (function && runtime_stage_->IsDirty()) { + library->UnregisterFunction(runtime_stage_->GetEntrypoint(), + ShaderStage::kFragment); + + function = nullptr; + } + if (!function) { std::promise promise; auto future = promise.get_future(); @@ -79,6 +86,8 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, << runtime_stage_->GetEntrypoint() << ")"; return false; } + + runtime_stage_->SetClean(); } //-------------------------------------------------------------------------- diff --git a/engine/src/flutter/impeller/entity/entity_unittests.cc b/engine/src/flutter/impeller/entity/entity_unittests.cc index f8c2b07c5f..09dc2a4372 100644 --- a/engine/src/flutter/impeller/entity/entity_unittests.cc +++ b/engine/src/flutter/impeller/entity/entity_unittests.cc @@ -2142,12 +2142,21 @@ TEST_P(EntityTest, RuntimeEffect) { GTEST_SKIP_("This test only has a Metal fixture at the moment."); } + auto runtime_stage = + OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr"); + ASSERT_TRUE(runtime_stage->IsDirty()); + + bool first_frame = true; auto callback = [&](ContentContext& context, RenderPass& pass) -> bool { + if (first_frame) { + first_frame = false; + } else { + assert(runtime_stage->IsDirty() == false); + } + auto contents = std::make_shared(); contents->SetGeometry(Geometry::MakeCover()); - auto runtime_stage = - OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr"); contents->SetRuntimeStage(runtime_stage); struct FragUniforms { diff --git a/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc b/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc index c783ecdad1..919d374a3f 100644 --- a/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc +++ b/engine/src/flutter/impeller/runtime_stage/runtime_stage.cc @@ -144,4 +144,12 @@ RuntimeShaderStage RuntimeStage::GetShaderStage() const { return stage_; } +bool RuntimeStage::IsDirty() const { + return is_dirty_; +} + +void RuntimeStage::SetClean() { + is_dirty_ = false; +} + } // namespace impeller diff --git a/engine/src/flutter/impeller/runtime_stage/runtime_stage.h b/engine/src/flutter/impeller/runtime_stage/runtime_stage.h index 5bbdaa86a7..2c5eca0e3b 100644 --- a/engine/src/flutter/impeller/runtime_stage/runtime_stage.h +++ b/engine/src/flutter/impeller/runtime_stage/runtime_stage.h @@ -36,6 +36,10 @@ class RuntimeStage { const std::shared_ptr& GetSkSLMapping() const; + bool IsDirty() const; + + void SetClean(); + private: RuntimeShaderStage stage_ = RuntimeShaderStage::kVertex; std::shared_ptr payload_; @@ -44,6 +48,7 @@ class RuntimeStage { std::shared_ptr sksl_mapping_; std::vector uniforms_; bool is_valid_ = false; + bool is_dirty_ = true; FML_DISALLOW_COPY_AND_ASSIGN(RuntimeStage); };