[Impeller] Replace FML_OS_PHYSICAL_IOS compile check with runtime capabilties check based on metal GPU family. (flutter/engine#40124)

[Impeller] Replace FML_OS_PHYSICAL_IOS compile check with runtime capabilties check based on metal GPU family.
This commit is contained in:
Jonah Williams 2023-03-07 19:25:08 -08:00 committed by GitHub
parent bf7cfcf102
commit aa6c168e5f
19 changed files with 234 additions and 165 deletions

View File

@ -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_

View File

@ -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;
}

View File

@ -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",

View File

@ -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<FramebufferBlendContents>();
contents->SetBlendMode(blend_mode_);
contents->SetChildContents(src_contents);
entity.SetContents(std::move(contents));
std::shared_ptr<Texture> 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<FramebufferBlendContents>();
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_);

View File

@ -183,6 +183,38 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
sweep_gradient_ssbo_fill_pipelines_[{}] =
CreateDefaultPipeline<SweepGradientSSBOFillPipeline>(*context_);
}
if (context_->GetDeviceCapabilities().SupportsFramebufferFetch()) {
framebuffer_blend_color_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendColorPipeline>(*context_);
framebuffer_blend_colorburn_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendColorBurnPipeline>(*context_);
framebuffer_blend_colordodge_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendColorDodgePipeline>(*context_);
framebuffer_blend_darken_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendDarkenPipeline>(*context_);
framebuffer_blend_difference_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendDifferencePipeline>(*context_);
framebuffer_blend_exclusion_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendExclusionPipeline>(*context_);
framebuffer_blend_hardlight_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendHardLightPipeline>(*context_);
framebuffer_blend_hue_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendHuePipeline>(*context_);
framebuffer_blend_lighten_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendLightenPipeline>(*context_);
framebuffer_blend_luminosity_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendLuminosityPipeline>(*context_);
framebuffer_blend_multiply_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendMultiplyPipeline>(*context_);
framebuffer_blend_overlay_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendOverlayPipeline>(*context_);
framebuffer_blend_saturation_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendSaturationPipeline>(*context_);
framebuffer_blend_screen_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendScreenPipeline>(*context_);
framebuffer_blend_softlight_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendSoftLightPipeline>(*context_);
}
blend_color_pipelines_[{}] =
CreateDefaultPipeline<BlendColorPipeline>(*context_);
@ -213,39 +245,6 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
CreateDefaultPipeline<BlendScreenPipeline>(*context_);
blend_softlight_pipelines_[{}] =
CreateDefaultPipeline<BlendSoftLightPipeline>(*context_);
#if FML_OS_PHYSICAL_IOS
framebuffer_blend_color_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendColorPipeline>(*context_);
framebuffer_blend_colorburn_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendColorBurnPipeline>(*context_);
framebuffer_blend_colordodge_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendColorDodgePipeline>(*context_);
framebuffer_blend_darken_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendDarkenPipeline>(*context_);
framebuffer_blend_difference_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendDifferencePipeline>(*context_);
framebuffer_blend_exclusion_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendExclusionPipeline>(*context_);
framebuffer_blend_hardlight_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendHardLightPipeline>(*context_);
framebuffer_blend_hue_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendHuePipeline>(*context_);
framebuffer_blend_lighten_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendLightenPipeline>(*context_);
framebuffer_blend_luminosity_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendLuminosityPipeline>(*context_);
framebuffer_blend_multiply_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendMultiplyPipeline>(*context_);
framebuffer_blend_overlay_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendOverlayPipeline>(*context_);
framebuffer_blend_saturation_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendSaturationPipeline>(*context_);
framebuffer_blend_screen_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendScreenPipeline>(*context_);
framebuffer_blend_softlight_pipelines_[{}] =
CreateDefaultPipeline<FramebufferBlendSoftLightPipeline>(*context_);
#endif // FML_OS_PHYSICAL_IOS
sweep_gradient_fill_pipelines_[{}] =
CreateDefaultPipeline<SweepGradientFillPipeline>(*context_);
rrect_blur_pipelines_[{}] =

View File

@ -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<AdvancedBlendVertexShader,
using BlendSoftLightPipeline =
RenderPipelineT<AdvancedBlendVertexShader,
AdvancedBlendSoftlightFragmentShader>;
#if FML_OS_PHYSICAL_IOS
// iOS only advanced blends.
// Framebuffer Advanced Blends
using FramebufferBlendColorPipeline =
RenderPipelineT<FramebufferBlendVertexShader,
FramebufferBlendColorFragmentShader>;
@ -249,7 +247,6 @@ using FramebufferBlendScreenPipeline =
using FramebufferBlendSoftLightPipeline =
RenderPipelineT<FramebufferBlendVertexShader,
FramebufferBlendSoftlightFragmentShader>;
#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<Pipeline<PipelineDescriptor>>
GetFramebufferBlendColorPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_color_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendColorBurnPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_colorburn_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendColorDodgePipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_colordodge_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendDarkenPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_darken_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendDifferencePipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_difference_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendExclusionPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_exclusion_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendHardLightPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_hardlight_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>> GetFramebufferBlendHuePipeline(
ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_hue_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendLightenPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_lighten_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendLuminosityPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_luminosity_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendMultiplyPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_multiply_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendOverlayPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_overlay_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendSaturationPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_saturation_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendScreenPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_screen_pipelines_, opts);
}
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendSoftLightPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_softlight_pipelines_, opts);
}
#endif // FML_OS_PHYSICAL_IOS
std::shared_ptr<Context> GetContext() const;
@ -669,7 +680,7 @@ class ContentContext {
mutable Variants<BlendSaturationPipeline> blend_saturation_pipelines_;
mutable Variants<BlendScreenPipeline> blend_screen_pipelines_;
mutable Variants<BlendSoftLightPipeline> blend_softlight_pipelines_;
#if FML_OS_PHYSICAL_IOS
// Framebuffer Advanced blends.
mutable Variants<FramebufferBlendColorPipeline>
framebuffer_blend_color_pipelines_;
mutable Variants<FramebufferBlendColorBurnPipeline>
@ -700,7 +711,6 @@ class ContentContext {
framebuffer_blend_screen_pipelines_;
mutable Variants<FramebufferBlendSoftLightPipeline>
framebuffer_blend_softlight_pipelines_;
#endif // FML_OS_PHYSICAL_IOS
template <class TypedPipeline>
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(

View File

@ -32,6 +32,10 @@ std::optional<Rect> 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;

View File

@ -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<EntityPassDelegate> 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<EntityPass> 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<FramebufferBlendContents>();
contents->SetChildContents(src_contents);
contents->SetBlendMode(result.entity.GetBlendMode());
result.entity.SetContents(std::move(contents));
result.entity.SetBlendMode(BlendMode::kSource);
if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
auto src_contents = result.entity.GetContents();
auto contents = std::make_shared<FramebufferBlendContents>();
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).
#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 (!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;
}
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);
}
// 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
}
//--------------------------------------------------------------------------

View File

@ -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<BackdropFilterProc> backdrop_filter_proc_ = std::nullopt;

View File

@ -9,7 +9,7 @@
#include <impeller/texture.glsl>
#include <impeller/types.glsl>
#ifdef IMPELLER_TARGET_METAL_IOS
#ifdef IMPELLER_TARGET_METAL
layout(set = 0,
binding = 0,
input_attachment_index = 0) uniform subpassInput uSub;

View File

@ -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",

View File

@ -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 @@ ShaderLibraryMappingsForPlayground() {
impeller_entity_shaders_length),
std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_data,
impeller_modern_shaders_length),
std::make_shared<fml::NonOwnedMapping>(
impeller_framebuffer_blend_shaders_data,
impeller_framebuffer_blend_shaders_length),
std::make_shared<fml::NonOwnedMapping>(impeller_fixtures_shaders_data,
impeller_fixtures_shaders_length),
std::make_shared<fml::NonOwnedMapping>(

View File

@ -78,6 +78,7 @@ ContextGLES::ContextGLES(std::unique_ptr<ProcTableGLES> gl,
.SetSupportsSSBO(false)
.SetSupportsTextureToTextureBlits(
reactor_->GetProcTable().BlitFramebuffer.IsAvailable())
.SetSupportsFramebufferFetch(false)
.SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt)
.SetDefaultStencilFormat(PixelFormat::kS8UInt)
.Build();

View File

@ -51,6 +51,8 @@ class ContextMTL final : public Context,
ContextMTL(id<MTLDevice> device, NSArray<id<MTLLibrary>>* shader_libraries);
bool SupportsFramebufferFetch() const;
// |Context|
bool IsValid() const override;

View File

@ -96,6 +96,7 @@ ContextMTL::ContextMTL(id<MTLDevice> device,
.SetSupportsOffscreenMSAA(true)
.SetSupportsSSBO(true)
.SetSupportsTextureToTextureBlits(true)
.SetSupportsFramebufferFetch(SupportsFramebufferFetch())
.SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt)
.SetDefaultStencilFormat(PixelFormat::kS8UInt)
.Build();
@ -104,6 +105,25 @@ ContextMTL::ContextMTL(id<MTLDevice> device,
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<id<MTLLibrary>>* MTLShaderLibraryFromFilePaths(
id<MTLDevice> device,
const std::vector<std::string>& libraries_paths) {

View File

@ -554,6 +554,7 @@ ContextVK::ContextVK(
.SetSupportsOffscreenMSAA(true)
.SetSupportsSSBO(false)
.SetSupportsTextureToTextureBlits(true)
.SetSupportsFramebufferFetch(false)
.SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt)
.SetDefaultStencilFormat(PixelFormat::kS8UInt)
.Build();

View File

@ -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<IDeviceCapabilities> DeviceCapabilitiesBuilder::Build() {
supports_offscreen_msaa_, //
supports_ssbo_, //
supports_texture_to_texture_blits_, //
supports_framebuffer_fetch_, //
*default_color_format_, //
*default_stencil_format_ //
);

View File

@ -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<PixelFormat> default_color_format_ = std::nullopt;
std::optional<PixelFormat> default_stencil_format_ = std::nullopt;

View File

@ -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 @@ static std::shared_ptr<impeller::ContextMTL> CreateImpellerContext() {
impeller_scene_shaders_length),
std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_data,
impeller_modern_shaders_length),
std::make_shared<fml::NonOwnedMapping>(impeller_framebuffer_blend_shaders_data,
impeller_framebuffer_blend_shaders_length),
};
auto context = impeller::ContextMTL::Create(shader_mappings, "Impeller Library");
if (!context) {