[Impeller] Comprehensively label snapshots (flutter/engine#41325)

Makes it much easier to work out where things are going wrong in filter
chains.

For example, when capturing the app in
https://github.com/flutter/flutter/issues/124956, the chain of
RenderPasses gets labeled as follows:
1. Contents to ForegroundPorterDuffBlend Filter Snapshot
2. Contents to GaussianBlur Filter Snapshot
3. Directional Gaussian Blur Filter
4. Directional Gaussian Blur Filter

...and so it's easy to see that the filter chain is
ForegroundPorterDuffBlend->DirectionalGaussianBlur->DirectionalGaussianBlur,
and the former two are triggering a non-collapsed snapshot of their
inputs.
This commit is contained in:
Brandon DeRosier
2023-04-19 11:56:12 -07:00
committed by GitHub
parent c7eefdf7f0
commit c43fb87612
28 changed files with 80 additions and 39 deletions

View File

@@ -31,7 +31,8 @@ sk_sp<DlImageImpeller> DlImageImpeller::MakeFromYUVTextures(
impeller::Entity entity;
entity.SetBlendMode(impeller::BlendMode::kSource);
auto snapshot = yuv_to_rgb_filter_contents->RenderToSnapshot(
aiks_context->GetContentContext(), entity);
aiks_context->GetContentContext(), entity, std::nullopt, true,
"MakeYUVToRGBFilter Snapshot");
return impeller::DlImageImpeller::Make(snapshot->texture);
}

View File

@@ -248,7 +248,8 @@ bool AtlasContents::Render(const ContentContext& renderer,
auto contents = ColorFilterContents::MakeBlend(
blend_mode_,
{FilterInput::Make(dst_contents), FilterInput::Make(src_contents)});
auto snapshot = contents->RenderToSnapshot(renderer, entity);
auto snapshot = contents->RenderToSnapshot(renderer, entity, std::nullopt,
true, "AtlasContents Snapshot");
if (!snapshot.has_value()) {
return false;
}

View File

@@ -56,14 +56,15 @@ std::optional<Snapshot> Contents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled) const {
bool msaa_enabled,
const std::string& label) const {
auto coverage = GetCoverage(entity);
if (!coverage.has_value()) {
return std::nullopt;
}
auto texture = renderer.MakeSubpass(
"Snapshot", ISize::Ceil(coverage->size),
label, ISize::Ceil(coverage->size),
[&contents = *this, &entity, &coverage](const ContentContext& renderer,
RenderPass& pass) -> bool {
Entity sub_entity;

View File

@@ -72,7 +72,8 @@ class Contents {
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor = std::nullopt,
bool msaa_enabled = true) const;
bool msaa_enabled = true,
const std::string& label = "Snapshot") const;
virtual bool ShouldRender(const Entity& entity,
const std::optional<Rect>& stencil_coverage) const;

View File

@@ -54,7 +54,8 @@ static std::optional<Entity> AdvancedBlend(
return std::nullopt;
}
auto dst_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto dst_snapshot =
inputs[0]->GetSnapshot("AdvancedBlend(Dst)", renderer, entity);
if (!dst_snapshot.has_value()) {
return std::nullopt;
}
@@ -67,7 +68,8 @@ static std::optional<Entity> AdvancedBlend(
std::optional<Snapshot> src_snapshot;
std::array<Point, 4> src_uvs;
if (!foreground_color.has_value()) {
src_snapshot = inputs[1]->GetSnapshot(renderer, entity);
src_snapshot =
inputs[1]->GetSnapshot("AdvancedBlend(Src)", renderer, entity);
if (!src_snapshot.has_value()) {
if (!dst_snapshot.has_value()) {
return std::nullopt;
@@ -188,7 +190,8 @@ std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
BlendMode blend_mode,
std::optional<Scalar> alpha,
bool absorb_opacity) const {
auto dst_snapshot = input->GetSnapshot(renderer, entity);
auto dst_snapshot =
input->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
if (!dst_snapshot.has_value()) {
return std::nullopt;
}
@@ -353,7 +356,8 @@ std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
BlendMode blend_mode,
std::optional<Scalar> alpha,
bool absorb_opacity) const {
auto dst_snapshot = input->GetSnapshot(renderer, entity);
auto dst_snapshot =
input->GetSnapshot("ForegroundPorterDuffBlend", renderer, entity);
if (!dst_snapshot.has_value()) {
return std::nullopt;
}
@@ -477,7 +481,8 @@ static std::optional<Entity> PipelineBlend(
using VS = BlendPipeline::VertexShader;
using FS = BlendPipeline::FragmentShader;
auto dst_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto dst_snapshot =
inputs[0]->GetSnapshot("PipelineBlend(Dst)", renderer, entity);
ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
RenderPass& pass) {
@@ -544,7 +549,8 @@ static std::optional<Entity> PipelineBlend(
for (auto texture_i = inputs.begin() + 1; texture_i < inputs.end();
texture_i++) {
auto src_input = texture_i->get()->GetSnapshot(renderer, entity);
auto src_input = texture_i->get()->GetSnapshot("PipelineBlend(Src)",
renderer, entity);
if (!add_blend_command(src_input)) {
return true;
}

View File

@@ -65,7 +65,8 @@ std::optional<Entity> BorderMaskBlurFilterContents::RenderFilter(
return std::nullopt;
}
auto input_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto input_snapshot =
inputs[0]->GetSnapshot("BorderMaskBlur", renderer, entity);
if (!input_snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -41,7 +41,7 @@ std::optional<Entity> ColorMatrixFilterContents::RenderFilter(
return std::nullopt;
}
auto input_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto input_snapshot = inputs[0]->GetSnapshot("ColorMatrix", renderer, entity);
if (!input_snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -242,12 +242,14 @@ std::optional<Snapshot> FilterContents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled) const {
bool msaa_enabled,
const std::string& label) const {
// Resolve the render instruction (entity) from the filter and render it to a
// snapshot.
if (std::optional<Entity> result = GetEntity(renderer, entity);
result.has_value()) {
return result->GetContents()->RenderToSnapshot(renderer, result.value());
return result->GetContents()->RenderToSnapshot(renderer, result.value(),
std::nullopt, true, label);
}
return std::nullopt;

View File

@@ -126,7 +126,8 @@ class FilterContents : public Contents {
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor = std::nullopt,
bool msaa_enabled = true) const override;
bool msaa_enabled = true,
const std::string& label = "Filter Snapshot") const override;
virtual Matrix GetLocalTransform(const Matrix& parent_transform) const;

View File

@@ -100,7 +100,8 @@ std::optional<Entity> DirectionalGaussianBlurFilterContents::RenderFilter(
// Input 0 snapshot.
auto input_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto input_snapshot =
inputs[0]->GetSnapshot("GaussianBlur", renderer, entity);
if (!input_snapshot.has_value()) {
return std::nullopt;
}
@@ -148,7 +149,8 @@ std::optional<Entity> DirectionalGaussianBlurFilterContents::RenderFilter(
// Source override snapshot.
auto source = source_override_ ? source_override_ : inputs[0];
auto source_snapshot = source->GetSnapshot(renderer, entity);
auto source_snapshot =
source->GetSnapshot("GaussianBlur(Override)", renderer, entity);
if (!source_snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -7,6 +7,8 @@
#include <optional>
#include <utility>
#include "impeller/base/strings.h"
namespace impeller {
ContentsFilterInput::ContentsFilterInput(std::shared_ptr<Contents> contents,
@@ -20,11 +22,13 @@ FilterInput::Variant ContentsFilterInput::GetInput() const {
}
std::optional<Snapshot> ContentsFilterInput::GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity) const {
if (!snapshot_.has_value()) {
snapshot_ = contents_->RenderToSnapshot(renderer, entity, std::nullopt,
msaa_enabled_);
snapshot_ = contents_->RenderToSnapshot(
renderer, entity, std::nullopt, msaa_enabled_,
SPrintF("Contents to %s Filter Snapshot", label.c_str()));
}
return snapshot_;
}

View File

@@ -16,7 +16,8 @@ class ContentsFilterInput final : public FilterInput {
Variant GetInput() const override;
// |FilterInput|
std::optional<Snapshot> GetSnapshot(const ContentContext& renderer,
std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity) const override;
// |FilterInput|

View File

@@ -6,6 +6,7 @@
#include <utility>
#include "impeller/base/strings.h"
#include "impeller/entity/contents/filters/filter_contents.h"
namespace impeller {
@@ -21,10 +22,13 @@ FilterInput::Variant FilterContentsFilterInput::GetInput() const {
}
std::optional<Snapshot> FilterContentsFilterInput::GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity) const {
if (!snapshot_.has_value()) {
snapshot_ = filter_->RenderToSnapshot(renderer, entity);
snapshot_ = filter_->RenderToSnapshot(
renderer, entity, std::nullopt, true,
SPrintF("Filter to %s Filter Snapshot", label.c_str()));
}
return snapshot_;
}

View File

@@ -16,7 +16,8 @@ class FilterContentsFilterInput final : public FilterInput {
Variant GetInput() const override;
// |FilterInput|
std::optional<Snapshot> GetSnapshot(const ContentContext& renderer,
std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity) const override;
// |FilterInput|

View File

@@ -45,7 +45,8 @@ class FilterInput {
virtual Variant GetInput() const = 0;
virtual std::optional<Snapshot> GetSnapshot(const ContentContext& renderer,
virtual std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity) const = 0;
std::optional<Rect> GetLocalCoverage(const Entity& entity) const;

View File

@@ -21,6 +21,7 @@ FilterInput::Variant TextureFilterInput::GetInput() const {
}
std::optional<Snapshot> TextureFilterInput::GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity) const {
auto snapshot =

View File

@@ -18,7 +18,8 @@ class TextureFilterInput final : public FilterInput {
Variant GetInput() const override;
// |FilterInput|
std::optional<Snapshot> GetSnapshot(const ContentContext& renderer,
std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity) const override;
// |FilterInput|

View File

@@ -31,7 +31,8 @@ std::optional<Entity> LinearToSrgbFilterContents::RenderFilter(
using VS = LinearToSrgbFilterPipeline::VertexShader;
using FS = LinearToSrgbFilterPipeline::FragmentShader;
auto input_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto input_snapshot =
inputs[0]->GetSnapshot("LinearToSrgb", renderer, entity);
if (!input_snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -25,8 +25,9 @@ std::optional<Entity> LocalMatrixFilterContents::RenderFilter(
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const {
return Entity::FromSnapshot(inputs[0]->GetSnapshot(renderer, entity),
entity.GetBlendMode(), entity.GetStencilDepth());
return Entity::FromSnapshot(
inputs[0]->GetSnapshot("LocalMatrix", renderer, entity),
entity.GetBlendMode(), entity.GetStencilDepth());
}
} // namespace impeller

View File

@@ -28,7 +28,7 @@ std::optional<Entity> MatrixFilterContents::RenderFilter(
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const {
auto snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto snapshot = inputs[0]->GetSnapshot("Matrix", renderer, entity);
if (!snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -51,7 +51,7 @@ std::optional<Entity> DirectionalMorphologyFilterContents::RenderFilter(
return std::nullopt;
}
auto input_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto input_snapshot = inputs[0]->GetSnapshot("Morphology", renderer, entity);
if (!input_snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -31,7 +31,8 @@ std::optional<Entity> SrgbToLinearFilterContents::RenderFilter(
using VS = SrgbToLinearFilterPipeline::VertexShader;
using FS = SrgbToLinearFilterPipeline::FragmentShader;
auto input_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto input_snapshot =
inputs[0]->GetSnapshot("SrgbToLinear", renderer, entity);
if (!input_snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -50,8 +50,10 @@ std::optional<Entity> YUVToRGBFilterContents::RenderFilter(
using VS = YUVToRGBFilterPipeline::VertexShader;
using FS = YUVToRGBFilterPipeline::FragmentShader;
auto y_input_snapshot = inputs[0]->GetSnapshot(renderer, entity);
auto uv_input_snapshot = inputs[1]->GetSnapshot(renderer, entity);
auto y_input_snapshot =
inputs[0]->GetSnapshot("YUVToRGB(Y)", renderer, entity);
auto uv_input_snapshot =
inputs[1]->GetSnapshot("YUVToRGB(UV)", renderer, entity);
if (!y_input_snapshot.has_value() || !uv_input_snapshot.has_value()) {
return std::nullopt;
}

View File

@@ -41,7 +41,9 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer,
auto& host_buffer = pass.GetTransientsBuffer();
auto src_snapshot = child_contents_->RenderToSnapshot(renderer, entity);
auto src_snapshot =
child_contents_->RenderToSnapshot(renderer, entity, std::nullopt, true,
"FramebufferBlendContents Snapshot");
if (!src_snapshot.has_value()) {
return true;
}

View File

@@ -77,7 +77,8 @@ std::optional<Snapshot> TextureContents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled) const {
bool msaa_enabled,
const std::string& label) const {
// Passthrough textures that have simple rectangle paths and complete source
// rects.
auto bounds = rect_;
@@ -94,7 +95,8 @@ std::optional<Snapshot> TextureContents::RenderToSnapshot(
.opacity = opacity};
}
return Contents::RenderToSnapshot(
renderer, entity, sampler_descriptor.value_or(sampler_descriptor_));
renderer, entity, sampler_descriptor.value_or(sampler_descriptor_), true,
label);
}
static TextureFillVertexShader::PerVertexData ComputeVertexData(

View File

@@ -58,7 +58,8 @@ class TextureContents final : public Contents {
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor = std::nullopt,
bool msaa_enabled = true) const override;
bool msaa_enabled = true,
const std::string& label = "Texture Snapshot") const override;
// |Contents|
bool Render(const ContentContext& renderer,

View File

@@ -65,7 +65,8 @@ TiledTextureContents::CreateFilterTexture(
const ContentContext& renderer) const {
const ColorFilterProc& filter = color_filter_.value();
auto color_filter_contents = filter(FilterInput::Make(texture_));
auto snapshot = color_filter_contents->RenderToSnapshot(renderer, Entity());
auto snapshot = color_filter_contents->RenderToSnapshot(
renderer, Entity(), std::nullopt, true, "TiledTextureContents Snapshot");
if (snapshot.has_value()) {
return snapshot.value().texture;
}

View File

@@ -107,7 +107,8 @@ bool VerticesUVContents::Render(const ContentContext& renderer,
auto src_contents = parent_.GetSourceContents();
auto snapshot = src_contents->RenderToSnapshot(renderer, entity);
auto snapshot = src_contents->RenderToSnapshot(
renderer, entity, std::nullopt, true, "VerticesUVContents Snapshot");
if (!snapshot.has_value()) {
return false;
}