Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion ci/licenses_golden/excluded_files
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@
../../../flutter/impeller/entity/contents/host_buffer_unittests.cc
../../../flutter/impeller/entity/contents/test
../../../flutter/impeller/entity/contents/tiled_texture_contents_unittests.cc
../../../flutter/impeller/entity/contents/vertices_contents_unittests.cc
../../../flutter/impeller/entity/entity_pass_target_unittests.cc
../../../flutter/impeller/entity/entity_pass_unittests.cc
../../../flutter/impeller/entity/entity_unittests.cc
Expand Down
64 changes: 38 additions & 26 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "impeller/entity/contents/atlas_contents.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/color_source_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/solid_rrect_blur_contents.h"
#include "impeller/entity/contents/text_contents.h"
Expand Down Expand Up @@ -933,8 +934,19 @@ void Canvas::DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
return;
}

// If there is are per-vertex colors, an image, and the blend mode
// is simple we can draw without a sub-renderpass.
// If the blend mode is destination don't bother to bind or create a texture.
if (blend_mode == BlendMode::kDestination) {
auto contents = std::make_shared<VerticesSimpleBlendContents>();
contents->SetBlendMode(blend_mode);
contents->SetAlpha(paint.color.alpha);
contents->SetGeometry(vertices);
entity.SetContents(paint.WithFilters(std::move(contents)));
AddRenderEntityToCurrentPass(std::move(entity));
return;
}

// If there is a texture, use this directly. Otherwise render the color
// source to a texture.
if (std::optional<ImageData> maybe_image_data =
GetImageColorSourceData(paint.color_source)) {
const ImageData& image_data = maybe_image_data.value();
Expand All @@ -956,35 +968,35 @@ void Canvas::DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,

std::shared_ptr<Contents> src_contents =
src_paint.CreateContentsForGeometry(vertices);
if (vertices->HasTextureCoordinates()) {
// If the color source has an intrinsic size, then we use that to
// create the src contents as a simplification. Otherwise we use
// the extent of the texture coordinates to determine how large
// the src contents should be. If neither has a value we fall back
// to using the geometry coverage data.
Rect src_coverage;
auto size = src_contents->GetColorSourceSize();
if (size.has_value()) {
src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
} else {
auto cvg = vertices->GetCoverage(Matrix{});
FML_CHECK(cvg.has_value());
src_coverage =
// Covered by FML_CHECK.
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
}
src_contents =
src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));

// If the color source has an intrinsic size, then we use that to
// create the src contents as a simplification. Otherwise we use
// the extent of the texture coordinates to determine how large
// the src contents should be. If neither has a value we fall back
// to using the geometry coverage data.
Rect src_coverage;
auto size = src_contents->GetColorSourceSize();
if (size.has_value()) {
src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
} else {
auto cvg = vertices->GetCoverage(Matrix{});
FML_CHECK(cvg.has_value());
src_coverage =
// Covered by FML_CHECK.
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
}
src_contents =
src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));

auto contents = std::make_shared<VerticesContents>();
contents->SetAlpha(paint.color.alpha);
auto contents = std::make_shared<VerticesSimpleBlendContents>();
contents->SetBlendMode(blend_mode);
contents->SetAlpha(paint.color.alpha);
contents->SetGeometry(vertices);
contents->SetSourceContents(std::move(src_contents));
contents->SetLazyTexture([src_contents](const ContentContext& renderer) {
return src_contents->RenderToSnapshot(renderer, {})->texture;
});
entity.SetContents(paint.WithFilters(std::move(contents)));

AddRenderEntityToCurrentPass(std::move(entity));
}

Expand Down
1 change: 0 additions & 1 deletion impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ impeller_component("entity_unittests") {
"contents/filters/inputs/filter_input_unittests.cc",
"contents/host_buffer_unittests.cc",
"contents/tiled_texture_contents_unittests.cc",
"contents/vertices_contents_unittests.cc",
"entity_pass_target_unittests.cc",
"entity_pass_unittests.cc",
"entity_playground.cc",
Expand Down
33 changes: 17 additions & 16 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "impeller/base/strings.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/entity/contents/framebuffer_blend_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/render_target_cache.h"
Expand Down Expand Up @@ -255,6 +256,18 @@ ContentContext::ContentContext(
return;
}

{
TextureDescriptor desc;
desc.storage_mode = StorageMode::kHostVisible;
desc.format = PixelFormat::kR8G8B8A8UNormInt;
desc.size = ISize{1, 1};
empty_texture_ = GetContext()->GetResourceAllocator()->CreateTexture(desc);
auto data = Color::BlackTransparent().ToR8G8B8A8();
if (!empty_texture_->SetContents(data.data(), 4)) {
VALIDATION_LOG << "Failed to create empty texture.";
}
}

auto options = ContentContextOptions{
.sample_count = SampleCount::kCount4,
.color_attachment_pixel_format =
Expand Down Expand Up @@ -448,6 +461,10 @@ bool ContentContext::IsValid() const {
return is_valid_;
}

std::shared_ptr<Texture> ContentContext::GetEmptyTexture() const {
return empty_texture_;
}

fml::StatusOr<RenderTarget> ContentContext::MakeSubpass(
std::string_view label,
ISize texture_size,
Expand Down Expand Up @@ -567,22 +584,6 @@ void ContentContext::ClearCachedRuntimeEffectPipeline(
void ContentContext::InitializeCommonlyUsedShadersIfNeeded() const {
TRACE_EVENT0("flutter", "InitializeCommonlyUsedShadersIfNeeded");
GetContext()->InitializeCommonlyUsedShadersIfNeeded();

// On ARM devices, the initial usage of vkCmdCopyBufferToImage has been
// observed to take 10s of ms as an internal shader is compiled to perform
// the operation. Similarly, the initial render pass can also take 10s of ms
// for a similar reason. Because the context object is initialized far
// before the first frame, create a trivial texture and render pass to force
// the driver to compiler these shaders before the frame begins.
TextureDescriptor desc;
desc.size = {1, 1};
desc.storage_mode = StorageMode::kHostVisible;
desc.format = PixelFormat::kR8G8B8A8UNormInt;
auto texture = GetContext()->GetResourceAllocator()->CreateTexture(desc);
uint32_t color = 0;
if (!texture->SetContents(reinterpret_cast<uint8_t*>(&color), 4u)) {
VALIDATION_LOG << "Failed to set bootstrap texture.";
}
}

} // namespace impeller
5 changes: 5 additions & 0 deletions impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,10 @@ class ContentContext {
return GetPipeline(vertices_uber_shader_, opts);
}

// An empty 1x1 texture for binding drawVertices/drawAtlas or other cases
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specify that its a 1x1 black transparent texture so callers can reason about potential issues with sampling and mixing from this empty texture.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// that don't always have a texture (due to blending).
std::shared_ptr<Texture> GetEmptyTexture() const;

std::shared_ptr<Context> GetContext() const;

const Capabilities& GetDeviceCapabilities() const;
Expand Down Expand Up @@ -1034,6 +1038,7 @@ class ContentContext {
#endif // IMPELLER_ENABLE_3D
std::shared_ptr<RenderTargetAllocator> render_target_cache_;
std::shared_ptr<HostBuffer> host_buffer_;
std::shared_ptr<Texture> empty_texture_;
bool wireframe_ = false;

ContentContext(const ContentContext&) = delete;
Expand Down
Loading