diff --git a/impeller/entity/contents/text_contents.cc b/impeller/entity/contents/text_contents.cc index 8b4e698183025..d61c0d6a0733f 100644 --- a/impeller/entity/contents/text_contents.cc +++ b/impeller/entity/contents/text_contents.cc @@ -67,7 +67,7 @@ bool TextContents::Render(const ContentContext& renderer, // Information shared by all glyph draw calls. Command cmd; - cmd.label = "Glyph"; + cmd.label = "TextRun"; cmd.primitive_type = PrimitiveType::kTriangle; cmd.pipeline = renderer.GetGlyphAtlasPipeline(OptionsFromPassAndEntity(pass, entity)); @@ -121,8 +121,20 @@ bool TextContents::Render(const ContentContext& renderer, cmd.BindVertices(std::move(vertex_buffer)); } + size_t instance_count = 0u; + std::vector glyph_positions; + std::vector glyph_sizes; + std::vector atlas_positions; + std::vector atlas_glyph_sizes; + // Iterate through all the runs in the blob. for (const auto& run : frame_.GetRuns()) { + instance_count = 0u; + glyph_positions.clear(); + glyph_sizes.clear(); + atlas_positions.clear(); + atlas_glyph_sizes.clear(); + auto font = run.GetFont(); auto glyph_size = ISize::Ceil(font.GetMetrics().GetBoundingBox().size); // Draw each glyph individually. This should probably be batched. @@ -133,21 +145,29 @@ bool TextContents::Render(const ContentContext& renderer, VALIDATION_LOG << "Could not find glyph position in the atlas."; return false; } + instance_count++; + glyph_positions.emplace_back(glyph_position.position.Translate( + {font.GetMetrics().min_extent.x, font.GetMetrics().ascent, 0.0})); + glyph_sizes.emplace_back(Point{static_cast(glyph_size.width), + static_cast(glyph_size.height)}); + atlas_positions.emplace_back(atlas_glyph_pos->origin); + atlas_glyph_sizes.emplace_back( + Point{atlas_glyph_pos->size.width, atlas_glyph_pos->size.height}); + } - VS::GlyphInfo glyph_info; - glyph_info.position = glyph_position.position.Translate( - {font.GetMetrics().min_extent.x, font.GetMetrics().ascent, 0.0}); - glyph_info.glyph_size = {static_cast(glyph_size.width), - static_cast(glyph_size.height)}; - glyph_info.atlas_position = atlas_glyph_pos->origin; - glyph_info.atlas_glyph_size = {atlas_glyph_pos->size.width, - atlas_glyph_pos->size.height}; - VS::BindGlyphInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(glyph_info)); - - if (!pass.AddCommand(cmd)) { - return false; - } + cmd.instance_count = instance_count; + VS::BindGlyphPositions( + cmd, pass.GetTransientsBuffer().EmplaceStorageBuffer(glyph_positions)); + VS::BindGlyphSizes( + cmd, pass.GetTransientsBuffer().EmplaceStorageBuffer(glyph_sizes)); + VS::BindAtlasPositions( + cmd, pass.GetTransientsBuffer().EmplaceStorageBuffer(atlas_positions)); + VS::BindAtlasGlyphSizes( + cmd, + pass.GetTransientsBuffer().EmplaceStorageBuffer(atlas_glyph_sizes)); + + if (!pass.AddCommand(cmd)) { + return false; } } diff --git a/impeller/entity/shaders/glyph_atlas.vert b/impeller/entity/shaders/glyph_atlas.vert index aff822fdd4aad..9320a3465d0b4 100644 --- a/impeller/entity/shaders/glyph_atlas.vert +++ b/impeller/entity/shaders/glyph_atlas.vert @@ -8,12 +8,21 @@ uniform FrameInfo { vec4 text_color; } frame_info; -uniform GlyphInfo { - mat4 position; - vec2 glyph_size; - vec2 atlas_position; - vec2 atlas_glyph_size; -} glyph_info; +readonly buffer GlyphPositions { + mat4 position[]; +} glyph_positions; + +readonly buffer GlyphSizes { + vec2 size[]; +} glyph_sizes; + +readonly buffer AtlasPositions { + vec2 position[]; +} atlas_positions; + +readonly buffer AtlasGlyphSizes { + vec2 size[]; +} atlas_glyph_sizes; in vec2 unit_vertex; @@ -24,20 +33,23 @@ out vec2 v_atlas_size; out vec4 v_text_color; void main() { - mat4 scale = mat4( - glyph_info.glyph_size.x, 0.0, 0.0, 0.0, - 0.0, glyph_info.glyph_size.y, 0.0, 0.0, - 0.0, 0.0, 1.0 , 0.0, - 0.0, 0.0, 0.0 , 1.0 - ); + // The position to place the glyph. + mat4 glyph_position = glyph_positions.position[gl_InstanceIndex]; + // The size of the glyph. + vec2 glyph_size = glyph_sizes.size[gl_InstanceIndex]; + // The location of the glyph in the atlas. + vec2 glyph_atlas_position = atlas_positions.position[gl_InstanceIndex]; + // The size of the glyph within the atlas. + vec2 glyph_atlas_size = atlas_glyph_sizes.size[gl_InstanceIndex]; + gl_Position = frame_info.mvp - * glyph_info.position - * scale - * vec4(unit_vertex, 0.0, 1.0); + * glyph_position + * vec4(unit_vertex.x * glyph_size.x, + unit_vertex.y * glyph_size.y, 0.0, 1.0); v_unit_vertex = unit_vertex; - v_atlas_position = glyph_info.atlas_position; - v_atlas_glyph_size = glyph_info.atlas_glyph_size; + v_atlas_position = glyph_atlas_position; + v_atlas_glyph_size = glyph_atlas_size; v_atlas_size = frame_info.atlas_size; v_text_color = frame_info.text_color; } diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm index ac55199e1ca36..895f1a15089b2 100644 --- a/impeller/renderer/backend/metal/render_pass_mtl.mm +++ b/impeller/renderer/backend/metal/render_pass_mtl.mm @@ -399,6 +399,9 @@ static bool Bind(PassBindingsCache& pass, if (command.index_count == 0u) { continue; } + if (command.instance_count == 0u) { + continue; + } fml::ScopedCleanupClosure auto_pop_debug_marker(pop_debug_marker); if (!command.label.empty()) { @@ -510,6 +513,12 @@ static bool Bind(PassBindingsCache& pass, return true; } + if (command.instance_count == 0u) { + // Essentially a no-op. Don't record the command but this is not necessary + // an error either. + return true; + } + commands_.emplace_back(std::move(command)); return true; }