Skip to content

Commit

Permalink
refactor: use AsyncGlContext.Request to get GlContext
Browse files Browse the repository at this point in the history
  • Loading branch information
homuler committed Aug 12, 2024
1 parent fd15462 commit 40d1ffd
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2021 homuler
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using UnityEngine;

namespace Mediapipe.Unity
{
public static class AsyncGlContext
{
public static AsyncGlContextRequest Request(Action<AsyncGlContextRequest> callback) => new AsyncGlContextRequest(callback);
}

public class AsyncGlContextRequest
{
private static int _Counter = 0;
private static readonly GlobalInstanceTable<int, AsyncGlContextRequest> _InstanceTable = new GlobalInstanceTable<int, AsyncGlContextRequest>(5);

private delegate void GLEventCallback(int eventId);

private readonly int _id;
private readonly Action<AsyncGlContextRequest> _callback;

public IntPtr platformGlContext { get; private set; }
public bool done { get; private set; }
public Exception error { get; private set; }

internal AsyncGlContextRequest(Action<AsyncGlContextRequest> callback)
{
_id = Interlocked.Increment(ref _Counter);
_callback = callback;
_InstanceTable.Add(_id, this);

GLEventCallback gLEventCallback = PluginCallback;
var fp = Marshal.GetFunctionPointerForDelegate(gLEventCallback);

GL.IssuePluginEvent(fp, _id);
}

[AOT.MonoPInvokeCallback(typeof(GLEventCallback))]
private static void PluginCallback(int eventId)
{
if (!_InstanceTable.TryGetValue(eventId, out var request))
{
Logger.LogWarning($"AsyncGlContextRequest with id {eventId} is not found, maybe already GCed");
return;
}

try
{
#if UNITY_ANDROID
// Currently, it works only on Android
request.platformGlContext = Egl.GetCurrentContext();
#endif

request._callback?.Invoke(request);
}
catch (Exception e)
{
request.error = e;
}
finally
{
request.done = true;
_InstanceTable.Remove(eventId);
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
using UnityEngine;
using UnityEngine.Rendering;

#if UNITY_ANDROID
using System.Runtime.InteropServices;
#endif

namespace Mediapipe.Unity
{
public static class GpuManager
Expand All @@ -22,10 +18,7 @@ public static class GpuManager
private delegate void PluginCallback(int eventId);

private static readonly object _SetupLock = new object();
#pragma warning disable IDE0044
private static IntPtr _CurrentContext = IntPtr.Zero;
#pragma warning restore IDE0044
private static bool _IsContextInitialized = false;
private static IntPtr _PlatformGlContext = IntPtr.Zero;

public static GpuResources GpuResources { get; private set; }
public static GlCalculatorHelper GlCalculatorHelper { get; private set; }
Expand All @@ -50,48 +43,21 @@ public static IEnumerator Initialize()
yield break;
}

#if UNITY_ANDROID
_IsContextInitialized = SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES3;
if (!_IsContextInitialized)
{
PluginCallback callback = GetCurrentContext;

var fp = Marshal.GetFunctionPointerForDelegate(callback);
GL.IssuePluginEvent(fp, 1);
}
#else
_IsContextInitialized = true;
#endif

var count = 100;
yield return new WaitUntil(() =>
{
return --count < 0 || _IsContextInitialized;
});

if (!_IsContextInitialized)
{
Logger.LogError(_TAG, "Failed to get GlContext");
yield break;
}

#if UNITY_ANDROID
if (_CurrentContext == IntPtr.Zero)
{
Logger.LogWarning(_TAG, "EGL context is not found, so MediaPipe won't share their EGL contexts with Unity");
}
else
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3)
{
Logger.LogVerbose(_TAG, $"EGL context is found: {_CurrentContext}");
var req = AsyncGlContext.Request(OnGetEglContext);
yield return new WaitUntil(() => req.done);

if (req.error != null)
{
Logger.LogException(req.error);
yield break;
}
}
#endif

try
{
Logger.LogInfo(_TAG, "Initializing GpuResources...");
GpuResources = GpuResources.Create(_CurrentContext);

Logger.LogInfo(_TAG, "Initializing GlCalculatorHelper...");
GpuResources = GpuResources.Create(_PlatformGlContext);
GlCalculatorHelper = new GlCalculatorHelper();
GlCalculatorHelper.InitializeForTest(GpuResources);

Expand Down Expand Up @@ -133,13 +99,30 @@ public static void Shutdown()
IsInitialized = false;
}

// Currently, it works only on Android
#if UNITY_ANDROID
[AOT.MonoPInvokeCallback(typeof(PluginCallback))]
private static void GetCurrentContext(int eventId) {
_CurrentContext = Egl.GetCurrentContext();
_IsContextInitialized = true;
public static void ResetGpuResources(IntPtr platformGlContext)
{
if (!IsInitialized)
{
throw new InvalidOperationException("GpuManager is not initialized");
}
GpuResources?.Dispose();

GpuResources = new GpuResources(platformGlContext);
GlCalculatorHelper.InitializeForTest(GpuResources);
}

public static GlContext GetGlContext() => GlCalculatorHelper?.GetGlContext();

private static void OnGetEglContext(AsyncGlContextRequest request)
{
if (request.platformGlContext == IntPtr.Zero)
{
Logger.LogWarning(_TAG, "EGL context is not found, so MediaPipe won't share their EGL contexts with Unity");
return;
}
Logger.LogVerbose(_TAG, $"EGL context is found: {request.platformGlContext}");

_PlatformGlContext = request.platformGlContext;
}
#endif
}
}

0 comments on commit 40d1ffd

Please sign in to comment.