Skip to content

Commit

Permalink
simplify vertex accumulation
Browse files Browse the repository at this point in the history
  • Loading branch information
flar committed Nov 22, 2023
1 parent 92b97fd commit 24811cf
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 92 deletions.
38 changes: 16 additions & 22 deletions impeller/entity/geometry/ellipse_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,19 @@ GeometryResult EllipseGeometry::GetPositionBuffer(
RenderPass& pass) {
auto& host_buffer = pass.GetTransientsBuffer();

VertexBufferBuilder<SolidFillVertexShader::PerVertexData> vtx_builder;

CircleTessellator tessellator(entity.GetTransformation(), radius_);
auto vertices = std::vector<Point>(tessellator.GetCircleVertexCount());
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateCircleTriangleStrip(
[&vertices](const Point& p) { vertices.push_back(p); }, center_, radius_);
[&vtx_builder](const Point& p) { //
vtx_builder.AppendVertex({.position = p});
},
center_, radius_);

return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer =
{
.vertex_buffer = host_buffer.Emplace(
vertices.data(), vertices.size() * sizeof(Point),
alignof(float)),
.vertex_count = vertices.size(),
.index_type = IndexType::kNone,
},
.vertex_buffer = vtx_builder.CreateVertexBuffer(host_buffer),
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation(),
.prevent_overdraw = false,
Expand All @@ -53,26 +51,22 @@ GeometryResult EllipseGeometry::GetPositionUVBuffer(

auto uv_transform =
texture_coverage.GetNormalizingTransform() * effect_transform;
VertexBufferBuilder<TextureFillVertexShader::PerVertexData> vtx_builder;

CircleTessellator tessellator(entity.GetTransformation(), radius_);
auto vertices = std::vector<Point>(tessellator.GetCircleVertexCount());
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateCircleTriangleStrip(
[&vertices, &uv_transform](const Point& p) {
vertices.push_back(p);
vertices.push_back(uv_transform * p);
[&vtx_builder, &uv_transform](const Point& p) {
vtx_builder.AppendVertex({
.position = p,
.texture_coords = uv_transform * p,
});
},
center_, radius_);

return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer =
{
.vertex_buffer = host_buffer.Emplace(
vertices.data(), vertices.size() * sizeof(Point),
alignof(float)),
.vertex_count = vertices.size() / 2,
.index_type = IndexType::kNone,
},
.vertex_buffer = vtx_builder.CreateVertexBuffer(host_buffer),
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation(),
.prevent_overdraw = false,
Expand Down
71 changes: 28 additions & 43 deletions impeller/entity/geometry/line_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,44 +70,37 @@ bool LineGeometry::ComputeCorners(Point corners[4],
GeometryResult LineGeometry::GetPositionBuffer(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) {
std::vector<Point> vertices;
auto& transform = entity.GetTransformation();
auto radius = ComputeHalfWidth(transform);

VertexBufferBuilder<SolidFillVertexShader::PerVertexData> vtx_builder;

if (cap_ == Cap::kRound) {
CircleTessellator tessellator(transform, radius);
vertices.reserve(tessellator.GetCircleVertexCount());
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateRoundCapLineTriangleStrip(
[&vertices](const Point& p) { //
vertices.push_back(p);
[&vtx_builder](const Point& p) { //
vtx_builder.AppendVertex({.position = p});
},
p0_, p1_, radius);
} else {
Point corners[4];
if (ComputeCorners(corners, transform, cap_ == Cap::kSquare)) {
vertices.reserve(4);
vertices.push_back(corners[0]);
vertices.push_back(corners[1]);
vertices.push_back(corners[2]);
vertices.push_back(corners[3]);
vtx_builder.Reserve(4);
vtx_builder.AppendVertex({.position = corners[0]});
vtx_builder.AppendVertex({.position = corners[1]});
vtx_builder.AppendVertex({.position = corners[2]});
vtx_builder.AppendVertex({.position = corners[3]});
}
}
if (vertices.empty()) {
if (!vtx_builder.HasVertices()) {
return {};
}

static_assert(sizeof(Point) == 2 * sizeof(float));
static_assert(alignof(Point) == alignof(float));
return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer =
{
.vertex_buffer = pass.GetTransientsBuffer().Emplace(
vertices.data(), vertices.size() * sizeof(Point),
alignof(Point)),
.vertex_count = vertices.size(),
.index_type = IndexType::kNone,
},
vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation(),
.prevent_overdraw = false,
Expand All @@ -120,52 +113,44 @@ GeometryResult LineGeometry::GetPositionUVBuffer(Rect texture_coverage,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) {
std::vector<Point> vertices;
auto& transform = entity.GetTransformation();
auto radius = ComputeHalfWidth(transform);

auto uv_transform =
texture_coverage.GetNormalizingTransform() * effect_transform;
VertexBufferBuilder<TextureFillVertexShader::PerVertexData> vtx_builder;

if (cap_ == Cap::kRound) {
CircleTessellator tessellator(transform, radius);
vertices.reserve(tessellator.GetCircleVertexCount() * 2);
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateRoundCapLineTriangleStrip(
[&vertices, &uv_transform](const Point& p) {
vertices.push_back(p);
vertices.push_back(uv_transform * p);
[&vtx_builder, &uv_transform](const Point& p) {
vtx_builder.AppendVertex({
.position = p,
.texture_coords = uv_transform * p,
});
},
p0_, p1_, radius);
} else {
Point corners[4];
if (ComputeCorners(corners, transform, cap_ == Cap::kSquare)) {
vertices.reserve(8);
vertices.push_back(corners[0]);
vertices.push_back(uv_transform * corners[0]);
vertices.push_back(corners[1]);
vertices.push_back(uv_transform * corners[1]);
vertices.push_back(corners[2]);
vertices.push_back(uv_transform * corners[2]);
vertices.push_back(corners[3]);
vertices.push_back(uv_transform * corners[3]);
vtx_builder.Reserve(4);
for (auto& corner : corners) {
vtx_builder.AppendVertex({
.position = corner,
.texture_coords = uv_transform * corner,
});
}
}
}
if (vertices.empty()) {
if (!vtx_builder.HasVertices()) {
return {};
}

static_assert(sizeof(Point) == 2 * sizeof(float));
static_assert(alignof(Point) == alignof(float));
return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer =
{
.vertex_buffer = pass.GetTransientsBuffer().Emplace(
vertices.data(), vertices.size() * sizeof(Point),
alignof(Point)),
.vertex_count = vertices.size() / 2,
.index_type = IndexType::kNone,
},
vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation(),
.prevent_overdraw = false,
Expand Down
49 changes: 22 additions & 27 deletions impeller/entity/geometry/point_field_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,48 +89,43 @@ PointFieldGeometry::GetPositionBufferCPU(const ContentContext& renderer,
if (round_) {
CircleTessellator tessellator(entity.GetTransformation(), radius);

// Get polygon relative to {0, 0} so we can translate it to each point
// in turn.
std::vector<Point> vertices;
// Get triangulation relative to {0, 0} so we can translate it to each
// point in turn.
std::vector<Point> circle_vertices;
circle_vertices.reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateCircleTriangleStrip(
[&vertices](const Point& p) { //
vertices.push_back(p);
[&circle_vertices](const Point& p) { //
circle_vertices.push_back(p);
},
{}, radius);
FML_DCHECK(vertices.size() == tessellator.GetCircleVertexCount());
vtx_builder.Reserve(vertices.size() * points_.size());
FML_DCHECK(circle_vertices.size() == tessellator.GetCircleVertexCount());

bool first = true;
Point prev;
vtx_builder.Reserve((circle_vertices.size() + 2) * points_.size() - 2);
for (auto& center : points_) {
if (first) {
first = false;
} else {
vtx_builder.AppendVertex({prev});
vtx_builder.AppendVertex({center + vertices[0]});
if (vtx_builder.HasVertices()) {
vtx_builder.AppendVertex(vtx_builder.Last());
vtx_builder.AppendVertex({center + circle_vertices[0]});
}
for (auto& vertex : vertices) {
prev = center + vertex;
vtx_builder.AppendVertex({prev});

for (auto& vertex : circle_vertices) {
vtx_builder.AppendVertex({center + vertex});
}
}
} else {
vtx_builder.Reserve(6 * points_.size());
bool first = true;
Point prev;
vtx_builder.Reserve(6 * points_.size() - 2);
for (auto& point : points_) {
if (first) {
first = false;
} else {
vtx_builder.AppendVertex({prev});
vtx_builder.AppendVertex({{point.x - radius, point.y - radius}});
auto first = Point(point.x - radius, point.y - radius);

if (vtx_builder.HasVertices()) {
vtx_builder.AppendVertex(vtx_builder.Last());
vtx_builder.AppendVertex({first});
}

// Z pattern from UL -> UR -> LL -> LR
vtx_builder.AppendVertex({{point.x - radius, point.y - radius}});
vtx_builder.AppendVertex({first});
vtx_builder.AppendVertex({{point.x + radius, point.y - radius}});
vtx_builder.AppendVertex({{point.x - radius, point.y + radius}});
vtx_builder.AppendVertex({prev = {point.x + radius, point.y + radius}});
vtx_builder.AppendVertex({{point.x + radius, point.y + radius}});
}
}

Expand Down
5 changes: 5 additions & 0 deletions impeller/renderer/vertex_buffer_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class VertexBufferBuilder {
return indices_.size() > 0 ? indices_.size() : vertices_.size();
}

const VertexType& Last() const {
FML_DCHECK(!vertices_.empty());
return vertices_.back();
}

VertexBufferBuilder& AppendVertex(VertexType_ vertex) {
vertices_.emplace_back(std::move(vertex));
return *this;
Expand Down

0 comments on commit 24811cf

Please sign in to comment.