Skip to content

JIT exception thrown when creating animated gif on iOS #762

Description

@dmanning23

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

Description

When creating animated gifs on iOS devices, a JIT exception is thrown by the quantizer and the operation fails:

Attempting to JIT compile method 'SixLabors.ImageSharp.Processing.Processors.Quantization.OctreeFrameQuantizer`1/Octree/OctreeNode<SixLabors.ImageSharp.PixelFormats.Rgba32>:ConstructPalette (SixLabors.ImageSharp.PixelFormats.Rgba32[],int&)' while running in aot-only mode. See https://developer.xamarin.com/guides/ios/advanced_topics/limitations/ for more information.

The WuQuantizer throws a similar exception:

Attempting to JIT compile method 'SixLabors.ImageSharp.Processing.Processors.Quantization.WuFrameQuantizer`1<SixLabors.ImageSharp.PixelFormats.Rgba32>:GetPalette ()' while running in aot-only mode. See https://developer.xamarin.com/guides/ios/advanced_topics/limitations/ for more information.

The Xamarin link in the exception message mentions decorating the method with the UnmanagedFunctionPointerAttribute to fix the problem.
https://docs.microsoft.com/en-us/xamarin/ios/internals/limitations#no-dynamic-code-generation

Steps to Reproduce

I see this error everytime I try to create an animated gif on iOS.
I have a sample project here that demonstrates the problem:
https://github.com/dmanning23/MonogameScreenToolsExample
https://github.com/dmanning23/MonogameScreenTools

System Configuration

I'm seeing this issue on an iPhone 5S running iOS 12.0.1

  • ImageSharp version: I am using the "dev" package from the ImageSharp nightly myget stream.

Activity

  1. JimBobSquarePants commented on Oct 30, 2018

    @JimBobSquarePants
    Member

    @dmanning23 Thanks for the info and initial research

    https://developer.xamarin.com/guides/ios/advanced_topics/limitations/

    I have no experience with mobile development so hopefully someone reads this and has a clue what this actually means.

  2. dmanning23 commented on Oct 30, 2018

    @dmanning23
    ContributorAuthor

    The guidelines mention an attribute that can be used to decorate the problem method. There are a few examples out there showing how to use it, I was going to fart around with it later this afternoon and see if I can get it working.

  3. antonfirsov commented on Oct 30, 2018

    @antonfirsov
    Member

    It seems to me that you are facing this specific limiatation.

    @dmanning23 can you try a little experiment for us?

    1. Create an application referencing the dev/MyGet version of ImageSharp and System.Memory, that does nothing else but
    2. PixelOperations<Bgra32> operations = PixelOperations<Bgra32>.Instance
    3. Invoke something like this method on the instance created in (2.), using reflection.
      Notes:
      • reflection is needed because the method is internal
      • to get an instance to Span<T> you can use the extension method array.AsSpan()
      • Span<T> is implictily convertible to ReadOnlySpan<T>)
  4. antonfirsov commented on Oct 30, 2018

    @antonfirsov
    Member

    @dmanning23 as @JimBobSquarePants mentioned, there are no Xamarin devs in the core team, but I have a few more ideas to try, if it's possible for you to use a manually built version of ImageSharp.

  5. dmanning23 commented on Nov 2, 2018

    @dmanning23
    ContributorAuthor

    Ok, I've made a bit of headway on this issue... If I explicitly build one of those objects (with the correct generic type) and call the ConstructPalette method BEFORE calling SaveAsGif(...):

    var test = new OctreeFrameQuantizer<Rgba32>(new OctreeQuantizer(false));
    test.AotGetPalette(); //stubbed out method that just calls empty ConstructPalette
    

    Now when it hits that bit of code when calling SaveAsGif<Rgba32>, it has already seen it ahead-of-time and doesn't need to spin up the JIT compiler. I can't think of a very elegant way to fix it though... The easiest thing I can think of is adding a few AotCompile methods that are similar to above, that the user can call at init on iOS.
    kinda gross, but it would work :) I'll put together a PR so yall can give me your thoughts.

  6. dlemstra commented on Nov 5, 2018

    @dlemstra
    Member
  7. dmanning23 commented on Nov 5, 2018

    @dmanning23
    ContributorAuthor

    Looks like those workarounds are if this issue pops up from calling p/invoke, I don't think any of those would work because the error here is due to the heavy generic usage in ImageSharp. I have a PR open that adds a few methods that can be used to pre-seed the AoT compiler on iOS. I've been able to generate animated gifs on iOS using this technique :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions