Skip to content

iOS Impeller-only crash with BackdropFilter+blank PlatformView #124612

@moffatman

Description

@moffatman

I found a crash on flutter 3.10.0-3.0.pre.31 which only occurs when rendering using Impeller.
It comes from using the package native_drag_n_drop: ^0.0.5 which creates a "blank" platform view (only thing set is the backgroundColor = UIColor.clear, and it's used to add a drag-and-drop interaction.

https://github.com/alexrabin/FlutterNativeDragAndDrop/blob/main/ios/Classes/SwiftNativeDragNDropPlugin.swift

When putting a BackdropFilter on top, the program crashes instantly with an Metal exception.

Code sample
import 'dart:async';
import 'dart:math';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:native_drag_n_drop/native_drag_n_drop.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  createState() => MyAppState16();
}

class MyAppState16 extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoPageScaffold(
        child: NativeDropView(
          loading: (isLoading) {

          },
          dataReceived: (data) {

          },
          child: Stack(
            fit: StackFit.expand,
            children: [
              const Center(
                child: Text('asdfasdfasdfasdf')
              ),
              Center(
                child: ClipRect(
                  child: BackdropFilter(
                    filter: ui.ImageFilter.blur(sigmaX: 10, sigmaY: 10),
                    child: Container(
                      width: 100,
                      height: 100,
                      color: Colors.black38,
                    )
                  )
                )
              )
            ]
          )
        )
      )
    );
  }
}

The error is as follows:

-[MTLDebugBlitCommandEncoder internalValidateCopyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:options:]:388: failed assertion `Copy From Texture Validation
destinationTexture must not be a framebufferOnly texture.

I ran with a local engine where I changed IOSSurfaceMetalImpeller::GetCAMetalLayer to always set layer.framebufferOnly = NO, and the crash doesn't happen. But I don't know anything about Impeller - not sure if that is a correct fix, or rather the invalid operation (blit) should not be attempted on such a layer.

Engine backtrace

To explain the bottom stack frames, this is running on M1 mac, not an actual iOS device.

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x0000000183692868 libsystem_kernel.dylib`__pthread_kill + 8
    frame #1: 0x0000000101e66bc4 libsystem_pthread.dylib`pthread_kill + 288
    frame #2: 0x00000001836022c8 libsystem_c.dylib`abort + 180
    frame #3: 0x0000000183601620 libsystem_c.dylib`__assert_rtn + 272
    frame #4: 0x000000018caeaba0 Metal`MTLReportFailure.cold.1 + 48
    frame #5: 0x000000018cac770c Metal`MTLReportFailure + 464
    frame #6: 0x000000018cabdaa4 Metal`_MTLMessageContextEnd + 876
    frame #7: 0x0000000183ec96bc MetalTools`-[MTLDebugBlitCommandEncoder internalValidateCopyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:options:] + 1116
    frame #8: 0x0000000183eca33c MetalTools`-[MTLDebugBlitCommandEncoder validateCopyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:options:move:] + 116
    frame #9: 0x0000000183eca6dc MetalTools`-[MTLDebugBlitCommandEncoder copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:] + 148
    frame #10: 0x000000010d67bac4 Flutter`impeller::BlitCopyTextureToTextureCommandMTL::Encode(id<MTLBlitCommandEncoder>) const + 176
    frame #11: 0x000000010d67c1f4 Flutter`impeller::BlitPassMTL::EncodeCommands(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<impeller::Allocator> const&) const + 584
    frame #12: 0x000000010d5d12b8 Flutter`impeller::AiksContext::Render(impeller::Picture const&, impeller::RenderTarget&) + 3324
    frame #13: 0x000000010d6a5ac0 Flutter`std::_LIBCPP_ABI_NAMESPACE::__function::__func<fml::internal::CopyableLambda<flutter::GPUSurfaceMetalImpeller::AcquireFrame(SkISize const&)::$_0>, std::_LIBCPP_ABI_NAMESPACE::allocator<fml::internal::CopyableLambda<flutter::GPUSurfaceMetalImpeller::AcquireFrame(SkISize const&)::$_0> >, bool (flutter::SurfaceFrame&, flutter::DlCanvas*)>::operator()(flutter::SurfaceFrame&, flutter::DlCanvas*&&) + 556
    frame #14: 0x000000010d55f2e4 Flutter`flutter::SurfaceFrame::Submit() + 84
    frame #15: 0x000000010d0f66cc Flutter`flutter::IOSExternalViewEmbedder::SubmitFrame(GrDirectContext*, std::_LIBCPP_ABI_NAMESPACE::unique_ptr<flutter::SurfaceFrame, std::_LIBCPP_ABI_NAMESPACE::default_delete<flutter::SurfaceFrame> >) + 4056
    frame #16: 0x000000010d4a0cc0 Flutter`flutter::Rasterizer::DrawToSurfaceUnsafe(flutter::FrameTimingsRecorder&, flutter::LayerTree&) + 1320
    frame #17: 0x000000010d4a1770 Flutter`std::_LIBCPP_ABI_NAMESPACE::__function::__func<flutter::Rasterizer::DrawToSurface(flutter::FrameTimingsRecorder&, flutter::LayerTree&)::$_1, std::_LIBCPP_ABI_NAMESPACE::allocator<flutter::Rasterizer::DrawToSurface(flutter::FrameTimingsRecorder&, flutter::LayerTree&)::$_1>, void ()>::operator()() + 28
    frame #18: 0x000000010d3a6888 Flutter`fml::SyncSwitch::Execute(fml::SyncSwitch::Handlers const&) const + 72
    frame #19: 0x000000010d4a0638 Flutter`flutter::Rasterizer::DrawToSurface(flutter::FrameTimingsRecorder&, flutter::LayerTree&) + 272
    frame #20: 0x000000010d4a26ec Flutter`std::_LIBCPP_ABI_NAMESPACE::__function::__func<flutter::Rasterizer::Draw(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::Pipeline<flutter::LayerTreeItem> > const&, std::_LIBCPP_ABI_NAMESPACE::function<bool (flutter::LayerTree&)>)::$_1, std::_LIBCPP_ABI_NAMESPACE::allocator<flutter::Rasterizer::Draw(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::Pipeline<flutter::LayerTreeItem> > const&, std::_LIBCPP_ABI_NAMESPACE::function<bool (flutter::LayerTree&)>)::$_1>, void (std::_LIBCPP_ABI_NAMESPACE::unique_ptr<flutter::LayerTreeItem, std::_LIBCPP_ABI_NAMESPACE::default_delete<flutter::LayerTreeItem> >)>::operator()(std::_LIBCPP_ABI_NAMESPACE::unique_ptr<flutter::LayerTreeItem, std::_LIBCPP_ABI_NAMESPACE::default_delete<flutter::LayerTreeItem> >&&) + 312
    frame #21: 0x000000010d4a19bc Flutter`flutter::Rasterizer::Draw(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::Pipeline<flutter::LayerTreeItem> > const&, std::_LIBCPP_ABI_NAMESPACE::function<bool (flutter::LayerTree&)>) + 460
    frame #22: 0x000000010d4b8a8c Flutter`std::_LIBCPP_ABI_NAMESPACE::__function::__func<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::Pipeline<flutter::LayerTreeItem> >)::$_0>, std::_LIBCPP_ABI_NAMESPACE::allocator<fml::internal::CopyableLambda<flutter::Shell::OnAnimatorDraw(std::_LIBCPP_ABI_NAMESPACE::shared_ptr<flutter::Pipeline<flutter::LayerTreeItem> >)::$_0> >, void ()>::operator()() + 368
    frame #23: 0x000000010d3a4ec0 Flutter`fml::MessageLoopImpl::FlushTasks(fml::FlushType) + 568
    frame #24: 0x000000010d3a8cbc Flutter`fml::MessageLoopDarwin::OnTimerFire(__CFRunLoopTimer*, fml::MessageLoopDarwin*) + 32
    frame #25: 0x00000001837c354c CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 32
    frame #26: 0x00000001837c31f4 CoreFoundation`__CFRunLoopDoTimer + 940
    frame #27: 0x00000001837c2d4c CoreFoundation`__CFRunLoopDoTimers + 356
    frame #28: 0x00000001837a8734 CoreFoundation`__CFRunLoopRun + 1896
    frame #29: 0x00000001837a7878 CoreFoundation`CFRunLoopRunSpecific + 612
    frame #30: 0x000000018ce87fa0 HIToolbox`RunCurrentEventLoopInMode + 292
    frame #31: 0x000000018ce87de4 HIToolbox`ReceiveNextEventCommon + 672
    frame #32: 0x000000018ce87b2c HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 72
    frame #33: 0x0000000186a2d838 AppKit`_DPSNextEvent + 632
    frame #34: 0x0000000186a2c9c8 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 728
    frame #35: 0x0000000186a20df8 AppKit`-[NSApplication run] + 464
    frame #36: 0x00000001869f823c AppKit`NSApplicationMain + 880
    frame #37: 0x0000000186c526fc AppKit`_NSApplicationMainWithInfoDictionary + 24
    frame #38: 0x0000000199d42b04 UIKitMacHelper`UINSApplicationMain + 988
    frame #39: 0x00000001ad8380e4 UIKitCore`UIApplicationMain + 148
  * frame #40: 0x0000000100bde92c Runner`main at AppDelegate.swift:6:13
    frame #41: 0x000000018339fe50 dyld`start + 2544

Metadata

Metadata

Assignees

No one assigned

    Labels

    e: impellerImpeller rendering backend issues and features requests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions