Skip to content

Commit

Permalink
fix(sample): GetNativeTexturePtr may never return on M1 Mac (#505)
Browse files Browse the repository at this point in the history
  • Loading branch information
homuler committed Mar 27, 2022
1 parent 9d47f7c commit 9d7e390
Showing 1 changed file with 39 additions and 30 deletions.
69 changes: 39 additions & 30 deletions Assets/Mediapipe/Samples/Common/Scripts/ImageSource/TextureFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ public class ReleaseEvent : UnityEvent<TextureFrame> { }
private const string _TAG = nameof(TextureFrame);

private static readonly GlobalInstanceTable<Guid, TextureFrame> _InstanceTable = new GlobalInstanceTable<Guid, TextureFrame>(100);
/// <summary>
/// A dictionary to look up which native texture belongs to which <see cref="TextureFrame" />.
/// </summary>
/// <remarks>
/// Not all the <see cref="TextureFrame" /> instances are registered.
/// Texture names are queried only when necessary, and the corresponding data will be saved then.
/// </remarks>
private static readonly Dictionary<uint, Guid> _NameTable = new Dictionary<uint, Guid>();

private readonly Texture2D _texture;
Expand Down Expand Up @@ -87,7 +94,7 @@ private TextureFrame(Texture2D texture)
format = texture.format;
OnRelease = new ReleaseEvent();
_instanceId = Guid.NewGuid();
RegisterInstance(this);
_InstanceTable.Add(_instanceId, this);
}

public TextureFrame(int width, int height, TextureFormat format) : this(new Texture2D(width, height, format, false)) { }
Expand Down Expand Up @@ -182,25 +189,37 @@ public Color32[] GetPixels32()

public void SetPixels32(Color32[] pixels)
{
var oldName = GetTextureName();

_texture.SetPixels32(pixels);
_texture.Apply();
_nativeTexturePtr = IntPtr.Zero;

ChangeNameFrom(oldName);
if (!RevokeNativeTexturePtr())
{
// If this line was executed, there must be a bug.
Logger.LogError("Failed to revoke the native texture.");
}
}

public NativeArray<T> GetRawTextureData<T>() where T : struct
{
return _texture.GetRawTextureData<T>();
}

/// <returns>The texture's native pointer</returns>
public IntPtr GetNativeTexturePtr()
{
if (_nativeTexturePtr == IntPtr.Zero)
{
_nativeTexturePtr = _texture.GetNativeTexturePtr();
var name = (uint)_nativeTexturePtr;

lock (((ICollection)_NameTable).SyncRoot)
{
if (!AcquireName(name, _instanceId))
{
throw new InvalidProgramException($"Another instance (id={_instanceId}) is using the specified name ({name}) now");
}
_NameTable.Add(name, _instanceId);
}
}
return _nativeTexturePtr;
}
Expand Down Expand Up @@ -284,22 +303,6 @@ public static void OnReleaseTextureFrame(uint textureName, IntPtr syncTokenPtr)
textureFrame.Release(_glSyncToken);
}

private static void RegisterInstance(TextureFrame textureFrame)
{
var name = textureFrame.GetTextureName();
var id = textureFrame._instanceId;
lock (((ICollection)_NameTable).SyncRoot)
{
if (AcquireName(name, id))
{
_InstanceTable.Add(id, textureFrame);
_NameTable.Add(name, id);
return;
}
}
throw new ArgumentException("Another instance has the same name");
}

/// <summary>
/// Remove <paramref name="name" /> from <see cref="_NameTable" /> if it's stale.
/// If <paramref name="name" /> does not exist in <see cref="_NameTable" />, do nothing.
Expand Down Expand Up @@ -328,18 +331,24 @@ private static TextureFormat GetTextureFormat(Texture texture)
return GraphicsFormatUtility.GetTextureFormat(texture.graphicsFormat);
}

private void ChangeNameFrom(uint oldName)
/// <summary>
/// Remove the texture name from <see cref="_NameTable" /> and empty <see cref="_nativeTexturePtr" />.
/// This method needs to be called when an operation is performed that may change the internal texture.
/// </summary>
private bool RevokeNativeTexturePtr()
{
var newName = GetTextureName();
lock (((ICollection)_NameTable).SyncRoot)
if (_nativeTexturePtr == IntPtr.Zero)
{
if (!AcquireName(newName, _instanceId))
{
throw new ArgumentException("Another instance is using the specified name now");
}
var _ = _NameTable.Remove(oldName);
_NameTable.Add(newName, _instanceId);
return true;
}

var currentName = GetTextureName();
if (!_NameTable.Remove(currentName))
{
return false;
}
_nativeTexturePtr = IntPtr.Zero;
return true;
}

private Texture2D LoadToTextureBuffer(Texture texture)
Expand Down

0 comments on commit 9d7e390

Please sign in to comment.