diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 02dd25cd7165d..f6761efd0726b 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -42656,8 +42656,6 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/gles/texture_gles.cc + ../../ ORIGIN: ../../../flutter/impeller/renderer/backend/gles/texture_gles.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/allocator_mtl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/allocator_mtl.mm + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/metal/blit_command_mtl.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/metal/blit_command_mtl.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/blit_pass_mtl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/blit_pass_mtl.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/command_buffer_mtl.h + ../../../flutter/LICENSE @@ -45531,8 +45529,6 @@ FILE: ../../../flutter/impeller/renderer/backend/gles/texture_gles.cc FILE: ../../../flutter/impeller/renderer/backend/gles/texture_gles.h FILE: ../../../flutter/impeller/renderer/backend/metal/allocator_mtl.h FILE: ../../../flutter/impeller/renderer/backend/metal/allocator_mtl.mm -FILE: ../../../flutter/impeller/renderer/backend/metal/blit_command_mtl.h -FILE: ../../../flutter/impeller/renderer/backend/metal/blit_command_mtl.mm FILE: ../../../flutter/impeller/renderer/backend/metal/blit_pass_mtl.h FILE: ../../../flutter/impeller/renderer/backend/metal/blit_pass_mtl.mm FILE: ../../../flutter/impeller/renderer/backend/metal/command_buffer_mtl.h diff --git a/impeller/renderer/backend/metal/BUILD.gn b/impeller/renderer/backend/metal/BUILD.gn index 2c9e0f2e718eb..e681b7bfee415 100644 --- a/impeller/renderer/backend/metal/BUILD.gn +++ b/impeller/renderer/backend/metal/BUILD.gn @@ -8,8 +8,6 @@ impeller_component("metal") { sources = [ "allocator_mtl.h", "allocator_mtl.mm", - "blit_command_mtl.h", - "blit_command_mtl.mm", "blit_pass_mtl.h", "blit_pass_mtl.mm", "command_buffer_mtl.h", diff --git a/impeller/renderer/backend/metal/blit_command_mtl.h b/impeller/renderer/backend/metal/blit_command_mtl.h deleted file mode 100644 index 90dad1956090c..0000000000000 --- a/impeller/renderer/backend/metal/blit_command_mtl.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_METAL_BLIT_COMMAND_MTL_H_ -#define FLUTTER_IMPELLER_RENDERER_BACKEND_METAL_BLIT_COMMAND_MTL_H_ - -#include - -#include "impeller/base/backend_cast.h" -#include "impeller/renderer/blit_command.h" - -namespace impeller { - -/// Mixin for dispatching Metal commands. -struct BlitEncodeMTL : BackendCast { - virtual ~BlitEncodeMTL(); - - virtual std::string GetLabel() const = 0; - - [[nodiscard]] virtual bool Encode( - id encoder) const = 0; -}; - -struct BlitCopyTextureToTextureCommandMTL - : public BlitCopyTextureToTextureCommand, - public BlitEncodeMTL { - ~BlitCopyTextureToTextureCommandMTL() override; - - std::string GetLabel() const override; - - [[nodiscard]] bool Encode(id encoder) const override; -}; - -struct BlitCopyTextureToBufferCommandMTL - : public BlitCopyTextureToBufferCommand, - public BlitEncodeMTL { - ~BlitCopyTextureToBufferCommandMTL() override; - - std::string GetLabel() const override; - - [[nodiscard]] bool Encode(id encoder) const override; -}; - -struct BlitGenerateMipmapCommandMTL : public BlitGenerateMipmapCommand, - public BlitEncodeMTL { - ~BlitGenerateMipmapCommandMTL() override; - - std::string GetLabel() const override; - - [[nodiscard]] bool Encode(id encoder) const override; -}; - -struct BlitCopyBufferToTextureCommandMTL - : public BlitCopyBufferToTextureCommand, - public BlitEncodeMTL { - ~BlitCopyBufferToTextureCommandMTL() override; - - std::string GetLabel() const override; - - [[nodiscard]] bool Encode(id encoder) const override; -}; - -} // namespace impeller - -#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_METAL_BLIT_COMMAND_MTL_H_ diff --git a/impeller/renderer/backend/metal/blit_command_mtl.mm b/impeller/renderer/backend/metal/blit_command_mtl.mm deleted file mode 100644 index 16ebf4441dadd..0000000000000 --- a/impeller/renderer/backend/metal/blit_command_mtl.mm +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "impeller/renderer/backend/metal/blit_command_mtl.h" - -#include "impeller/renderer/backend/metal/device_buffer_mtl.h" -#include "impeller/renderer/backend/metal/texture_mtl.h" - -namespace impeller { - -BlitEncodeMTL::~BlitEncodeMTL() = default; - -BlitCopyTextureToTextureCommandMTL::~BlitCopyTextureToTextureCommandMTL() = - default; - -std::string BlitCopyTextureToTextureCommandMTL::GetLabel() const { - return label; -} - -bool BlitCopyTextureToTextureCommandMTL::Encode( - id encoder) const { - auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture(); - if (!source_mtl) { - return false; - } - - auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture(); - if (!destination_mtl) { - return false; - } - - auto source_origin_mtl = - MTLOriginMake(source_region.GetX(), source_region.GetY(), 0); - auto source_size_mtl = - MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1); - auto destination_origin_mtl = - MTLOriginMake(destination_origin.x, destination_origin.y, 0); - - [encoder copyFromTexture:source_mtl - sourceSlice:0 - sourceLevel:0 - sourceOrigin:source_origin_mtl - sourceSize:source_size_mtl - toTexture:destination_mtl - destinationSlice:0 - destinationLevel:0 - destinationOrigin:destination_origin_mtl]; - - return true; -}; - -BlitCopyTextureToBufferCommandMTL::~BlitCopyTextureToBufferCommandMTL() = - default; - -std::string BlitCopyTextureToBufferCommandMTL::GetLabel() const { - return label; -} - -bool BlitCopyTextureToBufferCommandMTL::Encode( - id encoder) const { - auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture(); - if (!source_mtl) { - return false; - } - - auto destination_mtl = DeviceBufferMTL::Cast(*destination).GetMTLBuffer(); - if (!destination_mtl) { - return false; - } - - auto source_origin_mtl = - MTLOriginMake(source_region.GetX(), source_region.GetY(), 0); - auto source_size_mtl = - MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1); - - auto destination_bytes_per_pixel = - BytesPerPixelForPixelFormat(source->GetTextureDescriptor().format); - auto destination_bytes_per_row = - source_size_mtl.width * destination_bytes_per_pixel; - auto destination_bytes_per_image = - source_size_mtl.height * destination_bytes_per_row; - - [encoder copyFromTexture:source_mtl - sourceSlice:0 - sourceLevel:0 - sourceOrigin:source_origin_mtl - sourceSize:source_size_mtl - toBuffer:destination_mtl - destinationOffset:destination_offset - destinationBytesPerRow:destination_bytes_per_row - destinationBytesPerImage:destination_bytes_per_image]; - - return true; -}; - -BlitCopyBufferToTextureCommandMTL::~BlitCopyBufferToTextureCommandMTL() = - default; - -std::string BlitCopyBufferToTextureCommandMTL::GetLabel() const { - return label; -} - -bool BlitCopyBufferToTextureCommandMTL::Encode( - id encoder) const { - auto source_mtl = DeviceBufferMTL::Cast(*source.buffer).GetMTLBuffer(); - if (!source_mtl) { - return false; - } - - auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture(); - if (!destination_mtl) { - return false; - } - - auto destination_origin_mtl = - MTLOriginMake(destination_region.GetX(), destination_region.GetY(), 0); - auto source_size_mtl = MTLSizeMake(destination_region.GetWidth(), - destination_region.GetHeight(), 1); - - auto destination_bytes_per_pixel = - BytesPerPixelForPixelFormat(destination->GetTextureDescriptor().format); - auto source_bytes_per_row = - destination_region.GetWidth() * destination_bytes_per_pixel; - - [encoder copyFromBuffer:source_mtl - sourceOffset:source.range.offset - sourceBytesPerRow:source_bytes_per_row - sourceBytesPerImage: - 0 // 0 for 2D textures according to - // https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400752-copyfrombuffer - sourceSize:source_size_mtl - toTexture:destination_mtl - destinationSlice:slice - destinationLevel:0 - destinationOrigin:destination_origin_mtl]; - - return true; -}; - -BlitGenerateMipmapCommandMTL::~BlitGenerateMipmapCommandMTL() = default; - -std::string BlitGenerateMipmapCommandMTL::GetLabel() const { - return label; -} - -bool BlitGenerateMipmapCommandMTL::Encode( - id encoder) const { - return TextureMTL::Cast(*texture).GenerateMipmap(encoder); -}; - -} // namespace impeller diff --git a/impeller/renderer/backend/metal/blit_pass_mtl.h b/impeller/renderer/backend/metal/blit_pass_mtl.h index b21a04e20a107..3363eb969f2bc 100644 --- a/impeller/renderer/backend/metal/blit_pass_mtl.h +++ b/impeller/renderer/backend/metal/blit_pass_mtl.h @@ -7,7 +7,6 @@ #include -#include "impeller/renderer/backend/metal/blit_command_mtl.h" #include "impeller/renderer/blit_pass.h" namespace impeller { @@ -20,10 +19,14 @@ class BlitPassMTL final : public BlitPass { private: friend class CommandBufferMTL; - std::vector> commands_; + id encoder_ = nil; id buffer_ = nil; - std::string label_; bool is_valid_ = false; + bool is_metal_trace_active_ = false; + // Many parts of the codebase will start writing to a render pass but + // never submit them. This boolean is used to track if a submit happened + // so that in the dtor we can always ensure the render pass is finished. + mutable bool did_finish_encoding_ = false; explicit BlitPassMTL(id buffer); @@ -37,8 +40,6 @@ class BlitPassMTL final : public BlitPass { bool EncodeCommands( const std::shared_ptr& transients_allocator) const override; - bool EncodeCommands(id pass) const; - // |BlitPass| bool OnCopyTextureToTextureCommand(std::shared_ptr source, std::shared_ptr destination, diff --git a/impeller/renderer/backend/metal/blit_pass_mtl.mm b/impeller/renderer/backend/metal/blit_pass_mtl.mm index 172a36212dbb0..9caa449cdf0a4 100644 --- a/impeller/renderer/backend/metal/blit_pass_mtl.mm +++ b/impeller/renderer/backend/metal/blit_pass_mtl.mm @@ -15,12 +15,12 @@ #include "impeller/core/formats.h" #include "impeller/core/host_buffer.h" #include "impeller/core/shader_types.h" -#include "impeller/renderer/backend/metal/blit_command_mtl.h" #include "impeller/renderer/backend/metal/device_buffer_mtl.h" #include "impeller/renderer/backend/metal/formats_mtl.h" #include "impeller/renderer/backend/metal/pipeline_mtl.h" #include "impeller/renderer/backend/metal/sampler_mtl.h" #include "impeller/renderer/backend/metal/texture_mtl.h" + #include "impeller/renderer/blit_command.h" namespace impeller { @@ -29,10 +29,19 @@ if (!buffer_) { return; } + encoder_ = [buffer_ blitCommandEncoder]; +#ifdef IMPELLER_DEBUG + is_metal_trace_active_ = + [[MTLCaptureManager sharedCaptureManager] isCapturing]; +#endif // IMPELLER_DEBUG is_valid_ = true; } -BlitPassMTL::~BlitPassMTL() = default; +BlitPassMTL::~BlitPassMTL() { + if (!did_finish_encoding_) { + [encoder_ endEncoding]; + } +} bool BlitPassMTL::IsValid() const { return is_valid_; @@ -42,49 +51,13 @@ if (label.empty()) { return; } - label_ = std::move(label); + [encoder_ setLabel:@(label.c_str())]; } bool BlitPassMTL::EncodeCommands( const std::shared_ptr& transients_allocator) const { - TRACE_EVENT0("impeller", "BlitPassMTL::EncodeCommands"); - if (!IsValid()) { - return false; - } - - auto blit_command_encoder = [buffer_ blitCommandEncoder]; - - if (!blit_command_encoder) { - return false; - } - - if (!label_.empty()) { - [blit_command_encoder setLabel:@(label_.c_str())]; - } - - // Success or failure, the pass must end. The buffer can only process one pass - // at a time. - fml::ScopedCleanupClosure auto_end( - [blit_command_encoder]() { [blit_command_encoder endEncoding]; }); - - return EncodeCommands(blit_command_encoder); -} - -bool BlitPassMTL::EncodeCommands(id encoder) const { - fml::closure pop_debug_marker = [encoder]() { [encoder popDebugGroup]; }; - for (const auto& command : commands_) { - fml::ScopedCleanupClosure auto_pop_debug_marker(pop_debug_marker); - auto label = command->GetLabel(); - if (!label.empty()) { - [encoder pushDebugGroup:@(label.c_str())]; - } else { - auto_pop_debug_marker.Release(); - } - - if (!command->Encode(encoder)) { - return false; - } - } + [encoder_ endEncoding]; + did_finish_encoding_ = true; return true; } @@ -95,14 +68,44 @@ IRect source_region, IPoint destination_origin, std::string label) { - auto command = std::make_unique(); - command->label = label; - command->source = std::move(source); - command->destination = std::move(destination); - command->source_region = source_region; - command->destination_origin = destination_origin; - - commands_.emplace_back(std::move(command)); + auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture(); + if (!source_mtl) { + return false; + } + + auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture(); + if (!destination_mtl) { + return false; + } + + auto source_origin_mtl = + MTLOriginMake(source_region.GetX(), source_region.GetY(), 0); + auto source_size_mtl = + MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1); + auto destination_origin_mtl = + MTLOriginMake(destination_origin.x, destination_origin.y, 0); + +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ pushDebugGroup:@(label.c_str())]; + } +#endif // IMPELLER_DEBUG + [encoder_ copyFromTexture:source_mtl + sourceSlice:0 + sourceLevel:0 + sourceOrigin:source_origin_mtl + sourceSize:source_size_mtl + toTexture:destination_mtl + destinationSlice:0 + destinationLevel:0 + destinationOrigin:destination_origin_mtl]; + +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ popDebugGroup]; + } +#endif // IMPELLER_DEBUG + return true; } @@ -113,14 +116,48 @@ IRect source_region, size_t destination_offset, std::string label) { - auto command = std::make_unique(); - command->label = label; - command->source = std::move(source); - command->destination = std::move(destination); - command->source_region = source_region; - command->destination_offset = destination_offset; - - commands_.emplace_back(std::move(command)); + auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture(); + if (!source_mtl) { + return false; + } + + auto destination_mtl = DeviceBufferMTL::Cast(*destination).GetMTLBuffer(); + if (!destination_mtl) { + return false; + } + + auto source_origin_mtl = + MTLOriginMake(source_region.GetX(), source_region.GetY(), 0); + auto source_size_mtl = + MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1); + + auto destination_bytes_per_pixel = + BytesPerPixelForPixelFormat(source->GetTextureDescriptor().format); + auto destination_bytes_per_row = + source_size_mtl.width * destination_bytes_per_pixel; + auto destination_bytes_per_image = + source_size_mtl.height * destination_bytes_per_row; + +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ pushDebugGroup:@(label.c_str())]; + } +#endif // IMPELLER_DEBUG + [encoder_ copyFromTexture:source_mtl + sourceSlice:0 + sourceLevel:0 + sourceOrigin:source_origin_mtl + sourceSize:source_size_mtl + toBuffer:destination_mtl + destinationOffset:destination_offset + destinationBytesPerRow:destination_bytes_per_row + destinationBytesPerImage:destination_bytes_per_image]; + +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ popDebugGroup]; + } +#endif // IMPELLER_DEBUG return true; } @@ -130,26 +167,67 @@ IRect destination_region, std::string label, uint32_t slice) { - auto command = std::make_unique(); - command->label = std::move(label); - command->source = std::move(source); - command->destination = std::move(destination); - command->destination_region = destination_region; - command->slice = slice; - - commands_.emplace_back(std::move(command)); + auto source_mtl = DeviceBufferMTL::Cast(*source.buffer).GetMTLBuffer(); + if (!source_mtl) { + return false; + } + + auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture(); + if (!destination_mtl) { + return false; + } + + auto destination_origin_mtl = + MTLOriginMake(destination_region.GetX(), destination_region.GetY(), 0); + auto source_size_mtl = MTLSizeMake(destination_region.GetWidth(), + destination_region.GetHeight(), 1); + + auto destination_bytes_per_pixel = + BytesPerPixelForPixelFormat(destination->GetTextureDescriptor().format); + auto source_bytes_per_row = + destination_region.GetWidth() * destination_bytes_per_pixel; + +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ pushDebugGroup:@(label.c_str())]; + } +#endif // IMPELLER_DEBUG + [encoder_ + copyFromBuffer:source_mtl + sourceOffset:source.range.offset + sourceBytesPerRow:source_bytes_per_row + sourceBytesPerImage: + 0 // 0 for 2D textures according to + // https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400752-copyfrombuffer + sourceSize:source_size_mtl + toTexture:destination_mtl + destinationSlice:slice + destinationLevel:0 + destinationOrigin:destination_origin_mtl]; + +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ popDebugGroup]; + } +#endif // IMPELLER_DEBUG return true; } // |BlitPass| bool BlitPassMTL::OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) { - auto command = std::make_unique(); - command->label = label; - command->texture = std::move(texture); - - commands_.emplace_back(std::move(command)); - return true; +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ pushDebugGroup:@(label.c_str())]; + } +#endif // IMPELLER_DEBUG + auto result = TextureMTL::Cast(*texture).GenerateMipmap(encoder_); +#ifdef IMPELLER_DEBUG + if (is_metal_trace_active_) { + [encoder_ popDebugGroup]; + } +#endif // IMPELLER_DEBUG + return result; } } // namespace impeller diff --git a/impeller/renderer/blit_pass_unittests.cc b/impeller/renderer/blit_pass_unittests.cc index e30d89fb049b4..b99a3d0aff443 100644 --- a/impeller/renderer/blit_pass_unittests.cc +++ b/impeller/renderer/blit_pass_unittests.cc @@ -66,11 +66,13 @@ TEST_P(BlitPassTest, BlitPassesForMatchingFormats) { TextureDescriptor src_desc; src_desc.format = PixelFormat::kR8G8B8A8UNormInt; src_desc.size = {100, 100}; + src_desc.storage_mode = StorageMode::kHostVisible; auto src = context->GetResourceAllocator()->CreateTexture(src_desc); TextureDescriptor dst_format; dst_format.format = PixelFormat::kR8G8B8A8UNormInt; dst_format.size = {100, 100}; + dst_format.storage_mode = StorageMode::kHostVisible; auto dst = context->GetResourceAllocator()->CreateTexture(dst_format); EXPECT_TRUE(blit_pass->AddCopy(src, dst)); diff --git a/impeller/typographer/backends/skia/typographer_context_skia.cc b/impeller/typographer/backends/skia/typographer_context_skia.cc index 35c39a96907d4..ff258c93945a0 100644 --- a/impeller/typographer/backends/skia/typographer_context_skia.cc +++ b/impeller/typographer/backends/skia/typographer_context_skia.cc @@ -306,43 +306,6 @@ static bool UpdateAtlasBitmap(const GlyphAtlas& atlas, return true; } -// The texture needs to be cleared to transparent black so that linearly -// samplex rotated/skewed glyphs do not grab uninitialized data. -bool ClearTextureToTransparentBlack(Context& context, - HostBuffer& host_buffer, - std::shared_ptr& cmd_buffer, - std::shared_ptr& blit_pass, - std::shared_ptr& texture) { - // The R8/A8 textures used for certain glyphs is not supported as color - // attachments in most graphics drivers. To be safe, just do a CPU clear - // for these. - if (texture->GetTextureDescriptor().format == - context.GetCapabilities()->GetDefaultGlyphAtlasFormat()) { - size_t byte_size = - texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel(); - BufferView buffer_view = - host_buffer.Emplace(nullptr, byte_size, DefaultUniformAlignment()); - - ::memset(buffer_view.buffer->OnGetContents() + buffer_view.range.offset, 0, - byte_size); - buffer_view.buffer->Flush(); - return blit_pass->AddCopy(buffer_view, texture); - } - // In all other cases, we can use a render pass to clear to a transparent - // color. - ColorAttachment attachment; - attachment.clear_color = Color::BlackTransparent(); - attachment.load_action = LoadAction::kClear; - attachment.store_action = StoreAction::kStore; - attachment.texture = texture; - - RenderTarget render_target; - render_target.SetColorAttachment(attachment, 0u); - - auto render_pass = cmd_buffer->CreateRenderPass(render_target); - return render_pass->EncodeCommands(); -} - std::shared_ptr TypographerContextSkia::CreateGlyphAtlas( Context& context, GlyphAtlas::Type type, @@ -359,13 +322,6 @@ std::shared_ptr TypographerContextSkia::CreateGlyphAtlas( if (font_glyph_map.empty()) { return last_atlas; } - std::shared_ptr cmd_buffer = context.CreateCommandBuffer(); - std::shared_ptr blit_pass = cmd_buffer->CreateBlitPass(); - - fml::ScopedCleanupClosure closure([&]() { - blit_pass->EncodeCommands(context.GetResourceAllocator()); - context.GetCommandQueue()->Submit({std::move(cmd_buffer)}); - }); // --------------------------------------------------------------------------- // Step 1: Determine if the atlas type and font glyph pairs are compatible @@ -394,8 +350,7 @@ std::shared_ptr TypographerContextSkia::CreateGlyphAtlas( // --------------------------------------------------------------------------- // Step 2: Determine if the additional missing glyphs can be appended to the - // existing bitmap without recreating the atlas. This requires that - // the type is identical. + // existing bitmap without recreating the atlas. // --------------------------------------------------------------------------- std::vector glyph_positions; if (CanAppendToExistingAtlas(last_atlas, new_glyphs, glyph_positions, @@ -412,6 +367,14 @@ std::shared_ptr TypographerContextSkia::CreateGlyphAtlas( last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]); } + std::shared_ptr cmd_buffer = context.CreateCommandBuffer(); + std::shared_ptr blit_pass = cmd_buffer->CreateBlitPass(); + + fml::ScopedCleanupClosure closure([&]() { + blit_pass->EncodeCommands(context.GetResourceAllocator()); + context.GetCommandQueue()->Submit({std::move(cmd_buffer)}); + }); + // --------------------------------------------------------------------------- // Step 4a: Draw new font-glyph pairs into the a host buffer and encode // the uploads into the blit pass. @@ -502,8 +465,46 @@ std::shared_ptr TypographerContextSkia::CreateGlyphAtlas( new_texture->SetLabel("GlyphAtlas"); - ClearTextureToTransparentBlack(context, host_buffer, cmd_buffer, blit_pass, - new_texture); + std::shared_ptr cmd_buffer = context.CreateCommandBuffer(); + std::shared_ptr blit_pass; + + // The R8/A8 textures used for certain glyphs is not supported as color + // attachments in most graphics drivers. To be safe, just do a CPU clear + // for these. + if (type == GlyphAtlas::Type::kAlphaBitmap) { + size_t byte_size = + new_texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel(); + BufferView buffer_view = + host_buffer.Emplace(nullptr, byte_size, DefaultUniformAlignment()); + + ::memset(buffer_view.buffer->OnGetContents() + buffer_view.range.offset, 0, + byte_size); + buffer_view.buffer->Flush(); + blit_pass = cmd_buffer->CreateBlitPass(); + blit_pass->AddCopy(buffer_view, new_texture); + } else { + // In all other cases, we can use a render pass to clear to a transparent + // color. + ColorAttachment attachment; + attachment.clear_color = Color::BlackTransparent(); + attachment.load_action = LoadAction::kClear; + attachment.store_action = StoreAction::kStore; + attachment.texture = new_texture; + + RenderTarget render_target; + render_target.SetColorAttachment(attachment, 0u); + + auto render_pass = cmd_buffer->CreateRenderPass(render_target); + render_pass->EncodeCommands(); + blit_pass = cmd_buffer->CreateBlitPass(); + } + FML_DCHECK(!!blit_pass); + + fml::ScopedCleanupClosure closure([&]() { + blit_pass->EncodeCommands(context.GetResourceAllocator()); + context.GetCommandQueue()->Submit({std::move(cmd_buffer)}); + }); + if (!UpdateAtlasBitmap(*glyph_atlas, blit_pass, host_buffer, new_texture, font_glyph_pairs)) { return nullptr;