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 1 commit
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
Next Next commit
[Impeller] only use porter duff or vertices.uber for drawVertices.
  • Loading branch information
jonahwilliams committed Apr 23, 2024
commit 855da7266ce5db9890da6412e47c1a7b404c2e2b
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 @@ -936,8 +937,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 @@ -960,35 +972,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 @@ -267,7 +267,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
224 changes: 30 additions & 194 deletions impeller/entity/contents/vertices_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/filters/blend_filter_contents.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/geometry/geometry.h"
#include "impeller/entity/geometry/vertices_geometry.h"
#include "impeller/entity/position_color.vert.h"
#include "impeller/entity/vertices.frag.h"
#include "impeller/geometry/color.h"
#include "impeller/renderer/render_pass.h"

Expand Down Expand Up @@ -42,190 +39,6 @@ static std::optional<SamplerAddressMode> TileModeToAddressMode(
}
} // namespace

VerticesContents::VerticesContents() = default;

VerticesContents::~VerticesContents() = default;

std::optional<Rect> VerticesContents::GetCoverage(const Entity& entity) const {
return geometry_->GetCoverage(entity.GetTransform());
};

void VerticesContents::SetGeometry(std::shared_ptr<VerticesGeometry> geometry) {
geometry_ = std::move(geometry);
}

void VerticesContents::SetSourceContents(std::shared_ptr<Contents> contents) {
src_contents_ = std::move(contents);
}

std::shared_ptr<VerticesGeometry> VerticesContents::GetGeometry() const {
return geometry_;
}

void VerticesContents::SetAlpha(Scalar alpha) {
alpha_ = alpha;
}

void VerticesContents::SetBlendMode(BlendMode blend_mode) {
blend_mode_ = blend_mode;
}

const std::shared_ptr<Contents>& VerticesContents::GetSourceContents() const {
return src_contents_;
}

bool VerticesContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
if (blend_mode_ == BlendMode::kClear) {
return true;
}

std::shared_ptr<Contents> src_contents = src_contents_;
src_contents->SetCoverageHint(GetCoverageHint());
if (geometry_->HasTextureCoordinates()) {
auto contents = std::make_shared<VerticesUVContents>(*this);
contents->SetCoverageHint(GetCoverageHint());
if (!geometry_->HasVertexColors()) {
contents->SetAlpha(alpha_);
return contents->Render(renderer, entity, pass);
}
src_contents = contents;
}

auto dst_contents = std::make_shared<VerticesColorContents>(*this);
dst_contents->SetCoverageHint(GetCoverageHint());

std::shared_ptr<Contents> contents;
if (blend_mode_ == BlendMode::kDestination) {
dst_contents->SetAlpha(alpha_);
contents = dst_contents;
} else {
auto color_filter_contents = ColorFilterContents::MakeBlend(
blend_mode_, {FilterInput::Make(dst_contents, false),
FilterInput::Make(src_contents, false)});
color_filter_contents->SetAlpha(alpha_);
color_filter_contents->SetCoverageHint(GetCoverageHint());
contents = color_filter_contents;
}

FML_DCHECK(contents->GetCoverageHint() == GetCoverageHint());
return contents->Render(renderer, entity, pass);
}

//------------------------------------------------------
// VerticesUVContents

VerticesUVContents::VerticesUVContents(const VerticesContents& parent)
: parent_(parent) {}

VerticesUVContents::~VerticesUVContents() {}

std::optional<Rect> VerticesUVContents::GetCoverage(
const Entity& entity) const {
return parent_.GetCoverage(entity);
}

void VerticesUVContents::SetAlpha(Scalar alpha) {
alpha_ = alpha;
}

bool VerticesUVContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = TexturePipeline::VertexShader;
using FS = TexturePipeline::FragmentShader;

auto src_contents = parent_.GetSourceContents();

auto snapshot =
src_contents->RenderToSnapshot(renderer, // renderer
entity, // entity
GetCoverageHint(), // coverage_limit
std::nullopt, // sampler_descriptor
true, // msaa_enabled
/*mip_count=*/1,
"VerticesUVContents Snapshot"); // label
if (!snapshot.has_value()) {
return false;
}

pass.SetCommandLabel("VerticesUV");
auto& host_buffer = renderer.GetTransientsBuffer();
const std::shared_ptr<Geometry>& geometry = parent_.GetGeometry();

auto coverage = src_contents->GetCoverage(Entity{});
if (!coverage.has_value()) {
return false;
}
auto geometry_result = geometry->GetPositionUVBuffer(
coverage.value(), Matrix(), renderer, entity, pass);
auto opts = OptionsFromPassAndEntity(pass, entity);
opts.primitive_type = geometry_result.type;
pass.SetPipeline(renderer.GetTexturePipeline(opts));
pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));

VS::FrameInfo frame_info;
frame_info.mvp = geometry_result.transform;
frame_info.texture_sampler_y_coord_scale =
snapshot->texture->GetYCoordScale();
VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));

FS::FragInfo frag_info;
frag_info.alpha = alpha_ * snapshot->opacity;
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
FS::BindTextureSampler(pass, snapshot->texture,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
snapshot->sampler_descriptor));

return pass.Draw().ok();
}

//------------------------------------------------------
// VerticesColorContents

VerticesColorContents::VerticesColorContents(const VerticesContents& parent)
: parent_(parent) {}

VerticesColorContents::~VerticesColorContents() {}

std::optional<Rect> VerticesColorContents::GetCoverage(
const Entity& entity) const {
return parent_.GetCoverage(entity);
}

void VerticesColorContents::SetAlpha(Scalar alpha) {
alpha_ = alpha;
}

bool VerticesColorContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = GeometryColorPipeline::VertexShader;
using FS = GeometryColorPipeline::FragmentShader;

pass.SetCommandLabel("VerticesColors");
auto& host_buffer = renderer.GetTransientsBuffer();
const std::shared_ptr<VerticesGeometry>& geometry = parent_.GetGeometry();

auto geometry_result =
geometry->GetPositionColorBuffer(renderer, entity, pass);
auto opts = OptionsFromPassAndEntity(pass, entity);
opts.primitive_type = geometry_result.type;
pass.SetPipeline(renderer.GetGeometryColorPipeline(opts));
pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));

VS::FrameInfo frame_info;
frame_info.mvp = geometry_result.transform;
VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));

FS::FragInfo frag_info;
frag_info.alpha = alpha_;
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));

return pass.Draw().ok();
}

//------------------------------------------------------
// VerticesSimpleBlendContents

Expand Down Expand Up @@ -270,15 +83,30 @@ void VerticesSimpleBlendContents::SetEffectTransform(Matrix transform) {
inverse_matrix_ = transform.Invert();
}

void VerticesSimpleBlendContents::SetLazyTexture(
const LazyTexture& lazy_texture) {
lazy_texture_ = lazy_texture;
}

bool VerticesSimpleBlendContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
FML_DCHECK(texture_);
FML_DCHECK(texture_ || lazy_texture_ ||
blend_mode_ == BlendMode::kDestination);
BlendMode blend_mode = blend_mode_;
if (!geometry_->HasVertexColors()) {
blend_mode = BlendMode::kSource;
}

std::shared_ptr<Texture> texture;
if (blend_mode != BlendMode::kDestination) {
if (!texture_) {
texture = lazy_texture_(renderer);
} else {
texture = texture_;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Nit: If the texture is nullptr here, set it to the empty texture right away so you don't have to do all the null checks later? Stuff like the size, y scale coord, etc. will just work without additional checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh good idea 👍

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


auto dst_sampler_descriptor = descriptor_;
dst_sampler_descriptor.width_address_mode =
TileModeToAddressMode(tile_mode_x_, renderer.GetDeviceCapabilities())
Expand All @@ -292,8 +120,8 @@ bool VerticesSimpleBlendContents::Render(const ContentContext& renderer,
dst_sampler_descriptor);

GeometryResult geometry_result = geometry_->GetPositionUVColorBuffer(
Rect::MakeSize(texture_->GetSize()), inverse_matrix_, renderer, entity,
pass);
(!!texture) ? Rect::MakeSize(texture->GetSize()) : Rect{},
inverse_matrix_, renderer, entity, pass);
if (geometry_result.vertex_buffer.vertex_count == 0) {
return true;
}
Expand All @@ -313,12 +141,16 @@ bool VerticesSimpleBlendContents::Render(const ContentContext& renderer,
options.primitive_type = geometry_result.type;
pass.SetPipeline(renderer.GetPorterDuffBlendPipeline(options));

FS::BindTextureSamplerDst(pass, texture_, dst_sampler);
if (texture) {
FS::BindTextureSamplerDst(pass, texture, dst_sampler);
}

VS::FrameInfo frame_info;
FS::FragInfo frag_info;

frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
if (texture) {
frame_info.texture_sampler_y_coord_scale = texture->GetYCoordScale();
}
frame_info.mvp = geometry_result.transform;

frag_info.output_alpha = alpha_;
Expand Down Expand Up @@ -356,12 +188,16 @@ bool VerticesSimpleBlendContents::Render(const ContentContext& renderer,
auto options = OptionsFromPassAndEntity(pass, entity);
options.primitive_type = geometry_result.type;
pass.SetPipeline(renderer.GetDrawVerticesUberShader(options));
FS::BindTextureSampler(pass, texture_, dst_sampler);
if (texture) {
FS::BindTextureSampler(pass, texture, dst_sampler);
}

VS::FrameInfo frame_info;
FS::FragInfo frag_info;

frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
if (texture) {
frame_info.texture_sampler_y_coord_scale = texture->GetYCoordScale();
}
frame_info.mvp = geometry_result.transform;
frag_info.alpha = alpha_;
frag_info.blend_mode = static_cast<int>(blend_mode);
Expand Down
Loading