Flutter Impeller
impeller::SurfaceMTL Class Referencefinal

#include <surface_mtl.h>

Inheritance diagram for impeller::SurfaceMTL:
impeller::Surface

Public Member Functions

 ~SurfaceMTL () override
 
id< MTLDrawable > drawable () const
 
IRect coverage () const
 
bool Present () const override
 
- Public Member Functions inherited from impeller::Surface
 Surface ()
 
 Surface (const RenderTarget &target_desc)
 
virtual ~Surface ()
 
const ISizeGetSize () const
 
bool IsValid () const
 
const RenderTargetGetTargetRenderPassDescriptor () const
 

Static Public Member Functions

static id< CAMetalDrawable > GetMetalDrawableAndValidate (const std::shared_ptr< Context > &context, CAMetalLayer *layer)
 Wraps the current drawable of the given Metal layer to create a surface Impeller can render to. The surface must be created as late as possible and discarded immediately after rendering to it. More...
 
static std::unique_ptr< SurfaceMTLMakeFromMetalLayerDrawable (const std::shared_ptr< Context > &context, id< CAMetalDrawable > drawable, std::optional< IRect > clip_rect=std::nullopt)
 
static std::unique_ptr< SurfaceMTLMakeFromTexture (const std::shared_ptr< Context > &context, id< MTLTexture > texture, std::optional< IRect > clip_rect, id< CAMetalDrawable > drawable=nil)
 

Detailed Description

Definition at line 17 of file surface_mtl.h.

Constructor & Destructor Documentation

◆ ~SurfaceMTL()

impeller::SurfaceMTL::~SurfaceMTL ( )
overridedefault

Member Function Documentation

◆ coverage()

IRect impeller::SurfaceMTL::coverage ( ) const

Definition at line 221 of file surface_mtl.mm.

221  {
222  return IRect::MakeSize(resolve_texture_->GetSize());
223 }

References impeller::TRect< T >::MakeSize().

◆ drawable()

id<MTLDrawable> impeller::SurfaceMTL::drawable ( ) const
inline

Definition at line 56 of file surface_mtl.h.

56 { return drawable_; }

Referenced by MakeFromMetalLayerDrawable(), MakeFromTexture(), and Present().

◆ GetMetalDrawableAndValidate()

id< CAMetalDrawable > impeller::SurfaceMTL::GetMetalDrawableAndValidate ( const std::shared_ptr< Context > &  context,
CAMetalLayer *  layer 
)
static

Wraps the current drawable of the given Metal layer to create a surface Impeller can render to. The surface must be created as late as possible and discarded immediately after rendering to it.

Parameters
[in]contextThe context
[in]layerThe layer whose current drawable to wrap to create a surface.
Returns
A pointer to the wrapped surface or null.

Definition at line 25 of file surface_mtl.mm.

27  {
28  TRACE_EVENT0("impeller", "SurfaceMTL::WrapCurrentMetalLayerDrawable");
29 
30  if (context == nullptr || !context->IsValid() || layer == nil) {
31  return nullptr;
32  }
33 
34  id<CAMetalDrawable> current_drawable = nil;
35  {
36  TRACE_EVENT0("impeller", "WaitForNextDrawable");
37  current_drawable = [layer nextDrawable];
38  }
39 
40  if (!current_drawable) {
41  VALIDATION_LOG << "Could not acquire current drawable.";
42  return nullptr;
43  }
44  return current_drawable;
45 }

References VALIDATION_LOG.

◆ MakeFromMetalLayerDrawable()

std::unique_ptr< SurfaceMTL > impeller::SurfaceMTL::MakeFromMetalLayerDrawable ( const std::shared_ptr< Context > &  context,
id< CAMetalDrawable >  drawable,
std::optional< IRect clip_rect = std::nullopt 
)
static

Definition at line 123 of file surface_mtl.mm.

126  {
127  return SurfaceMTL::MakeFromTexture(context, drawable.texture, clip_rect,
128  drawable);
129 }

References drawable(), and MakeFromTexture().

◆ MakeFromTexture()

std::unique_ptr< SurfaceMTL > impeller::SurfaceMTL::MakeFromTexture ( const std::shared_ptr< Context > &  context,
id< MTLTexture >  texture,
std::optional< IRect clip_rect,
id< CAMetalDrawable >  drawable = nil 
)
static

Definition at line 131 of file surface_mtl.mm.

135  {
136  bool partial_repaint_blit_required = ShouldPerformPartialRepaint(clip_rect);
137 
138  // The returned render target is the texture that Impeller will render the
139  // root pass to. If partial repaint is in use, this may be a new texture which
140  // is smaller than the given MTLTexture.
141  auto render_target =
142  WrapTextureWithRenderTarget(*context->GetResourceAllocator(), texture,
143  partial_repaint_blit_required, clip_rect);
144  if (!render_target) {
145  return nullptr;
146  }
147 
148  // If partial repainting, set a "source" texture. The presence of a source
149  // texture and clip rect instructs the surface to blit this texture to the
150  // destination texture.
151  auto source_texture = partial_repaint_blit_required
152  ? render_target->GetRenderTargetTexture()
153  : nullptr;
154 
155  // The final "destination" texture is the texture that will be presented. In
156  // this case, it's always the given drawable.
157  std::shared_ptr<Texture> destination_texture;
158  if (partial_repaint_blit_required) {
159  // If blitting for partial repaint, we need to wrap the drawable. Simply
160  // reuse the texture descriptor that was already formed for the new render
161  // target, but override the size with the drawable's size.
162  auto destination_descriptor =
163  render_target->GetRenderTargetTexture()->GetTextureDescriptor();
164  destination_descriptor.size = {static_cast<ISize::Type>(texture.width),
165  static_cast<ISize::Type>(texture.height)};
166  destination_texture = TextureMTL::Wrapper(destination_descriptor, texture);
167  } else {
168  // When not partial repaint blit is needed, the render target texture _is_
169  // the drawable texture.
170  destination_texture = render_target->GetRenderTargetTexture();
171  }
172 
173  return std::unique_ptr<SurfaceMTL>(new SurfaceMTL(
174  context, // context
175  *render_target, // target
176  render_target->GetRenderTargetTexture(), // resolve_texture
177  drawable, // drawable
178  source_texture, // source_texture
179  destination_texture, // destination_texture
180  partial_repaint_blit_required, // requires_blit
181  clip_rect // clip_rect
182  ));
183 }

References drawable(), impeller::TextureMTL::Wrapper(), and impeller::WrapTextureWithRenderTarget().

Referenced by MakeFromMetalLayerDrawable().

◆ Present()

bool impeller::SurfaceMTL::Present ( ) const
overridevirtual

Reimplemented from impeller::Surface.

Definition at line 226 of file surface_mtl.mm.

226  {
227  auto context = context_.lock();
228  if (!context) {
229  return false;
230  }
231 
232 #ifdef IMPELLER_DEBUG
233  context->GetResourceAllocator()->DebugTraceMemoryStatistics();
234 #endif // IMPELLER_DEBUG
235 
236  if (requires_blit_) {
237  if (!(source_texture_ && destination_texture_)) {
238  return false;
239  }
240 
241  auto blit_command_buffer = context->CreateCommandBuffer();
242  if (!blit_command_buffer) {
243  return false;
244  }
245  auto blit_pass = blit_command_buffer->CreateBlitPass();
246  if (!clip_rect_.has_value()) {
247  VALIDATION_LOG << "Missing clip rectangle.";
248  return false;
249  }
250  blit_pass->AddCopy(source_texture_, destination_texture_, std::nullopt,
251  clip_rect_->GetOrigin());
252  blit_pass->EncodeCommands(context->GetResourceAllocator());
253  if (!context->GetCommandQueue()->Submit({blit_command_buffer}).ok()) {
254  return false;
255  }
256  }
257 #ifdef IMPELLER_DEBUG
258  ContextMTL::Cast(context.get())->GetGPUTracer()->MarkFrameEnd();
259 #endif // IMPELLER_DEBUG
260 
261  if (drawable_) {
262  id<MTLCommandBuffer> command_buffer =
263  ContextMTL::Cast(context.get())
264  ->CreateMTLCommandBuffer("Present Waiter Command Buffer");
265 
266  id<CAMetalDrawable> metal_drawable =
267  reinterpret_cast<id<CAMetalDrawable>>(drawable_);
268  if ([metal_drawable conformsToProtocol:@protocol(FlutterMetalDrawable)]) {
269  [(id<FlutterMetalDrawable>)metal_drawable
270  flutterPrepareForPresent:command_buffer];
271  }
272 
273  // Intel iOS simulators do not seem to give backpressure on Metal drawable
274  // aquisition, which can result in Impeller running head of the GPU
275  // workload by dozens of frames. Slow this process down by blocking
276  // on submit until the last command buffer is at least scheduled.
277 #if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
278  constexpr bool alwaysWaitForScheduling = true;
279 #else
280  constexpr bool alwaysWaitForScheduling = false;
281 #endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
282 
283  // If the threads have been merged, or there is a pending frame capture,
284  // then block on cmd buffer scheduling to ensure that the
285  // transaction/capture work correctly.
286  if ([[NSThread currentThread] isMainThread] ||
287  [[MTLCaptureManager sharedCaptureManager] isCapturing] ||
288  alwaysWaitForScheduling) {
289  TRACE_EVENT0("flutter", "waitUntilScheduled");
290  [command_buffer commit];
291 #if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
292  [command_buffer waitUntilCompleted];
293 #else
294  [command_buffer waitUntilScheduled];
295 #endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
296  [drawable_ present];
297  } else {
298  // The drawable may come from a FlutterMetalLayer, so it can't be
299  // presented through the command buffer.
300  id<CAMetalDrawable> drawable = drawable_;
301  [command_buffer addScheduledHandler:^(id<MTLCommandBuffer> buffer) {
302  [drawable present];
303  }];
304  [command_buffer commit];
305  }
306  }
307 
308  return true;
309 }

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::ContextMTL::CreateMTLCommandBuffer(), drawable(), and VALIDATION_LOG.


The documentation for this class was generated from the following files:
impeller::TSize::Type
T Type
Definition: size.h:20
impeller::WrapTextureWithRenderTarget
static std::optional< RenderTarget > WrapTextureWithRenderTarget(Allocator &allocator, id< MTLTexture > texture, bool requires_blit, std::optional< IRect > clip_rect)
Definition: surface_mtl.mm:47
FlutterMetalDrawable-p
Definition: surface_mtl.mm:16
impeller::SurfaceMTL::MakeFromTexture
static std::unique_ptr< SurfaceMTL > MakeFromTexture(const std::shared_ptr< Context > &context, id< MTLTexture > texture, std::optional< IRect > clip_rect, id< CAMetalDrawable > drawable=nil)
Definition: surface_mtl.mm:131
impeller::SurfaceMTL::drawable
id< MTLDrawable > drawable() const
Definition: surface_mtl.h:56
impeller::TextureMTL::Wrapper
static std::shared_ptr< TextureMTL > Wrapper(TextureDescriptor desc, id< MTLTexture > texture, std::function< void()> deletion_proc=nullptr)
Definition: texture_mtl.mm:41
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::TRect::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
impeller::BackendCast< ContextMTL, Context >::Cast
static ContextMTL & Cast(Context &base)
Definition: backend_cast.h:13
impeller::ContextMTL::CreateMTLCommandBuffer
id< MTLCommandBuffer > CreateMTLCommandBuffer(const std::string &label) const
Definition: context_mtl.mm:369