diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index a40c1e0728b46..b21aa32e7d731 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -2750,7 +2750,7 @@ TEST_P(AiksTest, CanRenderClippedBlur) { .color = Color::Green(), .image_filter = ImageFilter::MakeBlur( Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp), + Entity::TileMode::kDecal), }); canvas.Restore(); @@ -3960,6 +3960,48 @@ TEST_P(AiksTest, GaussianBlurMipMapImageFilter) { #endif } +TEST_P(AiksTest, GaussianBlurMipMapSolidColor) { + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + fml::testing::LogCapture log_capture; + Canvas canvas; + canvas.DrawPath(PathBuilder{} + .MoveTo({100, 100}) + .LineTo({200, 100}) + .LineTo({150, 200}) + .LineTo({50, 200}) + .Close() + .TakePath(), + {.color = Color::Chartreuse(), + .image_filter = ImageFilter::MakeBlur( + Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {1024, 768}); + + size_t max_mip_count = 0; + for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd(); + ++it) { + max_mip_count = + std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); + // The log is FML_DLOG, so only check in debug builds. +#ifndef NDEBUG + if (GetParam() != PlaygroundBackend::kOpenGLES) { + EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } else { + EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } +#endif +} + TEST_P(AiksTest, ImageColorSourceEffectTransform) { // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885 diff --git a/impeller/display_list/dl_image_impeller.cc b/impeller/display_list/dl_image_impeller.cc index 44381efc89f63..e5af07f6a2ffc 100644 --- a/impeller/display_list/dl_image_impeller.cc +++ b/impeller/display_list/dl_image_impeller.cc @@ -36,7 +36,8 @@ sk_sp DlImageImpeller::MakeFromYUVTextures( std::nullopt, // coverage_limit std::nullopt, // sampler_descriptor true, // msaa_enabled - "MakeYUVToRGBFilter Snapshot"); // label + /*mip_count=*/1, + "MakeYUVToRGBFilter Snapshot"); // label if (!snapshot.has_value()) { return nullptr; } diff --git a/impeller/entity/contents/atlas_contents.cc b/impeller/entity/contents/atlas_contents.cc index de9d7c425d78b..c8df84b02ac15 100644 --- a/impeller/entity/contents/atlas_contents.cc +++ b/impeller/entity/contents/atlas_contents.cc @@ -304,6 +304,7 @@ bool AtlasContents::Render(const ContentContext& renderer, std::nullopt, // coverage_limit std::nullopt, // sampler_descriptor true, // msaa_enabled + /*mip_count=*/1, "AtlasContents Snapshot"); // label if (!snapshot.has_value()) { return false; diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index f4c186199a817..2c333b3c9a474 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -15,6 +15,7 @@ #include "impeller/renderer/pipeline_descriptor.h" #include "impeller/renderer/pipeline_library.h" #include "impeller/renderer/render_target.h" +#include "impeller/renderer/texture_mipmap.h" #include "impeller/tessellator/tessellator.h" #include "impeller/typographer/typographer_context.h" @@ -429,20 +430,21 @@ fml::StatusOr ContentContext::MakeSubpass( const std::string& label, ISize texture_size, const SubpassCallback& subpass_callback, - bool msaa_enabled) const { + bool msaa_enabled, + int32_t mip_count) const { const std::shared_ptr& context = GetContext(); RenderTarget subpass_target; if (context->GetCapabilities()->SupportsOffscreenMSAA() && msaa_enabled) { subpass_target = RenderTarget::CreateOffscreenMSAA( - *context, *GetRenderTargetCache(), texture_size, /*mip_count=*/1, - SPrintF("%s Offscreen", label.c_str()), + *context, *GetRenderTargetCache(), texture_size, + /*mip_count=*/mip_count, SPrintF("%s Offscreen", label.c_str()), RenderTarget::kDefaultColorAttachmentConfigMSAA, std::nullopt // stencil_attachment_config ); } else { subpass_target = RenderTarget::CreateOffscreen( - *context, *GetRenderTargetCache(), texture_size, /*mip_count=*/1, - SPrintF("%s Offscreen", label.c_str()), + *context, *GetRenderTargetCache(), texture_size, + /*mip_count=*/mip_count, SPrintF("%s Offscreen", label.c_str()), RenderTarget::kDefaultColorAttachmentConfig, // std::nullopt // stencil_attachment_config ); @@ -477,7 +479,21 @@ fml::StatusOr ContentContext::MakeSubpass( return fml::Status(fml::StatusCode::kUnknown, ""); } - if (!sub_command_buffer->EncodeAndSubmit(sub_renderpass)) { + if (!sub_renderpass->EncodeCommands()) { + return fml::Status(fml::StatusCode::kUnknown, ""); + } + + const std::shared_ptr& target_texture = + subpass_target.GetRenderTargetTexture(); + if (target_texture->GetMipCount() > 1) { + fml::Status mipmap_status = + AddMipmapGeneration(sub_command_buffer, context, target_texture); + if (!mipmap_status.ok()) { + return mipmap_status; + } + } + + if (!sub_command_buffer->SubmitCommands()) { return fml::Status(fml::StatusCode::kUnknown, ""); } diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 2bcbb725068bf..1143741f157b9 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -724,7 +724,8 @@ class ContentContext { const std::string& label, ISize texture_size, const SubpassCallback& subpass_callback, - bool msaa_enabled = true) const; + bool msaa_enabled = true, + int32_t mip_count = 1) const; /// Makes a subpass that will render to `subpass_target`. fml::StatusOr MakeSubpass( diff --git a/impeller/entity/contents/contents.cc b/impeller/entity/contents/contents.cc index 9b6038b6ae864..bbef8298ce869 100644 --- a/impeller/entity/contents/contents.cc +++ b/impeller/entity/contents/contents.cc @@ -60,6 +60,7 @@ std::optional Contents::RenderToSnapshot( std::optional coverage_limit, const std::optional& sampler_descriptor, bool msaa_enabled, + int32_t mip_count, const std::string& label) const { auto coverage = GetCoverage(entity); if (!coverage.has_value()) { @@ -90,7 +91,7 @@ std::optional Contents::RenderToSnapshot( entity.GetTransform()); return contents.Render(renderer, sub_entity, pass); }, - msaa_enabled); + msaa_enabled, mip_count); if (!render_target.ok()) { return std::nullopt; diff --git a/impeller/entity/contents/contents.h b/impeller/entity/contents/contents.h index 9a9ea86609184..ec8f1a714708a 100644 --- a/impeller/entity/contents/contents.h +++ b/impeller/entity/contents/contents.h @@ -121,6 +121,7 @@ class Contents { std::optional coverage_limit = std::nullopt, const std::optional& sampler_descriptor = std::nullopt, bool msaa_enabled = true, + int32_t mip_count = 1, const std::string& label = "Snapshot") const; virtual bool ShouldRender(const Entity& entity, diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc index 6ed61b0235744..a4532db4a78ad 100644 --- a/impeller/entity/contents/filters/filter_contents.cc +++ b/impeller/entity/contents/filters/filter_contents.cc @@ -50,7 +50,8 @@ std::shared_ptr FilterContents::MakeDirectionalGaussianBlur( return blur; } -const int32_t FilterContents::kBlurFilterRequiredMipCount = 4; +const int32_t FilterContents::kBlurFilterRequiredMipCount = + GaussianBlurFilterContents::kBlurFilterRequiredMipCount; std::shared_ptr FilterContents::MakeGaussianBlur( const FilterInput::Ref& input, @@ -262,6 +263,7 @@ std::optional FilterContents::RenderToSnapshot( std::optional coverage_limit, const std::optional& sampler_descriptor, bool msaa_enabled, + int32_t mip_count, const std::string& label) const { // Resolve the render instruction (entity) from the filter and render it to a // snapshot. @@ -274,7 +276,8 @@ std::optional FilterContents::RenderToSnapshot( coverage_limit, // coverage_limit std::nullopt, // sampler_descriptor true, // msaa_enabled - label); // label + /*mip_count=*/mip_count, + label); // label } return std::nullopt; diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h index 076593f644dab..6c420a2697385 100644 --- a/impeller/entity/contents/filters/filter_contents.h +++ b/impeller/entity/contents/filters/filter_contents.h @@ -131,6 +131,7 @@ class FilterContents : public Contents { std::optional coverage_limit = std::nullopt, const std::optional& sampler_descriptor = std::nullopt, bool msaa_enabled = true, + int32_t mip_count = 1, const std::string& label = "Filter Snapshot") const override; // |Contents| diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index a58d8b26a56a8..838a87c408610 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -19,6 +19,8 @@ namespace impeller { using GaussianBlurVertexShader = KernelPipeline::VertexShader; using GaussianBlurFragmentShader = KernelPipeline::FragmentShader; +const int32_t GaussianBlurFilterContents::kBlurFilterRequiredMipCount = 4; + namespace { SamplerDescriptor MakeSamplerDescriptor(MinMagFilter filter, @@ -269,9 +271,18 @@ std::optional GaussianBlurFilterContents::RenderFilter( expanded_coverage_hint = coverage_hint->Expand(local_padding); } + int32_t mip_count = kBlurFilterRequiredMipCount; + if (renderer.GetContext()->GetBackendType() == + Context::BackendType::kOpenGLES) { + // TODO(https://github.com/flutter/flutter/issues/141732): Implement mip map + // generation on opengles. + mip_count = 1; + } + std::optional input_snapshot = inputs[0]->GetSnapshot("GaussianBlur", renderer, entity, - /*coverage_limit=*/expanded_coverage_hint); + /*coverage_limit=*/expanded_coverage_hint, + /*mip_count=*/mip_count); if (!input_snapshot.has_value()) { return std::nullopt; } diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h b/impeller/entity/contents/filters/gaussian_blur_filter_contents.h index 4473318698df6..458e310541f9a 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.h @@ -28,6 +28,7 @@ KernelPipeline::FragmentShader::KernelSamples GenerateBlurInfo( class GaussianBlurFilterContents final : public FilterContents { public: static std::string_view kNoMipsError; + static const int32_t kBlurFilterRequiredMipCount; explicit GaussianBlurFilterContents(Scalar sigma_x, Scalar sigma_y, diff --git a/impeller/entity/contents/filters/inputs/contents_filter_input.cc b/impeller/entity/contents/filters/inputs/contents_filter_input.cc index 8fd28f5e14954..f6e95a1af23ec 100644 --- a/impeller/entity/contents/filters/inputs/contents_filter_input.cc +++ b/impeller/entity/contents/filters/inputs/contents_filter_input.cc @@ -25,7 +25,8 @@ std::optional ContentsFilterInput::GetSnapshot( const std::string& label, const ContentContext& renderer, const Entity& entity, - std::optional coverage_limit) const { + std::optional coverage_limit, + int32_t mip_count) const { if (!coverage_limit.has_value() && entity.GetContents()) { coverage_limit = entity.GetContents()->GetCoverageHint(); } @@ -36,6 +37,7 @@ std::optional ContentsFilterInput::GetSnapshot( coverage_limit, // coverage_limit std::nullopt, // sampler_descriptor msaa_enabled_, // msaa_enabled + /*mip_count=*/mip_count, SPrintF("Contents to %s Filter Snapshot", label.c_str())); // label } return snapshot_; diff --git a/impeller/entity/contents/filters/inputs/contents_filter_input.h b/impeller/entity/contents/filters/inputs/contents_filter_input.h index 8d381b76530ed..374e10123efc4 100644 --- a/impeller/entity/contents/filters/inputs/contents_filter_input.h +++ b/impeller/entity/contents/filters/inputs/contents_filter_input.h @@ -17,11 +17,11 @@ class ContentsFilterInput final : public FilterInput { Variant GetInput() const override; // |FilterInput| - std::optional GetSnapshot( - const std::string& label, - const ContentContext& renderer, - const Entity& entity, - std::optional coverage_limit) const override; + std::optional GetSnapshot(const std::string& label, + const ContentContext& renderer, + const Entity& entity, + std::optional coverage_limit, + int32_t mip_count) const override; // |FilterInput| std::optional GetCoverage(const Entity& entity) const override; diff --git a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc index 200edc632d956..2dabc08e61c06 100644 --- a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc +++ b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc @@ -25,7 +25,8 @@ std::optional FilterContentsFilterInput::GetSnapshot( const std::string& label, const ContentContext& renderer, const Entity& entity, - std::optional coverage_limit) const { + std::optional coverage_limit, + int32_t mip_count) const { if (!snapshot_.has_value()) { snapshot_ = filter_->RenderToSnapshot( renderer, // renderer @@ -33,6 +34,7 @@ std::optional FilterContentsFilterInput::GetSnapshot( coverage_limit, // coverage_limit std::nullopt, // sampler_descriptor true, // msaa_enabled + /*mip_count=*/mip_count, SPrintF("Filter to %s Filter Snapshot", label.c_str())); // label } return snapshot_; diff --git a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h index 965d45b3b1698..8d5f26693be9b 100644 --- a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h +++ b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h @@ -17,11 +17,11 @@ class FilterContentsFilterInput final : public FilterInput { Variant GetInput() const override; // |FilterInput| - std::optional GetSnapshot( - const std::string& label, - const ContentContext& renderer, - const Entity& entity, - std::optional coverage_limit) const override; + std::optional GetSnapshot(const std::string& label, + const ContentContext& renderer, + const Entity& entity, + std::optional coverage_limit, + int32_t mip_count) const override; // |FilterInput| std::optional GetCoverage(const Entity& entity) const override; diff --git a/impeller/entity/contents/filters/inputs/filter_input.h b/impeller/entity/contents/filters/inputs/filter_input.h index 20a7136b446fd..070b05c688daf 100644 --- a/impeller/entity/contents/filters/inputs/filter_input.h +++ b/impeller/entity/contents/filters/inputs/filter_input.h @@ -51,7 +51,8 @@ class FilterInput { const std::string& label, const ContentContext& renderer, const Entity& entity, - std::optional coverage_limit = std::nullopt) const = 0; + std::optional coverage_limit = std::nullopt, + int32_t mip_count = 1) const = 0; std::optional GetLocalCoverage(const Entity& entity) const; diff --git a/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc b/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc index 5cc22d886ad16..5341b287f0756 100644 --- a/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc +++ b/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc @@ -24,7 +24,8 @@ std::optional PlaceholderFilterInput::GetSnapshot( const std::string& label, const ContentContext& renderer, const Entity& entity, - std::optional coverage_limit) const { + std::optional coverage_limit, + int32_t mip_count) const { return std::nullopt; } diff --git a/impeller/entity/contents/filters/inputs/placeholder_filter_input.h b/impeller/entity/contents/filters/inputs/placeholder_filter_input.h index a6305bc22b236..3641176a51dd4 100644 --- a/impeller/entity/contents/filters/inputs/placeholder_filter_input.h +++ b/impeller/entity/contents/filters/inputs/placeholder_filter_input.h @@ -19,11 +19,11 @@ class PlaceholderFilterInput final : public FilterInput { Variant GetInput() const override; // |FilterInput| - std::optional GetSnapshot( - const std::string& label, - const ContentContext& renderer, - const Entity& entity, - std::optional coverage_limit) const override; + std::optional GetSnapshot(const std::string& label, + const ContentContext& renderer, + const Entity& entity, + std::optional coverage_limit, + int32_t mip_count = 1) const override; // |FilterInput| std::optional GetCoverage(const Entity& entity) const override; diff --git a/impeller/entity/contents/filters/inputs/texture_filter_input.cc b/impeller/entity/contents/filters/inputs/texture_filter_input.cc index 903bca976b597..b18c90f135131 100644 --- a/impeller/entity/contents/filters/inputs/texture_filter_input.cc +++ b/impeller/entity/contents/filters/inputs/texture_filter_input.cc @@ -24,7 +24,8 @@ std::optional TextureFilterInput::GetSnapshot( const std::string& label, const ContentContext& renderer, const Entity& entity, - std::optional coverage_limit) const { + std::optional coverage_limit, + int32_t mip_count) const { auto snapshot = Snapshot{.texture = texture_, .transform = GetTransform(entity)}; if (texture_->GetMipCount() > 1) { diff --git a/impeller/entity/contents/filters/inputs/texture_filter_input.h b/impeller/entity/contents/filters/inputs/texture_filter_input.h index 320eb1b191f6d..5adbe4bb7b398 100644 --- a/impeller/entity/contents/filters/inputs/texture_filter_input.h +++ b/impeller/entity/contents/filters/inputs/texture_filter_input.h @@ -19,11 +19,11 @@ class TextureFilterInput final : public FilterInput { Variant GetInput() const override; // |FilterInput| - std::optional GetSnapshot( - const std::string& label, - const ContentContext& renderer, - const Entity& entity, - std::optional coverage_limit) const override; + std::optional GetSnapshot(const std::string& label, + const ContentContext& renderer, + const Entity& entity, + std::optional coverage_limit, + int32_t mip_count) const override; // |FilterInput| std::optional GetCoverage(const Entity& entity) const override; diff --git a/impeller/entity/contents/framebuffer_blend_contents.cc b/impeller/entity/contents/framebuffer_blend_contents.cc index 0a73b1c33cd16..265f97e3e9b7b 100644 --- a/impeller/entity/contents/framebuffer_blend_contents.cc +++ b/impeller/entity/contents/framebuffer_blend_contents.cc @@ -46,7 +46,8 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer, Rect::MakeSize(pass.GetRenderTargetSize()), // coverage_limit std::nullopt, // sampler_descriptor true, // msaa_enabled - "FramebufferBlendContents Snapshot"); // label + /*mip_count=*/1, + "FramebufferBlendContents Snapshot"); // label if (!src_snapshot.has_value()) { return true; diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc index 8a2c38ad3e8a4..116e5e7617908 100644 --- a/impeller/entity/contents/texture_contents.cc +++ b/impeller/entity/contents/texture_contents.cc @@ -79,6 +79,7 @@ std::optional TextureContents::RenderToSnapshot( std::optional coverage_limit, const std::optional& sampler_descriptor, bool msaa_enabled, + int32_t mip_count, const std::string& label) const { // Passthrough textures that have simple rectangle paths and complete source // rects. @@ -101,7 +102,8 @@ std::optional TextureContents::RenderToSnapshot( std::nullopt, // coverage_limit sampler_descriptor.value_or(sampler_descriptor_), // sampler_descriptor true, // msaa_enabled - label); // label + /*mip_count=*/mip_count, + label); // label } bool TextureContents::Render(const ContentContext& renderer, diff --git a/impeller/entity/contents/texture_contents.h b/impeller/entity/contents/texture_contents.h index 9d3f8d6b2c6f4..fc25a900570e3 100644 --- a/impeller/entity/contents/texture_contents.h +++ b/impeller/entity/contents/texture_contents.h @@ -65,6 +65,7 @@ class TextureContents final : public Contents { std::optional coverage_limit = std::nullopt, const std::optional& sampler_descriptor = std::nullopt, bool msaa_enabled = true, + int32_t mip_count = 1, const std::string& label = "Texture Snapshot") const override; // |Contents| diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc index 96ba9f359e0c8..3a9f558ddaa2c 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -65,11 +65,12 @@ std::shared_ptr TiledTextureContents::CreateFilterTexture( } auto color_filter_contents = color_filter_(FilterInput::Make(texture_)); auto snapshot = color_filter_contents->RenderToSnapshot( - renderer, // renderer - Entity(), // entity - std::nullopt, // coverage_limit - std::nullopt, // sampler_descriptor - true, // msaa_enabled + renderer, // renderer + Entity(), // entity + std::nullopt, // coverage_limit + std::nullopt, // sampler_descriptor + true, // msaa_enabled + /*mip_count=*/1, "TiledTextureContents Snapshot"); // label if (snapshot.has_value()) { return snapshot.value().texture; @@ -236,6 +237,7 @@ std::optional TiledTextureContents::RenderToSnapshot( std::optional coverage_limit, const std::optional& sampler_descriptor, bool msaa_enabled, + int32_t mip_count, const std::string& label) const { if (GetInverseEffectTransform().IsIdentity() && GetGeometry()->IsAxisAlignedRect()) { @@ -260,7 +262,8 @@ std::optional TiledTextureContents::RenderToSnapshot( std::nullopt, // coverage_limit sampler_descriptor.value_or(sampler_descriptor_), // sampler_descriptor true, // msaa_enabled - label); // label + /*mip_count=*/1, + label); // label } } // namespace impeller diff --git a/impeller/entity/contents/tiled_texture_contents.h b/impeller/entity/contents/tiled_texture_contents.h index b0a4af1dab9b2..f798c13622a86 100644 --- a/impeller/entity/contents/tiled_texture_contents.h +++ b/impeller/entity/contents/tiled_texture_contents.h @@ -61,6 +61,7 @@ class TiledTextureContents final : public ColorSourceContents { std::optional coverage_limit = std::nullopt, const std::optional& sampler_descriptor = std::nullopt, bool msaa_enabled = true, + int32_t mip_count = 1, const std::string& label = "Tiled Texture Snapshot") const override; private: diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc index 597a0546c2172..f5d433d70f009 100644 --- a/impeller/entity/contents/vertices_contents.cc +++ b/impeller/entity/contents/vertices_contents.cc @@ -116,6 +116,7 @@ bool VerticesUVContents::Render(const ContentContext& renderer, GetCoverageHint(), // coverage_limit std::nullopt, // sampler_descriptor true, // msaa_enabled + /*mip_count=*/1, "VerticesUVContents Snapshot"); // label if (!snapshot.has_value()) { return false;