Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use AsyncGlContext.Request to get GlContext #1243

Merged
merged 1 commit into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}