forked from firka/flutter
[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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user