Merge pull request #1311 from Santarh/awaitcaller

Implements asynchronous AwaitCaller at runtime.
This commit is contained in:
ousttrue
2021-10-14 21:26:35 +09:00
committed by GitHub
11 changed files with 180 additions and 22 deletions

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ea8ee11da1da4f82b988a3108a362c2f
timeCreated: 1634202988

View File

@@ -32,26 +32,4 @@ namespace VRMShaders
/// <returns></returns>
Task<T> Run<T>(Func<T> action);
}
/// <summary>
/// 同期実行
/// </summary>
public sealed class ImmediateCaller : IAwaitCaller
{
public Task NextFrame()
{
return Task.FromResult<object>(null);
}
public Task Run(Action action)
{
action();
return Task.FromResult<object>(null);
}
public Task<T> Run<T>(Func<T> action)
{
return Task.FromResult(action());
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
namespace VRMShaders
{
/// <summary>
/// 同期実行
/// </summary>
public sealed class ImmediateCaller : IAwaitCaller
{
public Task NextFrame()
{
return Task.FromResult<object>(null);
}
public Task Run(Action action)
{
action();
return Task.FromResult<object>(null);
}
public Task<T> Run<T>(Func<T> action)
{
return Task.FromResult(action());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 30f43d5b7d6b4184fb775a315b835365
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
using System;
using UnityEngine;
using Object = UnityEngine.Object;
namespace VRMShaders
{
internal sealed class NextFrameTaskScheduler
{
public bool IsSupported => Application.isPlaying;
public NextFrameTaskScheduler()
{
if (!IsSupported)
{
throw new NotSupportedException($"{nameof(NextFrameTaskScheduler)} is supported at runtime only.");
}
}
public bool Enqueue(Action action)
{
var currentFrame = Time.frameCount;
UnityLoopTaskScheduler.Instance.Scheduler.Enqueue(action, () => Time.frameCount != currentFrame);
return true;
}
private sealed class UnityLoopTaskScheduler : MonoBehaviour
{
private static UnityLoopTaskScheduler _instance;
public static UnityLoopTaskScheduler Instance
{
get
{
if (_instance == null)
{
var go = new GameObject("UniGLTF UnityThreadScheduler");
Object.DontDestroyOnLoad(go);
_instance = go.AddComponent<UnityLoopTaskScheduler>();
}
return _instance;
}
}
public TinyManagedTaskScheduler Scheduler { get; } = new TinyManagedTaskScheduler();
private void Update()
{
Scheduler.ManagedUpdate();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3ce7defdc7144878a058274ae561d0be
timeCreated: 1634203513

View File

@@ -0,0 +1,36 @@
using System;
using System.Threading.Tasks;
namespace VRMShaders
{
/// <summary>
/// Runtime (Build 後と、Editor Playing) での非同期ロードを実現する AwaitCaller.
/// NOTE: 簡便に実装されたものなので、最適化の余地はある.
/// </summary>
public sealed class RuntimeOnlyAwaitCaller : IAwaitCaller
{
private readonly NextFrameTaskScheduler _scheduler;
public RuntimeOnlyAwaitCaller()
{
_scheduler = new NextFrameTaskScheduler();
}
public Task NextFrame()
{
var tcs = new TaskCompletionSource<object>();
_scheduler.Enqueue(() => tcs.SetResult(default));
return tcs.Task;
}
public Task Run(Action action)
{
return Task.Run(action);
}
public Task<T> Run<T>(Func<T> action)
{
return Task.Run(action);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e4e64b1835ca4cd2b682a6bda572b8fb
timeCreated: 1634203216

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Concurrent;
namespace VRMShaders
{
internal sealed class TinyManagedTaskScheduler
{
private readonly ConcurrentQueue<(Action, Func<bool>)> _continuationQueue =
new ConcurrentQueue<(Action, Func<bool>)>();
private readonly ConcurrentQueue<(Action, Func<bool>)> _temporaryQueue =
new ConcurrentQueue<(Action, Func<bool>)>();
public void ManagedUpdate()
{
while (_continuationQueue.TryDequeue(out var tuple))
{
var (continuation, canExecute) = tuple;
if (canExecute())
{
continuation();
}
else
{
_temporaryQueue.Enqueue(tuple);
}
}
while (_temporaryQueue.TryDequeue(out var tuple))
{
_continuationQueue.Enqueue(tuple);
}
}
public void Enqueue(Action continuation, Func<bool> canExecute)
{
_continuationQueue.Enqueue((continuation, canExecute));
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9c52ff07a0834bdc8f4c8d6c7f9a634f
timeCreated: 1634203919