| Flutter Impeller |

Public Member Functions | Static Public Member Functions | List of all members
impeller::SurfaceMTL Class Referencefinal

`#include <surface_mtl.h>`

Inheritance diagram for impeller::SurfaceMTL:

## Public Member Functions
| ~SurfaceMTL () override
id< MTLDrawable > | drawable () const
IRect | coverage () const
void | PresentWithTransaction (bool present_with_transaction)
bool | PreparePresent () const
| Perform the final blit and trigger end of frame workloads. More...
bool | Present () const override
void | SetFrameBoundary (bool frame_boundary)
Public Member Functions inherited from impeller::Surface
| Surface ()
| Surface (const RenderTarget &target_desc)
virtual | ~Surface ()
const ISize & | GetSize () const
bool | IsValid () const
const RenderTarget & | GetRenderTarget () 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< SurfaceMTL > | MakeFromMetalLayerDrawable (const std::shared_ptr< Context > &context, id< CAMetalDrawable > drawable, const std::shared_ptr< SwapchainTransientsMTL > &transients, std::optional< IRect > clip_rect=std::nullopt)
static std::unique_ptr< SurfaceMTL > | MakeFromTexture (const std::shared_ptr< Context > &context, id< MTLTexture > texture, const std::shared_ptr< SwapchainTransientsMTL > &transients, std::optional< IRect > clip_rect, id< CAMetalDrawable > drawable=nil)

## Detailed Description

Definition at line 18 of file surface_mtl.h.

## Constructor & Destructor Documentation

## ◆ ~SurfaceMTL()

impeller::SurfaceMTL::~SurfaceMTL | ( |  | ) |
| override default

## Member Function Documentation

## ◆ coverage()

IRect impeller::SurfaceMTL::coverage | ( |  | ) | const

Definition at line 212 of file surface_mtl.mm.

212 {
213 return IRect::MakeSize(resolve_texture_->GetSize());
214 }
impeller::TRect::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150

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

## ◆ drawable()

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

Definition at line 59 of file surface_mtl.h.

59 { 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] | context | The context
  [in] | layer | The layer whose current drawable to wrap to create a surface.

Returns
  A pointer to the wrapped surface or null.

Definition at line 29 of file surface_mtl.mm.

31 {
32 TRACE_EVENT0("impeller", "SurfaceMTL::WrapCurrentMetalLayerDrawable");
33
34 if (context == nullptr || !context->IsValid() || layer == nil) {
35 return nullptr;
36 }
37
38 id<CAMetalDrawable> current_drawable = nil;
39 {
40 TRACE_EVENT0("impeller", "WaitForNextDrawable");
41 current_drawable = [layer nextDrawable];
42 }
43
44 if (!current_drawable) {
45 VALIDATION_LOG << "Could not acquire current drawable.";
46 return nullptr;
47 }
48 return current_drawable;
49 }
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91

References VALIDATION_LOG.

## ◆ MakeFromMetalLayerDrawable()

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

Definition at line 113 of file surface_mtl.mm.

117 {
118 return SurfaceMTL::MakeFromTexture(context, drawable.texture, transients,
119 clip_rect, drawable);
120 }
impeller::SurfaceMTL::MakeFromTexture
static std::unique_ptr< SurfaceMTL > MakeFromTexture(const std::shared_ptr< Context > &context, id< MTLTexture > texture, const std::shared_ptr< SwapchainTransientsMTL > &transients, std::optional< IRect > clip_rect, id< CAMetalDrawable > drawable=nil)
Definition: surface_mtl.mm:122
impeller::SurfaceMTL::drawable
id< MTLDrawable > drawable() const
Definition: surface_mtl.h:59

References drawable(), and MakeFromTexture().

## ◆ MakeFromTexture()

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

Definition at line 122 of file surface_mtl.mm.

127 {
128 bool partial_repaint_blit_required = ShouldPerformPartialRepaint(clip_rect);
129
130 // The returned render target is the texture that Impeller will render the
131 // root pass to. If partial repaint is in use, this may be a new texture which
132 // is smaller than the given MTLTexture.
133 auto render_target = WrapTextureWithRenderTarget(
134 transients, texture, partial_repaint_blit_required, clip_rect);
135 if (!render_target) {
136 return nullptr;
137 }
138
139 // If partial repainting, set a "source" texture. The presence of a source
140 // texture and clip rect instructs the surface to blit this texture to the
141 // destination texture.
142 auto source_texture = partial_repaint_blit_required
143 ? render_target->GetRenderTargetTexture()
144 : nullptr;
145
146 // The final "destination" texture is the texture that will be presented. In
147 // this case, it's always the given drawable.
148 std::shared_ptr<Texture> destination_texture;
149 if (partial_repaint_blit_required) {
150 // If blitting for partial repaint, we need to wrap the drawable. Simply
151 // reuse the texture descriptor that was already formed for the new render
152 // target, but override the size with the drawable's size.
153 auto destination_descriptor =
154 render_target->GetRenderTargetTexture()->GetTextureDescriptor();
155 destination_descriptor.size = {static_cast<ISize::Type>(texture.width),
156 static_cast<ISize::Type>(texture.height)};
157 destination_texture = TextureMTL::Wrapper(destination_descriptor, texture);
158 } else {
159 // When not partial repaint blit is needed, the render target texture _is_
160 // the drawable texture.
161 destination_texture = render_target->GetRenderTargetTexture();
162 }
163
164 return std::unique_ptr<SurfaceMTL>(new SurfaceMTL(
165 context, // context
166 *render_target, // target
167 render_target->GetRenderTargetTexture(), // resolve_texture
168 drawable, // drawable
169 source_texture, // source_texture
170 destination_texture, // destination_texture
171 partial_repaint_blit_required, // requires_blit
172 clip_rect // clip_rect
173 ));
174 }
impeller::TextureMTL::Wrapper
static std::shared_ptr< TextureMTL > Wrapper(TextureDescriptor desc, id< MTLTexture > texture, std::function< void()> deletion_proc=nullptr)
Definition: texture_mtl.mm:44
impeller::WrapTextureWithRenderTarget
static std::optional< RenderTarget > WrapTextureWithRenderTarget(const std::shared_ptr< SwapchainTransientsMTL > &transients, id< MTLTexture > texture, bool requires_blit, std::optional< IRect > clip_rect)
Definition: surface_mtl.mm:51
impeller::TSize::Type
T Type
Definition: size.h:26

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

Referenced by MakeFromMetalLayerDrawable().

## ◆ PreparePresent()

bool impeller::SurfaceMTL::PreparePresent | ( |  | ) | const

Perform the final blit and trigger end of frame workloads.

Definition at line 216 of file surface_mtl.mm.

216 {
217 auto context = context_.lock();
218 if (!context) {
219 return false;
220 }
221
222 #ifdef IMPELLER_DEBUG
223 context->GetResourceAllocator()->DebugTraceMemoryStatistics();
224 if (frame_boundary_) {
225 ContextMTL::Cast(context.get())->GetCaptureManager()->FinishCapture();
226 }
227 #endif // IMPELLER_DEBUG
228
229 if (requires_blit_) {
230 if (!(source_texture_ && destination_texture_)) {
231 return false;
232 }
233
234 auto blit_command_buffer = context->CreateCommandBuffer();
235 if (!blit_command_buffer) {
236 return false;
237 }
238 auto blit_pass = blit_command_buffer->CreateBlitPass();
239 if (!clip_rect_.has_value()) {
240 VALIDATION_LOG << "Missing clip rectangle.";
241 return false;
242 }
243 blit_pass->AddCopy(source_texture_, destination_texture_, clip_rect_,
244 clip_rect_->GetOrigin());
245 blit_pass->EncodeCommands();
246 if (!context->GetCommandQueue()->Submit({blit_command_buffer}).ok()) {
247 return false;
248 }
249 }
250 #ifdef IMPELLER_DEBUG
251 ContextMTL::Cast(context.get())->GetGPUTracer()->MarkFrameEnd();
252 #endif // IMPELLER_DEBUG
253 prepared_ = true;
254 return true;
255 }
impeller::BackendCast< ContextMTL, Context >::Cast
static ContextMTL & Cast(Context &base)
Definition: backend_cast.h:13
impeller::ContextMTL::CreateCommandBuffer
std::shared_ptr< CommandBuffer > CreateCommandBuffer() const override
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
Definition: context_mtl.mm:325

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

Referenced by Present().

## ◆ Present()

bool impeller::SurfaceMTL::Present | ( |  | ) | const
| override virtual

Reimplemented from impeller::Surface.

Definition at line 258 of file surface_mtl.mm.

258 {
259 if (!prepared_) {
260 PreparePresent();
261 }
262 auto context = context_.lock();
263 if (!context) {
264 return false;
265 }
266
267 if (drawable_) {
268 id<MTLCommandBuffer> command_buffer =
269 ContextMTL::Cast(context.get())
270 ->CreateMTLCommandBuffer("Present Waiter Command Buffer");
271
272 id<CAMetalDrawable> metal_drawable =
273 reinterpret_cast<id<CAMetalDrawable>>(drawable_);
274 if ([metal_drawable conformsToProtocol:@protocol(FlutterMetalDrawable)]) {
275 [(id<FlutterMetalDrawable>)metal_drawable
276 flutterPrepareForPresent:command_buffer];
277 }
278
279 // Intel iOS simulators do not seem to give backpressure on Metal drawable
280 // aquisition, which can result in Impeller running head of the GPU
281 // workload by dozens of frames. Slow this process down by blocking
282 // on submit until the last command buffer is at least scheduled.
283 #if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
284 constexpr bool alwaysWaitForScheduling = true;
285 #else
286 constexpr bool alwaysWaitForScheduling = false;
287 #endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
288
289 // If the threads have been merged, or there is a pending frame capture,
290 // then block on cmd buffer scheduling to ensure that the
291 // transaction/capture work correctly.
292 if (present_with_transaction_ || [[NSThread currentThread] isMainThread] ||
293 [[MTLCaptureManager sharedCaptureManager] isCapturing] ||
294 alwaysWaitForScheduling) {
295 TRACE_EVENT0("flutter", "waitUntilScheduled");
296 [command_buffer commit];
297 #if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
298 [command_buffer waitUntilCompleted];
299 #else
300 [command_buffer waitUntilScheduled];
301 #endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
302 [drawable_ present];
303 } else {
304 // The drawable may come from a FlutterMetalLayer, so it can't be
305 // presented through the command buffer.
306 id<CAMetalDrawable> drawable = drawable_;
307 [command_buffer addScheduledHandler:^(id<MTLCommandBuffer> buffer) {
308 [drawable present];
309 }];
310 [command_buffer commit];
311 }
312 }
313
314 return true;
315 }
impeller::ContextMTL::CreateMTLCommandBuffer
id< MTLCommandBuffer > CreateMTLCommandBuffer(const std::string &label) const
Definition: context_mtl.mm:380
impeller::SurfaceMTL::PreparePresent
bool PreparePresent() const
Perform the final blit and trigger end of frame workloads.
Definition: surface_mtl.mm:216
FlutterMetalDrawable-p
Definition: surface_mtl.mm:20

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

## ◆ PresentWithTransaction()

void impeller::SurfaceMTL::PresentWithTransaction | ( | bool | present_with_transaction | ) |
| inline

Mark this surface as presenting with a transaction.

If true, [Present] will block on the scheduling of a command buffer.

Definition at line 67 of file surface_mtl.h.

67 {
68 present_with_transaction_ = present_with_transaction;
69 }

## ◆ SetFrameBoundary()

void impeller::SurfaceMTL::SetFrameBoundary | ( | bool | frame_boundary | ) |
| inline

Definition at line 77 of file surface_mtl.h.

77 {
78 frame_boundary_ = frame_boundary;
79 }

The documentation for this class was generated from the following files:

- impeller/renderer/backend/metal/surface_mtl.h
- impeller/renderer/backend/metal/surface_mtl.mm