Files
stgsharp/源代码/StgSharp/Graphics/FrameThread.cs
T

500 lines
15 KiB
C#

using StgSharp.Logic;
using StgSharp.Math;
using System;
using System.Runtime.CompilerServices;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.Graphics
{
internal sealed class FrameOperationBuffer
{
private readonly unsafe GLcontext* currentContext;
private IntPtr _func;
private ConcurrentQueue<IntPtr> _funcQueue;
public unsafe bool CallNext()
{
if (_funcQueue.TryDequeue(out _func))
{
((delegate*<FrameOperationBuffer, GLcontext*, void>)_func)(this, currentContext);
return true;
}
else
{
return false;
}
}
#region gl param queue
private ConcurrentQueue<M128> paramQueue = new ConcurrentQueue<M128>();
private ConcurrentQueue<glArrayHandle> streamQueue = new ConcurrentQueue<glArrayHandle>();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MethodEnqueue(IntPtr p)
{
_funcQueue.Enqueue(p);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(Vec4d v)
{
paramQueue.Enqueue(v);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(M128 m)
{
paramQueue.Enqueue(m);
Console.WriteLine(paramQueue.Count + streamQueue.Count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(uint u0)
{
M128 m = default;
m.Write<uint>(0, u0);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(uint u0, uint u1)
{
M128 m = default;
m.Write<uint>(0, u0);
m.Write<uint>(1, u1);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(ulong u0, ulong u1)
{
M128 m = default;
m.Write<ulong>(0, u0);
m.Write<ulong>(1, u1);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(uint u0, uint u1, uint u2)
{
M128 m = default;
m.Write<uint>(0, u0);
m.Write<uint>(1, u1);
m.Write<uint>(2, u2);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(float f0, float f1, float f2)
{
M128 m = default;
m.Write<float>(0, f0);
m.Write<float>(1, f1);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(float f0, float f1, float f2, float f3)
{
M128 m = default;
m.Write<float>(0, f0);
m.Write<float>(1, f1);
m.Write<float>(2, f2);
m.Write<float>(3, f3);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(IntPtr p0, IntPtr p1)
{
M128 m = default;
m.Write<ulong>(0, (ulong)p0);
m.Write<ulong>(1, (ulong)p1);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(IntPtr p)
{
M128 m = default;
m.Write<ulong>(0, (ulong)p);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void ParamEnqueue(glHandle handle)
{
M128 m = default;
m.Write<ulong>(0, (ulong)handle.valuePtr);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void ParamEnqueue(glHandle handle, glHandle handle1)
{
M128 m = default;
m.Write<ulong>(0, (ulong)handle.valuePtr);
m.Write<ulong>(1, (ulong)handle1.valuePtr);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(int i0)
{
M128 m = default;
m.Write<int>(0, i0);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(int i0, int i1)
{
M128 m = default;
m.Write<int>(0, i0);
m.Write<int>(1, i1);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(int i0, int i1, int i2)
{
M128 m = default;
m.Write<int>(0, i0);
m.Write<int>(1, i1);
m.Write<int>(2, i2);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(int i0, int i1, int i2, int i3)
{
M128 m = default;
m.Write<int>(0, i0);
m.Write<int>(1, i1);
m.Write<int>(2, i2);
m.Write<int>(3, i3);
this.ParamEnqueue(m);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue(string str)
{
byte[] code = Encoding.UTF8.GetBytes(str);
streamQueue.Enqueue(glArrayHandle.Alloc<byte>(code));
Console.WriteLine(paramQueue.Count + streamQueue.Count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ParamEnqueue<T>(T[] array) where T : struct
{
streamQueue.Enqueue(glArrayHandle.Alloc<T>(array));
Console.WriteLine(paramQueue.Count + streamQueue.Count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out glArrayHandle arrayHandle)
{
if (!streamQueue.TryDequeue(out arrayHandle))
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function:", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryDequeue(out M128 m)
{
bool ret = paramQueue.TryDequeue(out m);
return ret;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void TryDequeue(out Vec4d v)
{
M128 m;
if (this.TryDequeue(out m))
{
v = *(Vec4d*)&m;
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue<T>(out T[] array)
{
glArrayHandle output = default;
if (streamQueue.TryDequeue(out output))
{
array = output.a as T[];
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out int i0)
{
M128 ret;
if (this.TryDequeue(out ret))
{
i0 = ret.Read<int>(0);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out int i0, out int i1)
{
M128 ret;
if (this.TryDequeue(out ret))
{
i0 = ret.Read<int>(0);
i1 = ret.Read<int>(1);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out int i0, out int i1, out int i2)
{
M128 ret;
if (this.TryDequeue(out ret))
{
i0 = ret.Read<int>(0);
i1 = ret.Read<int>(1);
i2 = ret.Read<int>(2);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out int i0, out int i1, out int i2, out int i3)
{
M128 ret;
if (this.TryDequeue(out ret))
{
i0 = ret.Read<int>(0);
i1 = ret.Read<int>(1);
i2 = ret.Read<int>(2);
i3 = ret.Read<int>(3);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out IntPtr p)
{
M128 ret;
if (this.TryDequeue(out ret))
{
p = (IntPtr)ret.Read<ulong>(0);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out IntPtr p0, out IntPtr p1)
{
M128 ret;
if (this.TryDequeue(out ret))
{
p0 = (IntPtr)ret.Read<ulong>(0);
p1 = (IntPtr)ret.Read<ulong>(1);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out float f0, out float f1, out float f2, out float f3)
{
M128 ret;
if (this.TryDequeue(out ret))
{
f0 = ret.Read<uint>(0);
f1 = ret.Read<uint>(1);
f2 = ret.Read<uint>(2);
f3 = ret.Read<uint>(3);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out float f0, out float f1, out float f2)
{
M128 ret;
if (this.TryDequeue(out ret))
{
f0 = ret.Read<uint>(0);
f1 = ret.Read<uint>(1);
f2 = ret.Read<uint>(2);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out uint u0)
{
M128 ret;
if (this.TryDequeue(out ret))
{
u0 = ret.Read<uint>(0);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out uint u0, out uint u1)
{
M128 ret;
if (this.TryDequeue(out ret))
{
u0 = ret.Read<uint>(0);
u1 = ret.Read<uint>(1);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out uint u0, out uint u1, out uint u2)
{
M128 ret;
if (this.TryDequeue(out ret))
{
u0 = ret.Read<uint>(0);
u1 = ret.Read<uint>(1);
u2 = ret.Read<uint>(2);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDequeue(out uint u0, out uint u1, out uint u2, out uint u3)
{
M128 ret;
if (this.TryDequeue(out ret))
{
u0 = ret.Read<uint>(0);
u1 = ret.Read<uint>(1);
u2 = ret.Read<uint>(2);
u3 = ret.Read<uint>(3);
}
else
{
InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error);
throw new Exception();
}
}
/*
internal void SetContext(GLcontext* p)
{
context = p;
}
/**/
#endregion gl param queue
}
internal sealed class FrameThread
{
private Thread _thread;
private FrameOperationBuffer renderBuffer;
private SemaphoreSlim renderCompleteSemaphore = new SemaphoreSlim(1, 1);
private SemaphoreSlim renderStartSemaphore;
private bool shouldTerminate;
private FrameOperationBuffer updateBuffer;
internal FrameThread(GLonUpdate gl)
{
updateBuffer = gl.ActivatedOperationBuffer;
_thread = new Thread(new ThreadStart(PrivateMain));
}
public bool IsRunning
{
get { return _thread.IsAlive; }
}
public void Start()
{
_thread.Start();
}
public void Terminate()
{
shouldTerminate = true;
}
private void PrivateMain()
{
renderStartSemaphore.Wait();
while (shouldTerminate && renderBuffer.CallNext())
{ }
renderCompleteSemaphore.Release();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetNext(FrameThread thread)
{
renderStartSemaphore = thread.renderCompleteSemaphore;
}
}
}