Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Prev Previous commit
Next Next commit
move to direct HostBuffer emplacement of tessellation results
  • Loading branch information
flar committed Nov 30, 2023
commit 4b638ba6f8add217c2a37d7046f8c8e0027cb652
11 changes: 6 additions & 5 deletions impeller/entity/geometry/circle_tessellator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace impeller {

std::vector<Trig> CircleTessellator::trigs_[MAX_DIVISIONS_ + 1];
std::vector<Trig> CircleTessellator::trigs_[kMaxDivisions + 1];

size_t CircleTessellator::ComputeQuadrantDivisions(Scalar pixel_radius) {
// Note: these values are approximated based on the values returned from
Expand All @@ -26,16 +26,17 @@ size_t CircleTessellator::ComputeQuadrantDivisions(Scalar pixel_radius) {
return 9;
}
pixel_radius /= 4;
if (pixel_radius > (MAX_DIVISIONS_ - 1)) {
return MAX_DIVISIONS_;
if (pixel_radius > (kMaxDivisions - 1)) {
return kMaxDivisions;
}
return static_cast<int>(ceil(pixel_radius));
return static_cast<size_t>(ceil(pixel_radius));
}

const std::vector<Trig>& CircleTessellator::GetTrigForDivisions(
size_t divisions) {
FML_DCHECK(divisions > 0 && divisions <= MAX_DIVISIONS_);
FML_DCHECK(divisions > 0 && divisions <= kMaxDivisions);
std::vector<Trig>& trigs = trigs_[divisions];
trigs.reserve(divisions + 1);

if (trigs.empty()) {
double angle_scale = kPiOver2 / divisions;
Expand Down
7 changes: 4 additions & 3 deletions impeller/entity/geometry/circle_tessellator.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace impeller {
/// @brief A structure to store the sine and cosine of an angle.
struct Trig {
/// Construct a Trig object from a given angle in radians.
Trig(Radians r) : cos(std::cos(r.radians)), sin(std::sin(r.radians)) {}
explicit Trig(Radians r)
: cos(std::cos(r.radians)), sin(std::sin(r.radians)) {}

/// Construct a Trig object from the given cosine and sine values.
Trig(double cos, double sin) : cos(cos), sin(sin) {}
Expand Down Expand Up @@ -128,9 +129,9 @@ class CircleTessellator {
/// @return The vector of (divisions + 1) trig values.
static const std::vector<Trig>& GetTrigForDivisions(size_t divisions);

static constexpr int MAX_DIVISIONS_ = 35;
static constexpr int kMaxDivisions = 35;

static std::vector<Trig> trigs_[MAX_DIVISIONS_ + 1];
static std::vector<Trig> trigs_[kMaxDivisions + 1];
};

} // namespace impeller
67 changes: 46 additions & 21 deletions impeller/entity/geometry/ellipse_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,33 @@ GeometryResult EllipseGeometry::GetPositionBuffer(
const Entity& entity,
RenderPass& pass) const {
auto& host_buffer = pass.GetTransientsBuffer();
using VT = SolidFillVertexShader::PerVertexData;

VertexBufferBuilder<SolidFillVertexShader::PerVertexData> vtx_builder;

Scalar radius = radius_;
const Point& center = center_;
CircleTessellator tessellator(entity.GetTransform(), radius_);
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateCircleTriangleStrip(
[&vtx_builder](const Point& p) { //
vtx_builder.AppendVertex({.position = p});
},
center_, radius_);
size_t count = tessellator.GetCircleVertexCount();
auto vertex_buffer =
host_buffer.Emplace(count * sizeof(VT), alignof(VT),
[&tessellator, &center, radius](uint8_t* buffer) {
auto vertices = reinterpret_cast<VT*>(buffer);
tessellator.GenerateCircleTriangleStrip(
[&vertices](const Point& p) { //
*vertices++ = {
.position = p,
};
},
center, radius);
});

return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer = vtx_builder.CreateVertexBuffer(host_buffer),
.vertex_buffer =
{
.vertex_buffer = vertex_buffer,
.vertex_count = count,
.index_type = IndexType::kNone,
},
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransform(),
.prevent_overdraw = false,
Expand All @@ -46,25 +59,37 @@ GeometryResult EllipseGeometry::GetPositionUVBuffer(
const Entity& entity,
RenderPass& pass) const {
auto& host_buffer = pass.GetTransientsBuffer();

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

Scalar radius = radius_;
const Point& center = center_;
CircleTessellator tessellator(entity.GetTransform(), radius_);
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateCircleTriangleStrip(
[&vtx_builder, &uv_transform](const Point& p) {
vtx_builder.AppendVertex({
.position = p,
.texture_coords = uv_transform * p,
});
},
center_, radius_);
size_t count = tessellator.GetCircleVertexCount();
auto vertex_buffer = host_buffer.Emplace(
count * sizeof(VT), alignof(VT),
[&tessellator, &uv_transform, &center, radius](uint8_t* buffer) {
auto vertices = reinterpret_cast<VT*>(buffer);
tessellator.GenerateCircleTriangleStrip(
[&vertices, &uv_transform](const Point& p) { //
*vertices++ = {
.position = p,
.texture_coords = uv_transform * p,
};
},
center, radius);
});

return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer = vtx_builder.CreateVertexBuffer(host_buffer),
.vertex_buffer =
{
.vertex_buffer = vertex_buffer,
.vertex_count = count,
.index_type = IndexType::kNone,
},
// .vertex_buffer = vtx_builder.CreateVertexBuffer(host_buffer),
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransform(),
.prevent_overdraw = false,
Expand Down
117 changes: 79 additions & 38 deletions impeller/entity/geometry/line_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,37 +68,58 @@ bool LineGeometry::ComputeCorners(Point corners[4],
GeometryResult LineGeometry::GetPositionBuffer(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
auto& host_buffer = pass.GetTransientsBuffer();
using VT = SolidFillVertexShader::PerVertexData;

auto& transform = entity.GetTransform();
auto radius = ComputeHalfWidth(transform);

VertexBufferBuilder<SolidFillVertexShader::PerVertexData> vtx_builder;

size_t count;
BufferView vertex_buffer;
if (cap_ == Cap::kRound) {
const Point& p0 = p0_;
const Point& p1 = p1_;

CircleTessellator tessellator(transform, radius);
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateRoundCapLineTriangleStrip(
[&vtx_builder](const Point& p) { //
vtx_builder.AppendVertex({.position = p});
},
p0_, p1_, radius);
count = tessellator.GetCircleVertexCount();
vertex_buffer =
host_buffer.Emplace(count * sizeof(VT), alignof(VT),
[&tessellator, &p0, &p1, radius](uint8_t* buffer) {
auto vertices = reinterpret_cast<VT*>(buffer);
tessellator.GenerateRoundCapLineTriangleStrip(
[&vertices](const Point& p) { //
*vertices++ = {
.position = p,
};
},
p0, p1, radius);
});
} else {
Point corners[4];
if (ComputeCorners(corners, transform, cap_ == Cap::kSquare)) {
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]});
count = 4;
vertex_buffer = host_buffer.Emplace(
count * sizeof(VT), alignof(VT), [&corners](uint8_t* buffer) {
auto vertices = reinterpret_cast<VT*>(buffer);
for (auto& corner : corners) {
*vertices++ = {
.position = corner,
};
}
});
} else {
return {};
}
}
if (!vtx_builder.HasVertices()) {
return {};
}

return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer =
vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
{
.vertex_buffer = vertex_buffer,
.vertex_count = count,
.index_type = IndexType::kNone,
},
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransform(),
.prevent_overdraw = false,
Expand All @@ -111,44 +132,64 @@ GeometryResult LineGeometry::GetPositionUVBuffer(Rect texture_coverage,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
auto& host_buffer = pass.GetTransientsBuffer();
using VT = TextureFillVertexShader::PerVertexData;

auto& transform = entity.GetTransform();
auto radius = ComputeHalfWidth(transform);

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

size_t count;
BufferView vertex_buffer;
if (cap_ == Cap::kRound) {
const Point& p0 = p0_;
const Point& p1 = p1_;

CircleTessellator tessellator(transform, radius);
vtx_builder.Reserve(tessellator.GetCircleVertexCount());
tessellator.GenerateRoundCapLineTriangleStrip(
[&vtx_builder, &uv_transform](const Point& p) {
vtx_builder.AppendVertex({
.position = p,
.texture_coords = uv_transform * p,
});
},
p0_, p1_, radius);
count = tessellator.GetCircleVertexCount();
vertex_buffer = host_buffer.Emplace(
count * sizeof(VT), alignof(VT),
[&tessellator, &uv_transform, &p0, &p1, radius](uint8_t* buffer) {
auto vertices = reinterpret_cast<VT*>(buffer);
tessellator.GenerateRoundCapLineTriangleStrip(
[&vertices, &uv_transform](const Point& p) { //
*vertices++ = {
.position = p,
.texture_coords = uv_transform * p,
};
},
p0, p1, radius);
});
} else {
Point corners[4];
if (ComputeCorners(corners, transform, cap_ == Cap::kSquare)) {
vtx_builder.Reserve(4);
for (auto& corner : corners) {
vtx_builder.AppendVertex({
.position = corner,
.texture_coords = uv_transform * corner,
});
}
count = 4;
vertex_buffer =
host_buffer.Emplace(count * sizeof(VT), alignof(VT),
[&uv_transform, &corners](uint8_t* buffer) {
auto vertices = reinterpret_cast<VT*>(buffer);
for (auto& corner : corners) {
*vertices++ = {
.position = corner,
.texture_coords = uv_transform * corner,
};
}
});
} else {
return {};
}
}
if (!vtx_builder.HasVertices()) {
return {};
}

return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer =
vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
{
.vertex_buffer = vertex_buffer,
.vertex_count = count,
.index_type = IndexType::kNone,
},
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransform(),
.prevent_overdraw = false,
Expand Down