Texture#GetNativeTexturePtr may not return on M1 Mac

When Texture#GetNativeTexturePtr is called repeatedly, the main thread freezes after a while on M1 Mac (Metal). I have never encountered this problem with Intel macs (nor Linux/Windows).

Here is a sample code I used to test.
Aside from efficiency, I don’t think there’s anything that would cause a deadlock, but is there?

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

using Mediapipe.Unity;

public class FreezeTest : MonoBehaviour
{
    [SerializeField] RawImage screen;
    [SerializeField] int width;
    [SerializeField] int height;
    [SerializeField] int fps;

    WebCamTexture webCamTexture;
    Color32[] pixelData;

    IEnumerator Start()
    {
        var webCamDevice = WebCamTexture.devices[0];
        webCamTexture = new WebCamTexture(webCamDevice.name, width, height, fps);
        webCamTexture.Play();

        yield return new WaitUntil(() => webCamTexture.width > 16);

        var texture = new Texture2D(width, height, TextureFormat.RGBA32, false);
        pixelData = new Color32[width * height];
        screen.texture = texture;

        while (true)
        {
          webCamTexture.GetPixels32(pixelData);
          texture.SetPixels32(pixelData);
          texture.Apply();
          Debug.Log(texture.GetNativeTexturePtr()); // At some point, this line will no longer return.
          yield return new WaitForEndOfFrame();
        }
    }

    void Destroy()
    {
        webCamTexture.Stop();
    }
}

The steps to reproduce

  • Create a new scene
  • Create an empty object and attach FreezeTest to it
  • Create a RawImage and set it to FreezeTest#screen
  • Set the other fields (i.e. width, height, fps) of FreezeTest according to your camera’s spec
  • Play the scene
  • Wait for a while (sometimes it takes a few seconds to reproduce, but sometimes several minutes)

Below is a screenshot of the profiler just before UnityEditor freezes.

And here is an excerpt of the dtruss’s output while UnityEditor freezes.
There seems to be some sort of deadlock occurring.

SYSCALL(args)         = return
__semwait_signal(0x1403, 0x0, 0x1)        = -1 Err#60
__semwait_signal(0x1403, 0x0, 0x1)        = -1 Err#60
__semwait_signal(0x1403, 0x0, 0x1)        = -1 Err#60
kevent_id(0x60000309DB00, 0x2D69B2B80, 0x1)        = 1 0
bsdthread_ctl(0x100, 0x0, 0xE653)        = 0 0
__semwait_signal(0x1403, 0x0, 0x1)        = -1 Err#60
workq_kernreturn(0x100, 0x2D69B2B80, 0x2)        = 0 Err#-2
kevent_id(0x60000309DB00, 0x2D69B2B80, 0x1)        = 1 0
bsdthread_ctl(0x100, 0x0, 0xE657)        = 0 0
kevent_id(0x6000030FF180, 0x2D69B1978, 0x1)        = 0 0
...

Environment
UnityEditor 2021.2.16f1
macOS Monterey 12.3
Mac mini (M1, 2020)
Memory 16GB

1 Like

I reproduce the issue in Unity-Technologies/NativeRenderingPlugin.
I add CreateTextureAndPassToPlugin() method inside a Update method.
I reproduce it with 100% chance with the start of the game in the editor. Sometimes need a 5 seconds to freeze. Not freeze in the first updates.

public void Update()
{
    CreateTextureAndPassToPlugin();
}

It’s important to enable any kind of Anti Aliasing.


Why that assign of new texture pointer in the plugin freezes the game? Do you have workaround or solution?

Environment:
MacOS architecture M1 Ventura 13.0.1
Xcode 14.1 (14B47b)
Unity3D editors

  • 2021.3.14f1 (Silicon)
  • 2022.2.0b6 (Silicon)(Beta)
    Cannot reproduce it on architecture Intel editor.

Thank you in advance.

8648067–1163448–NativeRenderingFreezeRepro.zip (255 KB)

1 Like

For what it’s worth, you are not alone - I’m seeing the same thing here. Just upgraded to an Apple Silicon laptop (M2 in my case), and a utility that always used to work without problems no long does so. Attaching a debugger I saw it was stuck in the same GetNativeTexturePtr method you mentioned. Did you file a bug report about it?

2 Likes

Looks like a bug has been filed by someone at least: Unity Issue Tracker - [M1] Editor/Player freezes when calling GetNativeTexturePtr

1 Like

Thanks for the link, AndyBlock.
Voted already. Need more votes.

1 Like

Same issue here! Although the ‘Anti Antialising’ setting doesn’t make a difference for me.

I somewhat worked around the issue by caching the IntPtr returned from Texture2d.GetNativeTexturePtr().

Texture2D.LoadImage/LoadRawTextureData() modify the underlying native texture pointer, so I had to create a temporary texture first, then copy it to my desired texture with Graphics.CopyTexture(). Graphics.CopyTexture() preserves the original texture pointer, so it can be cached and reused.

Of course, this workaround has terrible performance, but in my case, it wasn’t critical.