diff --git a/fml/build_config.h b/fml/build_config.h index e1abd5c8dec42..d42a88e5bbce0 100644 --- a/fml/build_config.h +++ b/fml/build_config.h @@ -100,10 +100,4 @@ #error Please add support for your architecture in flutter/fml/build_config.h #endif -#if defined(FML_OS_IOS) -#if !defined(FML_OS_IOS_SIMULATOR) -#define FML_OS_PHYSICAL_IOS 1 -#endif -#endif - #endif // FLUTTER_FML_BUILD_CONFIG_H_ diff --git a/impeller/compiler/compiler.cc b/impeller/compiler/compiler.cc index 05be9d20133b3..38ea2a2b495ec 100644 --- a/impeller/compiler/compiler.cc +++ b/impeller/compiler/compiler.cc @@ -42,7 +42,7 @@ static uint32_t ParseMSLVersion(const std::string& msl_version) { } } } - if (major < 1 || minor < 2) { + if (major < 1 || (major == 1 && minor < 2)) { std::cerr << "--metal-version version must be at least 1.2. Have " << msl_version << std::endl; } diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 7507599a57e25..dd328219e6b17 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -77,26 +77,40 @@ impeller_shaders("modern_entity_shaders") { "shaders/radial_gradient_ssbo_fill.frag", "shaders/sweep_gradient_ssbo_fill.frag", ] - if (is_ios && !use_ios_simulator) { - shaders += [ - "shaders/blending/ios/framebuffer_blend.vert", - "shaders/blending/ios/framebuffer_blend_color.frag", - "shaders/blending/ios/framebuffer_blend_colorburn.frag", - "shaders/blending/ios/framebuffer_blend_colordodge.frag", - "shaders/blending/ios/framebuffer_blend_darken.frag", - "shaders/blending/ios/framebuffer_blend_difference.frag", - "shaders/blending/ios/framebuffer_blend_exclusion.frag", - "shaders/blending/ios/framebuffer_blend_hardlight.frag", - "shaders/blending/ios/framebuffer_blend_hue.frag", - "shaders/blending/ios/framebuffer_blend_lighten.frag", - "shaders/blending/ios/framebuffer_blend_luminosity.frag", - "shaders/blending/ios/framebuffer_blend_multiply.frag", - "shaders/blending/ios/framebuffer_blend_overlay.frag", - "shaders/blending/ios/framebuffer_blend_saturation.frag", - "shaders/blending/ios/framebuffer_blend_screen.frag", - "shaders/blending/ios/framebuffer_blend_softlight.frag", - ] +} + +impeller_shaders("framebuffer_blend_entity_shaders") { + name = "framebuffer_blend" + + if (is_mac && !is_ios) { + # Note: this needs to correspond to the Apple7 Support family + # for M1 and M2. + metal_version = "2.3" + } + + # This version is to disable malioc checks. + if (impeller_enable_opengles) { + gles_language_version = "460" } + + shaders = [ + "shaders/blending/ios/framebuffer_blend.vert", + "shaders/blending/ios/framebuffer_blend_color.frag", + "shaders/blending/ios/framebuffer_blend_colorburn.frag", + "shaders/blending/ios/framebuffer_blend_colordodge.frag", + "shaders/blending/ios/framebuffer_blend_darken.frag", + "shaders/blending/ios/framebuffer_blend_difference.frag", + "shaders/blending/ios/framebuffer_blend_exclusion.frag", + "shaders/blending/ios/framebuffer_blend_hardlight.frag", + "shaders/blending/ios/framebuffer_blend_hue.frag", + "shaders/blending/ios/framebuffer_blend_lighten.frag", + "shaders/blending/ios/framebuffer_blend_luminosity.frag", + "shaders/blending/ios/framebuffer_blend_multiply.frag", + "shaders/blending/ios/framebuffer_blend_overlay.frag", + "shaders/blending/ios/framebuffer_blend_saturation.frag", + "shaders/blending/ios/framebuffer_blend_screen.frag", + "shaders/blending/ios/framebuffer_blend_softlight.frag", + ] } impeller_component("entity") { @@ -143,6 +157,8 @@ impeller_component("entity") { "contents/filters/srgb_to_linear_filter_contents.h", "contents/filters/yuv_to_rgb_filter_contents.cc", "contents/filters/yuv_to_rgb_filter_contents.h", + "contents/framebuffer_blend_contents.cc", + "contents/framebuffer_blend_contents.h", "contents/gradient_generator.cc", "contents/gradient_generator.h", "contents/linear_gradient_contents.cc", @@ -179,15 +195,9 @@ impeller_component("entity") { "inline_pass_context.h", ] - if (is_ios && !use_ios_simulator) { - sources += [ - "contents/framebuffer_blend_contents.cc", - "contents/framebuffer_blend_contents.h", - ] - } - public_deps = [ ":entity_shaders", + ":framebuffer_blend_entity_shaders", ":modern_entity_shaders", "../archivist", "../image", diff --git a/impeller/entity/contents/atlas_contents.cc b/impeller/entity/contents/atlas_contents.cc index cb636e89fb4d2..f1a82ef6616df 100644 --- a/impeller/entity/contents/atlas_contents.cc +++ b/impeller/entity/contents/atlas_contents.cc @@ -12,6 +12,7 @@ #include "impeller/entity/contents/content_context.h" #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/framebuffer_blend_contents.h" #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity.h" #include "impeller/entity/geometry.h" @@ -22,10 +23,6 @@ #include "impeller/renderer/sampler_library.h" #include "impeller/renderer/vertex_buffer_builder.h" -#ifdef FML_OS_PHYSICAL_IOS -#include "impeller/entity/contents/framebuffer_blend_contents.h" -#endif - namespace impeller { AtlasContents::AtlasContents() = default; @@ -224,38 +221,39 @@ bool AtlasContents::Render(const ContentContext& renderer, dst_contents->SetSubAtlas(sub_atlas); dst_contents->SetCoverage(sub_coverage); -#ifdef FML_OS_PHYSICAL_IOS - auto new_texture = renderer.MakeSubpass( - "Atlas Blend", sub_atlas->size, - [&](const ContentContext& context, RenderPass& pass) { - Entity entity; - entity.SetContents(dst_contents); - entity.SetBlendMode(BlendMode::kSource); - if (!entity.Render(context, pass)) { - return false; - } - if (blend_mode_ >= Entity::kLastPipelineBlendMode) { - auto contents = std::make_shared(); - contents->SetBlendMode(blend_mode_); - contents->SetChildContents(src_contents); - entity.SetContents(std::move(contents)); + std::shared_ptr new_texture; + if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) { + new_texture = renderer.MakeSubpass( + "Atlas Blend", sub_atlas->size, + [&](const ContentContext& context, RenderPass& pass) { + Entity entity; + entity.SetContents(dst_contents); entity.SetBlendMode(BlendMode::kSource); + if (!entity.Render(context, pass)) { + return false; + } + if (blend_mode_ >= Entity::kLastPipelineBlendMode) { + auto contents = std::make_shared(); + contents->SetBlendMode(blend_mode_); + contents->SetChildContents(src_contents); + entity.SetContents(std::move(contents)); + entity.SetBlendMode(BlendMode::kSource); + return entity.Render(context, pass); + } + entity.SetContents(src_contents); + entity.SetBlendMode(blend_mode_); return entity.Render(context, pass); - } - entity.SetContents(src_contents); - entity.SetBlendMode(blend_mode_); - return entity.Render(context, pass); - }); -#else - auto contents = ColorFilterContents::MakeBlend( - blend_mode_, - {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)}); - auto snapshot = contents->RenderToSnapshot(renderer, entity); - if (!snapshot.has_value()) { - return false; + }); + } else { + auto contents = ColorFilterContents::MakeBlend( + blend_mode_, + {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)}); + auto snapshot = contents->RenderToSnapshot(renderer, entity); + if (!snapshot.has_value()) { + return false; + } + new_texture = snapshot.value().texture; } - auto new_texture = snapshot.value().texture; -#endif auto child_contents = AtlasTextureContents(*this); child_contents.SetAlpha(alpha_); diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index e15058d5fb330..fcbead26b251c 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -183,6 +183,38 @@ ContentContext::ContentContext(std::shared_ptr context) sweep_gradient_ssbo_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); } + if (context_->GetDeviceCapabilities().SupportsFramebufferFetch()) { + framebuffer_blend_color_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_colorburn_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_colordodge_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_darken_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_difference_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_exclusion_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_hardlight_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_hue_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_lighten_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_luminosity_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_multiply_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_overlay_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_saturation_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_screen_pipelines_[{}] = + CreateDefaultPipeline(*context_); + framebuffer_blend_softlight_pipelines_[{}] = + CreateDefaultPipeline(*context_); + } blend_color_pipelines_[{}] = CreateDefaultPipeline(*context_); @@ -213,39 +245,6 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); blend_softlight_pipelines_[{}] = CreateDefaultPipeline(*context_); -#if FML_OS_PHYSICAL_IOS - framebuffer_blend_color_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_colorburn_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_colordodge_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_darken_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_difference_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_exclusion_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_hardlight_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_hue_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_lighten_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_luminosity_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_multiply_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_overlay_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_saturation_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_screen_pipelines_[{}] = - CreateDefaultPipeline(*context_); - framebuffer_blend_softlight_pipelines_[{}] = - CreateDefaultPipeline(*context_); -#endif // FML_OS_PHYSICAL_IOS - sweep_gradient_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); rrect_blur_pipelines_[{}] = diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index fdad286a4016c..72c11360cf8f3 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -78,7 +78,7 @@ #include "impeller/entity/advanced_blend_saturation.frag.h" #include "impeller/entity/advanced_blend_screen.frag.h" #include "impeller/entity/advanced_blend_softlight.frag.h" -#if FML_OS_PHYSICAL_IOS + #include "impeller/entity/framebuffer_blend.vert.h" #include "impeller/entity/framebuffer_blend_color.frag.h" #include "impeller/entity/framebuffer_blend_colorburn.frag.h" @@ -95,7 +95,6 @@ #include "impeller/entity/framebuffer_blend_saturation.frag.h" #include "impeller/entity/framebuffer_blend_screen.frag.h" #include "impeller/entity/framebuffer_blend_softlight.frag.h" -#endif // FML_OS_PHYSICAL_IOS namespace impeller { @@ -202,8 +201,7 @@ using BlendScreenPipeline = RenderPipelineT; -#if FML_OS_PHYSICAL_IOS -// iOS only advanced blends. +// Framebuffer Advanced Blends using FramebufferBlendColorPipeline = RenderPipelineT; @@ -249,7 +247,6 @@ using FramebufferBlendScreenPipeline = using FramebufferBlendSoftLightPipeline = RenderPipelineT; -#endif // FML_OS_PHYSICAL_IOS /// Pipeline state configuration. /// @@ -516,83 +513,97 @@ class ContentContext { ContentContextOptions opts) const { return GetPipeline(blend_softlight_pipelines_, opts); } -#if FML_OS_PHYSICAL_IOS - // iOS advanced blends. + + // Framebuffer Advanced Blends std::shared_ptr> GetFramebufferBlendColorPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_color_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendColorBurnPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_colorburn_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendColorDodgePipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_colordodge_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendDarkenPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_darken_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendDifferencePipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_difference_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendExclusionPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_exclusion_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendHardLightPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_hardlight_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendHuePipeline( ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_hue_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendLightenPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_lighten_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendLuminosityPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_luminosity_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendMultiplyPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_multiply_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendOverlayPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_overlay_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendSaturationPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_saturation_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendScreenPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_screen_pipelines_, opts); } std::shared_ptr> GetFramebufferBlendSoftLightPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); return GetPipeline(framebuffer_blend_softlight_pipelines_, opts); } -#endif // FML_OS_PHYSICAL_IOS std::shared_ptr GetContext() const; @@ -669,7 +680,7 @@ class ContentContext { mutable Variants blend_saturation_pipelines_; mutable Variants blend_screen_pipelines_; mutable Variants blend_softlight_pipelines_; -#if FML_OS_PHYSICAL_IOS + // Framebuffer Advanced blends. mutable Variants framebuffer_blend_color_pipelines_; mutable Variants @@ -700,7 +711,6 @@ class ContentContext { framebuffer_blend_screen_pipelines_; mutable Variants framebuffer_blend_softlight_pipelines_; -#endif // FML_OS_PHYSICAL_IOS template std::shared_ptr> GetPipeline( diff --git a/impeller/entity/contents/framebuffer_blend_contents.cc b/impeller/entity/contents/framebuffer_blend_contents.cc index 3943adba77abe..7b2699ce4f453 100644 --- a/impeller/entity/contents/framebuffer_blend_contents.cc +++ b/impeller/entity/contents/framebuffer_blend_contents.cc @@ -32,6 +32,10 @@ std::optional FramebufferBlendContents::GetCoverage( bool FramebufferBlendContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { + if (!renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) { + return false; + } + using VS = FramebufferBlendScreenPipeline::VertexShader; using FS = FramebufferBlendScreenPipeline::FragmentShader; diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 23e7f861085c1..487c56d063976 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -16,9 +16,7 @@ #include "impeller/entity/contents/content_context.h" #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" -#if FML_OS_PHYSICAL_IOS #include "impeller/entity/contents/framebuffer_blend_contents.h" -#endif #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity.h" #include "impeller/entity/inline_pass_context.h" @@ -44,12 +42,9 @@ void EntityPass::SetDelegate(std::unique_ptr delegate) { } void EntityPass::AddEntity(Entity entity) { -#ifndef FML_OS_PHYSICAL_IOS if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) { - reads_from_pass_texture_ += 1; + blend_reads_from_pass_texture_ += 1; } -#endif - elements_.emplace_back(std::move(entity)); } @@ -135,16 +130,12 @@ EntityPass* EntityPass::AddSubpass(std::unique_ptr pass) { FML_DCHECK(pass->superpass_ == nullptr); pass->superpass_ = this; -#if FML_OS_PHYSICAL_IOS if (pass->backdrop_filter_proc_.has_value()) { - reads_from_pass_texture_ += 1; + filter_reads_from_pass_texture_ += 1; } -#else - if (pass->blend_mode_ > Entity::kLastPipelineBlendMode || - pass->backdrop_filter_proc_.has_value()) { - reads_from_pass_texture_ += 1; + if (pass->blend_mode_ > Entity::kLastPipelineBlendMode) { + blend_reads_from_pass_texture_ += 1; } -#endif auto subpass_pointer = pass.get(); elements_.emplace_back(std::move(pass)); @@ -199,9 +190,15 @@ static RenderTarget CreateRenderTarget(ContentContext& renderer, ); } +uint32_t EntityPass::ComputeTotalReads(ContentContext& renderer) const { + return renderer.GetDeviceCapabilities().SupportsFramebufferFetch() + ? filter_reads_from_pass_texture_ + : filter_reads_from_pass_texture_ + blend_reads_from_pass_texture_; +} + bool EntityPass::Render(ContentContext& renderer, const RenderTarget& render_target) const { - if (reads_from_pass_texture_ > 0) { + if (ComputeTotalReads(renderer) > 0) { auto offscreen_target = CreateRenderTarget(renderer, render_target.GetRenderTargetSize(), true); if (!OnRender(renderer, offscreen_target.GetRenderTargetSize(), @@ -357,7 +354,7 @@ EntityPass::EntityResult EntityPass::GetEntityForElement( auto subpass_target = CreateRenderTarget(renderer, // ISize(subpass_coverage->size), // - subpass->reads_from_pass_texture_ > 0); + subpass->ComputeTotalReads(renderer) > 0); auto subpass_texture = subpass_target.GetRenderTargetTexture(); @@ -420,7 +417,7 @@ bool EntityPass::OnRender(ContentContext& renderer, auto context = renderer.GetContext(); InlinePassContext pass_context(context, render_target, - reads_from_pass_texture_, + ComputeTotalReads(renderer), std::move(collapsed_parent_pass)); if (!pass_context.IsValid()) { return false; @@ -552,46 +549,45 @@ bool EntityPass::OnRender(ContentContext& renderer, /// if (result.entity.GetBlendMode() > Entity::kLastPipelineBlendMode) { -#if FML_OS_PHYSICAL_IOS - auto src_contents = result.entity.GetContents(); - auto contents = std::make_shared(); - contents->SetChildContents(src_contents); - contents->SetBlendMode(result.entity.GetBlendMode()); - result.entity.SetContents(std::move(contents)); - result.entity.SetBlendMode(BlendMode::kSource); - -#else - // End the active pass and flush the buffer before rendering "advanced" - // blends. Advanced blends work by binding the current render target - // texture as an input ("destination"), blending with a second texture - // input ("source"), writing the result to an intermediate texture, and - // finally copying the data from the intermediate texture back to the - // render target texture. And so all of the commands that have written - // to the render target texture so far need to execute before it's bound - // for blending (otherwise the blend pass will end up executing before - // all the previous commands in the active pass). - - if (!pass_context.EndPass()) { - return false; - } + if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) { + auto src_contents = result.entity.GetContents(); + auto contents = std::make_shared(); + contents->SetChildContents(src_contents); + contents->SetBlendMode(result.entity.GetBlendMode()); + result.entity.SetContents(std::move(contents)); + result.entity.SetBlendMode(BlendMode::kSource); + } else { + // End the active pass and flush the buffer before rendering "advanced" + // blends. Advanced blends work by binding the current render target + // texture as an input ("destination"), blending with a second texture + // input ("source"), writing the result to an intermediate texture, and + // finally copying the data from the intermediate texture back to the + // render target texture. And so all of the commands that have written + // to the render target texture so far need to execute before it's bound + // for blending (otherwise the blend pass will end up executing before + // all the previous commands in the active pass). + + if (!pass_context.EndPass()) { + return false; + } - // Amend an advanced blend filter to the contents, attaching the pass - // texture. - auto texture = pass_context.GetTexture(); - if (!texture) { - return false; - } + // Amend an advanced blend filter to the contents, attaching the pass + // texture. + auto texture = pass_context.GetTexture(); + if (!texture) { + return false; + } - FilterInput::Vector inputs = { - FilterInput::Make(texture, - result.entity.GetTransformation().Invert()), - FilterInput::Make(result.entity.GetContents())}; - auto contents = - ColorFilterContents::MakeBlend(result.entity.GetBlendMode(), inputs); - contents->SetCoverageCrop(result.entity.GetCoverage()); - result.entity.SetContents(std::move(contents)); - result.entity.SetBlendMode(BlendMode::kSource); -#endif // FML_OS_PHYSICAL_IOS + FilterInput::Vector inputs = { + FilterInput::Make(texture, + result.entity.GetTransformation().Invert()), + FilterInput::Make(result.entity.GetContents())}; + auto contents = ColorFilterContents::MakeBlend( + result.entity.GetBlendMode(), inputs); + contents->SetCoverageCrop(result.entity.GetCoverage()); + result.entity.SetContents(std::move(contents)); + result.entity.SetBlendMode(BlendMode::kSource); + } } //-------------------------------------------------------------------------- diff --git a/impeller/entity/entity_pass.h b/impeller/entity/entity_pass.h index d15beab319429..c958420157d13 100644 --- a/impeller/entity/entity_pass.h +++ b/impeller/entity/entity_pass.h @@ -118,12 +118,18 @@ class EntityPass { BlendMode blend_mode_ = BlendMode::kSourceOver; bool cover_whole_screen_ = false; - /// This value is incremented whenever something is added to the pass that + /// These value are incremented whenever something is added to the pass that /// requires reading from the backdrop texture. Currently, this can happen in /// the following scenarios: /// 1. An entity with an "advanced blend" is added to the pass. /// 2. A subpass with a backdrop filter is added to the pass. - uint32_t reads_from_pass_texture_ = 0; + /// These are tracked as separate values because we may ignore + /// blend_reads_from_pass_texture_ if the device supports framebuffer based + /// advanced blends. + uint32_t filter_reads_from_pass_texture_ = 0; + uint32_t blend_reads_from_pass_texture_ = 0; + + uint32_t ComputeTotalReads(ContentContext& renderer) const; std::optional backdrop_filter_proc_ = std::nullopt; diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl b/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl index 391b2841905b5..06324909a6af5 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl @@ -9,7 +9,7 @@ #include #include -#ifdef IMPELLER_TARGET_METAL_IOS +#ifdef IMPELLER_TARGET_METAL layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInput uSub; diff --git a/impeller/playground/BUILD.gn b/impeller/playground/BUILD.gn index b6c26fcad9e2b..623b0d2557b9e 100644 --- a/impeller/playground/BUILD.gn +++ b/impeller/playground/BUILD.gn @@ -40,6 +40,7 @@ impeller_component("playground") { public_deps = [ "../entity:entity_shaders", + "../entity:framebuffer_blend_entity_shaders", "../entity:modern_entity_shaders", "../fixtures:shader_fixtures", "../renderer", diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index 1e900d7da7bdd..2418d1dae7c9a 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -15,6 +15,7 @@ #include "flutter/fml/mapping.h" #include "impeller/entity/mtl/entity_shaders.h" +#include "impeller/entity/mtl/framebuffer_blend_shaders.h" #include "impeller/entity/mtl/modern_shaders.h" #include "impeller/fixtures/mtl/fixtures_shaders.h" #include "impeller/fixtures/mtl/subgroup_fixtures_shaders.h" @@ -38,6 +39,9 @@ impeller_entity_shaders_length), std::make_shared(impeller_modern_shaders_data, impeller_modern_shaders_length), + std::make_shared( + impeller_framebuffer_blend_shaders_data, + impeller_framebuffer_blend_shaders_length), std::make_shared(impeller_fixtures_shaders_data, impeller_fixtures_shaders_length), std::make_shared( diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index 99922ba7efaeb..a9de32f2c3df3 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -78,6 +78,7 @@ ContextGLES::ContextGLES(std::unique_ptr gl, .SetSupportsSSBO(false) .SetSupportsTextureToTextureBlits( reactor_->GetProcTable().BlitFramebuffer.IsAvailable()) + .SetSupportsFramebufferFetch(false) .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) .SetDefaultStencilFormat(PixelFormat::kS8UInt) .Build(); diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index ceea472db4364..bd75e585d86c0 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -51,6 +51,8 @@ class ContextMTL final : public Context, ContextMTL(id device, NSArray>* shader_libraries); + bool SupportsFramebufferFetch() const; + // |Context| bool IsValid() const override; diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index a601f099fd001..c9f0dd9c24216 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -96,6 +96,7 @@ .SetSupportsOffscreenMSAA(true) .SetSupportsSSBO(true) .SetSupportsTextureToTextureBlits(true) + .SetSupportsFramebufferFetch(SupportsFramebufferFetch()) .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) .SetDefaultStencilFormat(PixelFormat::kS8UInt) .Build(); @@ -104,6 +105,25 @@ is_valid_ = true; } +bool ContextMTL::SupportsFramebufferFetch() const { + // The iOS simulator lies about supporting framebuffer fetch. +#if FML_OS_IOS_SIMULATOR + return false; +#endif // FML_OS_IOS_SIMULATOR + + if (@available(macOS 10.15, iOS 13, tvOS 13, *)) { + return [device_ supportsFamily:MTLGPUFamilyApple2]; + } + // According to + // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf , Apple2 + // corresponds to iOS GPU family 2, which supports A8 devices. +#if FML_OS_IOS + return [device_ supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]; +#else + return false; +#endif // FML_OS_IOS +} + static NSArray>* MTLShaderLibraryFromFilePaths( id device, const std::vector& libraries_paths) { diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 41594818f7b8f..a71731d16627a 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -554,6 +554,7 @@ ContextVK::ContextVK( .SetSupportsOffscreenMSAA(true) .SetSupportsSSBO(false) .SetSupportsTextureToTextureBlits(true) + .SetSupportsFramebufferFetch(false) .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) .SetDefaultStencilFormat(PixelFormat::kS8UInt) .Build(); diff --git a/impeller/renderer/device_capabilities.cc b/impeller/renderer/device_capabilities.cc index 87653bb63beef..9bb9e3702d239 100644 --- a/impeller/renderer/device_capabilities.cc +++ b/impeller/renderer/device_capabilities.cc @@ -10,12 +10,14 @@ IDeviceCapabilities::IDeviceCapabilities(bool has_threading_restrictions, bool supports_offscreen_msaa, bool supports_ssbo, bool supports_texture_to_texture_blits, + bool supports_framebuffer_fetch, PixelFormat default_color_format, PixelFormat default_stencil_format) : has_threading_restrictions_(has_threading_restrictions), supports_offscreen_msaa_(supports_offscreen_msaa), supports_ssbo_(supports_ssbo), supports_texture_to_texture_blits_(supports_texture_to_texture_blits), + supports_framebuffer_fetch_(supports_framebuffer_fetch), default_color_format_(default_color_format), default_stencil_format_(default_stencil_format) {} @@ -37,6 +39,10 @@ bool IDeviceCapabilities::SupportsTextureToTextureBlits() const { return supports_texture_to_texture_blits_; } +bool IDeviceCapabilities::SupportsFramebufferFetch() const { + return supports_framebuffer_fetch_; +} + PixelFormat IDeviceCapabilities::GetDefaultColorFormat() const { return default_color_format_; } @@ -73,6 +79,12 @@ DeviceCapabilitiesBuilder::SetSupportsTextureToTextureBlits(bool value) { return *this; } +DeviceCapabilitiesBuilder& +DeviceCapabilitiesBuilder::SetSupportsFramebufferFetch(bool value) { + supports_framebuffer_fetch_ = value; + return *this; +} + DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetDefaultColorFormat( PixelFormat value) { default_color_format_ = value; @@ -96,6 +108,7 @@ std::unique_ptr DeviceCapabilitiesBuilder::Build() { supports_offscreen_msaa_, // supports_ssbo_, // supports_texture_to_texture_blits_, // + supports_framebuffer_fetch_, // *default_color_format_, // *default_stencil_format_ // ); diff --git a/impeller/renderer/device_capabilities.h b/impeller/renderer/device_capabilities.h index 010281da37a4d..697b8f5d531a0 100644 --- a/impeller/renderer/device_capabilities.h +++ b/impeller/renderer/device_capabilities.h @@ -23,6 +23,8 @@ class IDeviceCapabilities { bool SupportsTextureToTextureBlits() const; + bool SupportsFramebufferFetch() const; + PixelFormat GetDefaultColorFormat() const; PixelFormat GetDefaultStencilFormat() const; @@ -32,6 +34,7 @@ class IDeviceCapabilities { bool supports_offscreen_msaa, bool supports_ssbo, bool supports_texture_to_texture_blits, + bool supports_framebuffer_fetch, PixelFormat default_color_format, PixelFormat default_stencil_format); @@ -41,6 +44,7 @@ class IDeviceCapabilities { bool supports_offscreen_msaa_ = false; bool supports_ssbo_ = false; bool supports_texture_to_texture_blits_ = false; + bool supports_framebuffer_fetch_ = false; PixelFormat default_color_format_; PixelFormat default_stencil_format_; @@ -61,6 +65,8 @@ class DeviceCapabilitiesBuilder { DeviceCapabilitiesBuilder& SetSupportsTextureToTextureBlits(bool value); + DeviceCapabilitiesBuilder& SetSupportsFramebufferFetch(bool value); + DeviceCapabilitiesBuilder& SetDefaultColorFormat(PixelFormat value); DeviceCapabilitiesBuilder& SetDefaultStencilFormat(PixelFormat value); @@ -72,6 +78,7 @@ class DeviceCapabilitiesBuilder { bool supports_offscreen_msaa_ = false; bool supports_ssbo_ = false; bool supports_texture_to_texture_blits_ = false; + bool supports_framebuffer_fetch_ = false; std::optional default_color_format_ = std::nullopt; std::optional default_stencil_format_ = std::nullopt; diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm index 4810aaae7a7a0..e84a2e29cb30f 100644 --- a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm +++ b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm @@ -10,6 +10,7 @@ #include "flutter/shell/common/context_options.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #include "impeller/entity/mtl/entity_shaders.h" +#include "impeller/entity/mtl/framebuffer_blend_shaders.h" #include "impeller/entity/mtl/modern_shaders.h" #include "impeller/scene/shaders/mtl/scene_shaders.h" @@ -23,6 +24,8 @@ impeller_scene_shaders_length), std::make_shared(impeller_modern_shaders_data, impeller_modern_shaders_length), + std::make_shared(impeller_framebuffer_blend_shaders_data, + impeller_framebuffer_blend_shaders_length), }; auto context = impeller::ContextMTL::Create(shader_mappings, "Impeller Library"); if (!context) {