Repository navigation
[Impeller] small cpu perf for text contents. #166199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -108,8 +108,7 @@ void TextContents::ComputeVertexData( | |
| // interpolated vertex information is also used in the fragment shader to | ||
| // sample from the glyph atlas. | ||
|
|
||
| constexpr std::array<Point, 6> unit_points = {Point{0, 0}, Point{1, 0}, | ||
| Point{0, 1}, Point{1, 0}, | ||
| constexpr std::array<Point, 4> unit_points = {Point{0, 0}, Point{1, 0}, | ||
| Point{0, 1}, Point{1, 1}}; | ||
|
|
||
| ISize atlas_size = atlas->GetTexture()->GetSize(); | ||
|
|
@@ -119,9 +118,19 @@ void TextContents::ComputeVertexData( | |
| VS::PerVertexData vtx; | ||
| size_t i = 0u; | ||
| size_t bounds_offset = 0u; | ||
| Rational rounded_scale = frame->GetScale(); | ||
| Scalar inverted_rounded_scale = static_cast<Scalar>(rounded_scale.Invert()); | ||
| Matrix unscaled_basis = | ||
| basis_transform * | ||
| Matrix::MakeScale({inverted_rounded_scale, inverted_rounded_scale, 1}); | ||
|
|
||
| // In typical scales < 48x these values should be -1 or 1. We round to | ||
| // those to avoid inaccuracies. | ||
| unscaled_basis.m[0] = AttractToOne(unscaled_basis.m[0]); | ||
| unscaled_basis.m[5] = AttractToOne(unscaled_basis.m[5]); | ||
|
|
||
| for (const TextRun& run : frame->GetRuns()) { | ||
| const Font& font = run.GetFont(); | ||
| Rational rounded_scale = frame->GetScale(); | ||
| const Matrix transform = frame->GetOffsetTransform(); | ||
| FontGlyphAtlas* font_atlas = nullptr; | ||
|
|
||
|
|
@@ -181,26 +190,15 @@ void TextContents::ComputeVertexData( | |
| atlas_glyph_bounds = maybe_atlas_glyph_bounds.value().atlas_bounds; | ||
| } | ||
|
|
||
| Scalar inverted_rounded_scale = | ||
| static_cast<Scalar>(rounded_scale.Invert()); | ||
| Rect scaled_bounds = glyph_bounds.Scale(inverted_rounded_scale); | ||
| // For each glyph, we compute two rectangles. One for the vertex | ||
| // positions and one for the texture coordinates (UVs). The atlas | ||
| // glyph bounds are used to compute UVs in cases where the | ||
| // destination and source sizes may differ due to clamping the sizes | ||
| // of large glyphs. | ||
| Point uv_origin = (atlas_glyph_bounds.GetLeftTop()) / atlas_size; | ||
| Point uv_origin = atlas_glyph_bounds.GetLeftTop() / atlas_size; | ||
| Point uv_size = SizeToPoint(atlas_glyph_bounds.GetSize()) / atlas_size; | ||
|
|
||
| Matrix unscaled_basis = | ||
| basis_transform * Matrix::MakeScale({inverted_rounded_scale, | ||
| inverted_rounded_scale, 1}); | ||
|
|
||
| // In typical scales < 48x these values should be -1 or 1. We round to | ||
| // those to avoid inaccuracies. | ||
| unscaled_basis.m[0] = AttractToOne(unscaled_basis.m[0]); | ||
| unscaled_basis.m[5] = AttractToOne(unscaled_basis.m[5]); | ||
|
|
||
| Point unrounded_glyph_position = | ||
| // This is for RTL text. | ||
| unscaled_basis * glyph_bounds.GetLeftTop() + | ||
|
|
@@ -231,12 +229,12 @@ void TextContents::ComputeVertexData( | |
| bool TextContents::Render(const ContentContext& renderer, | ||
| const Entity& entity, | ||
| RenderPass& pass) const { | ||
| auto color = GetColor(); | ||
| Color color = GetColor(); | ||
| if (color.IsTransparent()) { | ||
| return true; | ||
| } | ||
|
|
||
| auto type = frame_->GetAtlasType(); | ||
| GlyphAtlas::Type type = frame_->GetAtlasType(); | ||
| const std::shared_ptr<GlyphAtlas>& atlas = | ||
| renderer.GetLazyGlyphAtlas()->CreateOrGetGlyphAtlas( | ||
| *renderer.GetContext(), renderer.GetTransientsBuffer(), type); | ||
|
|
@@ -298,26 +296,45 @@ bool TextContents::Render(const ContentContext& renderer, | |
| sampler_desc) // sampler | ||
| ); | ||
|
|
||
| auto& host_buffer = renderer.GetTransientsBuffer(); | ||
| size_t vertex_count = 0; | ||
| HostBuffer& host_buffer = renderer.GetTransientsBuffer(); | ||
| size_t glyph_count = 0; | ||
| for (const auto& run : frame_->GetRuns()) { | ||
| vertex_count += run.GetGlyphPositions().size(); | ||
| glyph_count += run.GetGlyphPositions().size(); | ||
| } | ||
| vertex_count *= 6; | ||
| size_t vertex_count = glyph_count * 4; | ||
| size_t index_count = glyph_count * 6; | ||
|
|
||
| BufferView buffer_view = host_buffer.Emplace( | ||
| vertex_count * sizeof(VS::PerVertexData), alignof(VS::PerVertexData), | ||
| [&](uint8_t* contents) { | ||
| [&](uint8_t* data) { | ||
| VS::PerVertexData* vtx_contents = | ||
| reinterpret_cast<VS::PerVertexData*>(contents); | ||
| ComputeVertexData(vtx_contents, frame_, scale_, | ||
| /*entity_transform=*/entity_transform, offset_, | ||
| GetGlyphProperties(), atlas); | ||
| reinterpret_cast<VS::PerVertexData*>(data); | ||
| ComputeVertexData(/*vtx_contents=*/vtx_contents, | ||
| /*frame=*/frame_, | ||
| /*scale=*/scale_, | ||
| /*entity_transform=*/entity_transform, | ||
| /*offset=*/offset_, | ||
| /*glyph_properties=*/GetGlyphProperties(), | ||
| /*atlas=*/atlas); | ||
| }); | ||
| BufferView index_buffer_view = host_buffer.Emplace( | ||
| index_count * sizeof(uint16_t), alignof(uint16_t), [&](uint8_t* data) { | ||
| uint16_t* indices = reinterpret_cast<uint16_t*>(data); | ||
| size_t j = 0; | ||
| for (auto i = 0u; i < glyph_count; i++) { | ||
| size_t base = i * 4; | ||
| indices[j++] = base + 0; | ||
| indices[j++] = base + 1; | ||
| indices[j++] = base + 2; | ||
| indices[j++] = base + 1; | ||
| indices[j++] = base + 2; | ||
| indices[j++] = base + 3; | ||
|
Comment on lines
+326
to
+331
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Switching to triangle strip would be more efficient.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The glyph rects aren't connected, so switching to strip would be move overall geometry: Before: 6 pts |
||
| } | ||
| }); | ||
|
|
||
| pass.SetVertexBuffer(std::move(buffer_view)); | ||
| pass.SetIndexBuffer({}, IndexType::kNone); | ||
| pass.SetElementCount(vertex_count); | ||
| pass.SetIndexBuffer(index_buffer_view, IndexType::k16bit); | ||
| pass.SetElementCount(index_count); | ||
|
|
||
| return pass.Draw().ok(); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has to loop through everything twice. Why not calculate the index buffer in the ComputeVertexData's loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the way the emplace callback works, we can't easy emplace into two buffers at once unless I copy everything. I think this is still OK.