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
16 changes: 16 additions & 0 deletions impeller/core/host_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,22 @@ BufferView HostBuffer::Emplace(const void* buffer, size_t length) {
return BufferView{shared_from_this(), GetBuffer(), Range{old_length, length}};
}

BufferView HostBuffer::Emplace(size_t length,
size_t align,
const EmplaceProc& cb) {
if (!cb) {
return {};
}
auto old_length = GetLength();
if (!Truncate(old_length + length)) {
return {};
}
generation_++;
cb(GetBuffer() + old_length);
Copy link
Member

Choose a reason for hiding this comment

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

Emplace and EmplaceCallback can be dried up by making Emplace call EmplaceCallback with a callback that does the memmove.

Copy link
Member

Choose a reason for hiding this comment

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

Also, let's check that CB is valid. If not, emplacing undefined data is fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

Alternatively consider making this return a std::pair

Copy link
Contributor

Choose a reason for hiding this comment

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

e.g. std::pair<BufferView, uintptr_t> Reserve(size_t length, size_t align); and then on this line you

return std::make_pair(BufferView{...}, GetBuffer() + old_length);

Copy link
Contributor

Choose a reason for hiding this comment

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

Emplace could still be dried up as Chinmay is suggesting to internally call Reserve and use the pointer.


return BufferView{shared_from_this(), GetBuffer(), Range{old_length, length}};
}

std::shared_ptr<const DeviceBuffer> HostBuffer::GetDeviceBuffer(
Allocator& allocator) const {
if (generation_ == device_buffer_generation_) {
Expand Down
16 changes: 16 additions & 0 deletions impeller/core/host_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,22 @@ class HostBuffer final : public std::enable_shared_from_this<HostBuffer>,
size_t length,
size_t align);

using EmplaceProc = std::function<void(uint8_t* buffer)>;

//----------------------------------------------------------------------------
/// @brief Emplaces undefined data onto the managed buffer and gives the
/// caller a chance to update it using the specified callback. The
/// buffer is guaranteed to have enough space for length bytes. It
/// is the responsibility of the caller to not exceed the bounds
/// of the buffer returned in the EmplaceProc.
///
/// @param[in] cb A callback that will be passed a ptr to the
/// underlying host buffer.
///
/// @return The buffer view.
///
BufferView Emplace(size_t length, size_t align, const EmplaceProc& cb);

private:
mutable std::shared_ptr<DeviceBuffer> device_buffer_;
mutable size_t device_buffer_generation_ = 0u;
Expand Down
98 changes: 48 additions & 50 deletions impeller/entity/contents/text_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,60 +135,58 @@ static bool CommonRender(const ContentContext& renderer,
// interpolated vertex information is also used in the fragment shader to
// sample from the glyph atlas.

constexpr std::array<Point, 4> unit_points = {Point{0, 0}, Point{1, 0},
constexpr std::array<Point, 6> unit_points = {Point{0, 0}, Point{1, 0},
Point{0, 1}, Point{1, 0},
Point{0, 1}, Point{1, 1}};
constexpr std::array<uint32_t, 6> indices = {0, 1, 2, 1, 2, 3};

VertexBufferBuilder<typename VS::PerVertexData> vertex_builder;

size_t count = 0;
for (const auto& run : frame.GetRuns()) {
count += run.GetGlyphPositions().size();
}

vertex_builder.Reserve(count * 4);
vertex_builder.ReserveIndices(count * 6);

uint32_t index_offset = 0u;
for (auto i = 0u; i < count; i++) {
for (const auto& index : indices) {
vertex_builder.AppendIndex(index + index_offset);
}
index_offset += 4;
}

auto& host_buffer = pass.GetTransientsBuffer();
size_t vertex_count = 0;
for (const auto& run : frame.GetRuns()) {
const Font& font = run.GetFont();

for (const auto& glyph_position : run.GetGlyphPositions()) {
FontGlyphPair font_glyph_pair{font, glyph_position.glyph};
auto atlas_glyph_bounds = atlas->FindFontGlyphBounds(font_glyph_pair);
if (!atlas_glyph_bounds.has_value()) {
VALIDATION_LOG << "Could not find glyph position in the atlas.";
return false;
}
Vector4 atlas_glyph_bounds_vec = Vector4(
atlas_glyph_bounds->origin.x, atlas_glyph_bounds->origin.y,
atlas_glyph_bounds->size.width, atlas_glyph_bounds->size.height);
Vector4 glyph_bounds_vec =
Vector4(glyph_position.glyph.bounds.origin.x,
glyph_position.glyph.bounds.origin.y,
glyph_position.glyph.bounds.size.width,
glyph_position.glyph.bounds.size.height);

for (const auto& point : unit_points) {
vertex_builder.AppendVertex(VS::PerVertexData{
.atlas_glyph_bounds = atlas_glyph_bounds_vec,
.glyph_bounds = glyph_bounds_vec,
.unit_position = point,
.glyph_position = glyph_position.position,
});
}
}
vertex_count += run.GetGlyphPositions().size();
}
auto vertex_buffer =
vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer());
cmd.BindVertices(vertex_buffer);
vertex_count *= 6;

auto buffer_view = host_buffer.Emplace(
vertex_count * sizeof(VS::PerVertexData), alignof(VS::PerVertexData),
[&](uint8_t* contents) {
VS::PerVertexData vtx;
size_t vertex_offset = 0;
for (const auto& run : frame.GetRuns()) {
const Font& font = run.GetFont();
for (const auto& glyph_position : run.GetGlyphPositions()) {
FontGlyphPair font_glyph_pair{font, glyph_position.glyph};
auto maybe_atlas_glyph_bounds =
atlas->FindFontGlyphBounds(font_glyph_pair);
if (!maybe_atlas_glyph_bounds.has_value()) {
VALIDATION_LOG << "Could not find glyph position in the atlas.";
continue;
}
auto atlas_glyph_bounds = maybe_atlas_glyph_bounds.value();
vtx.atlas_glyph_bounds = Vector4(
atlas_glyph_bounds.origin.x, atlas_glyph_bounds.origin.y,
atlas_glyph_bounds.size.width, atlas_glyph_bounds.size.height);
vtx.glyph_bounds = Vector4(glyph_position.glyph.bounds.origin.x,
glyph_position.glyph.bounds.origin.y,
glyph_position.glyph.bounds.size.width,
glyph_position.glyph.bounds.size.height);
vtx.glyph_position = glyph_position.position;

for (const auto& point : unit_points) {
vtx.unit_position = point;
::memcpy(contents + vertex_offset, &vtx,
sizeof(VS::PerVertexData));
vertex_offset += sizeof(VS::PerVertexData);
}
}
}
});

cmd.BindVertices({
.vertex_buffer = buffer_view,
.index_buffer = {},
.vertex_count = vertex_count,
.index_type = IndexType::kNone,
});

return pass.AddCommand(cmd);
}
Expand Down