daily update on 20240328 by nitload youmu, building thread blueprint

This commit is contained in:
YoumuLiu
2024-03-29 11:05:57 +08:00
parent ea2a4a7dcb
commit b207f16616
68 changed files with 1083 additions and 2181 deletions
+312
View File
@@ -0,0 +1,312 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="Form.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and
// this permission notice shall be included in all copies
// or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”,
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using StgSharp.Math;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace StgSharp.Graphics
{
/// <summary>
///
/// </summary>
public abstract unsafe partial class Form
{
private int _frameCount;
private int _frameSpeed;
private short fpsCount;
private IntPtr windowID;
internal LinkedList<Control> allControl;
internal Vector4 backgroundColor;
internal TimeSpanProvider fpsCountProvider;
internal TimeSpanProvider frameTimeProvider;
internal IglFunc gl;
internal IntPtr graphicContextID;
internal int height;
internal IntPtr monitor;
internal string name;
internal Form sharedForm;
internal int width;
protected Form()
{
fpsCountProvider = new TimeSpanProvider(1.0, TimeSpanProvider.DefaultProvider);
_frameSpeed = 0;
_frameCount = 0;
fpsCountProvider.SpanRefreshCallback = new TimeSpanRefeshCallback(
() =>
{
Interlocked.Exchange(ref _frameSpeed, _frameCount);
Interlocked.Exchange(ref _frameCount, 0);
});
frameAsyncThreadList = new List<FrameAsyncThread>();
}
public int CurrentFrameCount => frameTimeProvider.CurrentSpan;
public int FrameSpeed => _frameSpeed;
/// <summary>
/// OpenGL package binded to current form context.
/// A OpenGL context is only binded to current form.
/// </summary>
public IglFunc GL => gl;
/// <summary>
/// Height of this form, represent in <see cref="int"/>
/// </summary>
public int Height
{
get => height;
set => height = value;
}
public bool ShouldClose
{
get
{
return InternalIO.glfwWindowShouldClose(windowID) != 0;
}
set => InternalIO.glfwSetWindowShouldClose(windowID, value ? 1 : 0);
}
/// <summary>
/// Width of this form, represent in <see cref="int"/>
/// </summary>
public Vec2d Size
{
get => new Vec2d(width, height);
set
{
width = (int)value.X;
height = (int)value.Y;
}
}
/// <summary>
/// Width of this form, represent in <see cref="int"/>
/// </summary>
public int Width
{
get => width;
set => width = value;
}
public unsafe IntPtr WindowID => windowID;
internal unsafe IntPtr id => windowID;
protected FrameBufferSizeHandler FrameBufferSizeCallback
{
set
{
IntPtr handlerPtr = Marshal.GetFunctionPointerForDelegate(value);
InternalIO.glfwSetFramebufferSizeCallback(windowID, handlerPtr);
}
}
public abstract void Deinit();
/// <summary>
/// Necessary operation to init this form.
/// </summary>
public abstract void Init();
/// <summary>
/// Behaviour of current form when in a frame cycle.
/// </summary>
public abstract void Main();
/// <summary>
/// Init an OpenGl context if current form has not been binded to any context. and set the context binded to
/// current form as current OpenGL context.
/// </summary>
/// <exception cref="Exception">
/// Something goes wrong and StgSharp fails in creating a new OpenGL context.
/// </exception>
public unsafe void MakeAsCurrentContext()
{
if (windowID == default)
{
IntPtr windowPtr;
byte[] tittleBytes = Encoding.UTF8.GetBytes(name);
if (sharedForm == null)
{
windowPtr = InternalIO.glfwCreateWindow(width, height, tittleBytes, monitor, IntPtr.Zero);
}
else
{
windowPtr = InternalIO.glfwCreateWindow(width, height, tittleBytes, monitor, sharedForm.windowID);
}
if (((long)windowPtr == -1) || ((long)windowPtr == -2))
{
throw new Exception("Cannot create window instance!");
}
else
{
windowID = windowPtr;
}
graphicContextID = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(GLcontext)));
GLcontext* contextID = (GLcontext*)graphicContextID;
*contextID = new GLcontext();
contextID->glGetString = (delegate*<uint, IntPtr>)IntPtr.Zero;
gl = new GLpack(contextID);
}
InternalIO.glfwMakeContextCurrent(windowID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void PollEvents()
{
InternalIO.glfwPollEvents();
}
/// <summary>
/// Set all necessary metadata to current form instance
/// </summary>
public void SetMetadata(int width, int height, string name, IntPtr monitor, Form sharedForm)
{
this.width = width;
this.height = height;
this.name = name;
this.sharedForm = sharedForm;
this.monitor = monitor;
}
/// <summary>
/// Resize the current form
/// </summary>
/// <param name="size">
/// A <see cref="Vec2d"/> (width,height) representing the new size of current form
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetSize(Vec2d size)
{
this.Size = size;
InternalIO.glfwSetWindowSize(this.windowID, (int)size.X, (int)size.Y);
}
/// <summary>
/// Resize the current form
/// </summary>
/// <param name="width">New width of the window</param>
/// <param name="height">New height of the window</param>
public void SetSize(int width, int height)
{
this.Width = width;
this.Height = height;
InternalIO.glfwSetWindowSize(this.windowID, width, height);
}
/// <summary>
/// Set the size limit of current form
/// </summary>
/// <param name="minSize">
/// Minimun size of current form. In form of a <see cref="Vec2d"/> of (width,height)
/// </param>
/// <param name="maxSize">
/// Maximum size of current form. In form of a <see cref="Vec2d"/> of (width,height)
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetSizeLimit(Vec2d minSize, Vec2d maxSize)
{
InternalIO.glfwSetWindowSizeLimits(
this.windowID,
(int)minSize.X,
(int)minSize.Y,
(int)maxSize.X,
(int)maxSize.Y);
}
/// <summary>
/// Set the size limit of current form
/// </summary>
/// <param name="minWidth">Minimum width of current form</param>
/// <param name="minHeight">Minimum height of current form</param>
/// <param name="maxWidth">Maximum width of curent form</param>
/// <param name="maxHeight">Maximum height of current form</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetSizeLimit(int minWidth, int minHeight, int maxWidth, int maxHeight)
{ InternalIO.glfwSetWindowSizeLimits(this.windowID, minWidth, minHeight, maxWidth, maxHeight); }
#region form main
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void InternalDeinit() { Deinit(); }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal unsafe void SwapBuffers()
{
InternalIO.glfwSwapBuffers(windowID);
}
/// <summary>
/// Get OpenGL library of this form's context.
/// </summary>
/// <returns>A <see cref="IglFunc"/> package contains all opengl APIs</returns>
protected IglFunc GetGL()
{
if (StgSharp.API == GraphicAPI.GL)
{
return this.GL;
}
else
{
InternalIO.InternalWriteLog(
"Attempt to get OpenGL API package in other graphic envitronment.",
LogType.Error);
throw new InvalidOperationException("Attempt to get OpenGL API package in other graphic envitronment.");
}
}
unsafe ~Form() { Marshal.FreeHGlobal(graphicContextID); }
#endregion form main
}
}
@@ -0,0 +1,102 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="FormThreadAttribute.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and
// this permission notice shall be included in all copies
// or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”,
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
namespace StgSharp.Graphics
{
/// <summary>
/// Mark that a method in a <see cref="Form"/>
/// should be called when rendering.
/// </summary>
public class RenderActivityAttribute : Attribute
{
internal bool _isRenderProgress;
internal int _priority;
public RenderActivityAttribute(RenderPriority priority, bool IsRenderProgress)
{
_priority = (int)priority; _isRenderProgress = IsRenderProgress;
}
public RenderActivityAttribute(int priority, bool IsRenderProgress)
{
_priority = priority; _isRenderProgress = IsRenderProgress;
}
public int Priority { get => _priority; set => _priority = value; }
}
/// <summary>
/// Priority level of a render activity.
/// </summary>
public enum RenderPriority: int
{
/// <summary>
/// One level higher than <see cref="RenderPriority.Default"/>.
/// </summary>
Pre_1 = -1,
/// <summary>
/// Two level higher than <see cref="RenderPriority.Default"/>.
/// </summary>
Pre_2 = -2,
/// <summary>
/// Three level higher than <see cref="RenderPriority.Default"/>.
/// </summary>
Pre_3 = -3,
/// <summary>
/// One level lower than <see cref="RenderPriority.Default"/>.
/// </summary>
Aft_1 = 1,
/// <summary>
/// Two level lower than <see cref="RenderPriority.Default"/>.
/// </summary>
Aft_2 = 2,
/// <summary>
/// Three level lower than <see cref="RenderPriority.Default"/>.
/// </summary>
Aft_3 = 3,
/// <summary>
/// Highest priority, in <see cref="RenderPriority"/>, it is <see cref="Pre_3"/>.
/// </summary>
Highest = Pre_3,
/// <summary>
/// Default priority, usually <see cref="Form.Main"/> is in this priority.
/// </summary>
Default = 0,
/// <summary>
/// Lowest priority, in <see cref="RenderPriority"/>, it is <see cref="Aft_3"/>.
/// </summary>
Least = Aft_3,
}
}
@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.Graphics
{
public abstract partial class Form
{
#region form thread setting
private List<FrameAsyncThread> frameAsyncThreadList;
#endregion form thread setting
/// <summary>
/// Init this form and render it on screen, and respond with operation
/// </summary>
public unsafe void Show()
{
if (gl == null)
{
InternalIO.InternalWriteLog($"Attempt to show form {name} before init", LogType.Error);
}
else
{
frameTimeProvider = new TimeSpanProvider(1 / 60.0, TimeSpanProvider.DefaultProvider);
MethodInfo[] methods = this.GetType().GetMethods(
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
if (methods.Length != 0)
{
foreach (MethodInfo m in methods) //find all methods decorated by RenderActivityAttribute
{
RenderActivityAttribute attr = m.GetCustomAttribute<RenderActivityAttribute>(false);
if (attr == null)
{
continue;
}
if (!m.IsStatic && (m.GetParameters().Length != 0) && (m.ReturnType != typeof(void)))
{
throw new NotSupportedException("A render activity cannot have parameters, returning value or be static.");
}
if (m.Name != "Main")
{
ThreadStart s = (ThreadStart)Delegate.CreateDelegate(typeof(ThreadStart), this, m);
FrameAsyncThread t = new(s,attr._priority);
frameAsyncThreadList.Add(t);
}
}
}
List<IGrouping<int,FrameAsyncThread>> threadGroup = frameAsyncThreadList.GroupBy<FrameAsyncThread, int>((t) => t.Priority).ToList();
int priority = 0;
foreach (var group in threadGroup)
{
foreach (var t in group)
{
t.Priority = priority;
}
priority++;
}
(Barrier, Barrier) b = FrameAsyncThread.CombineAsync(true, frameAsyncThreadList);
FrameAsyncThread.AsyncStartAll(frameAsyncThreadList);
if (b.Item1 == null)
{
while (!ShouldClose)
{
Main();
SwapBuffers();
PollEvents();
frameTimeProvider.WaitNextSpan();
Interlocked.Add(ref _frameCount, 1);
}
}
else
{
while (!ShouldClose)
{
b.Item1.SignalAndWait();
Main();
b.Item2.SignalAndWait();
SwapBuffers();
PollEvents();
frameTimeProvider.WaitNextSpan();
Interlocked.Add(ref _frameCount, 1);
}
FrameAsyncThread.TerminateAll(frameAsyncThreadList);
b.Item1.SignalAndWait();
FrameAsyncThread.WaitAll(frameAsyncThreadList);
}
//InternalDeinit();
}
}
}
}
@@ -0,0 +1,625 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="FrameAsyncThread.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and
// this permission notice shall be included in all copies
// or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”,
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using StgSharp.Math;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.Graphics
{
internal sealed class FrameOperationBuffer
{
private IntPtr _func;
private ConcurrentQueue<IntPtr> _funcQueue;
private readonly unsafe GLcontext* currentContext;
public unsafe FrameOperationBuffer(IglFunc gl)
{
currentContext = gl.Context;
_funcQueue = new ConcurrentQueue<IntPtr>();
}
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.Write(paramQueue.Count + streamQueue.Count);
//Console.Write($":{m.ToString(16)}\n");
}
[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)
{
m = new();
bool ret = paramQueue.TryDequeue(out m);
Console.WriteLine(m.ToString(16));
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
}
public class FrameAsyncThread
{
private Thread _task;
private volatile int _terminateToken;
private int _priority;
protected Barrier _frameSpeedSyncBarrier;
protected Barrier _spanCompleteBarrier;
protected ThreadStart _taskTODO;
public FrameAsyncThread(ThreadStart action, int priority)
{
_taskTODO = action;
_terminateToken = 1;
_spanCompleteBarrier = new Barrier(2);
_priority = priority;
}
public int Priority
{
get => _priority;
internal set { _priority = value; }
}
public ThreadStart TaskTODO
{
get => _taskTODO;
set => _taskTODO = value;
}
public Barrier TodoCompleteBarrier
=> _spanCompleteBarrier;
public void AsyncStart()
{
_task = new Thread(
() =>
{
while (true)
{
_frameSpeedSyncBarrier.SignalAndWait();
if (_terminateToken == 0)
{
break;
}
_taskTODO();
_spanCompleteBarrier.SignalAndWait();
}
Console.WriteLine("Thread terminated");
});
_task.Start();
}
public static void AsyncStartAll(IEnumerable<FrameAsyncThread> threadList)
{
foreach (FrameAsyncThread t in threadList)
{
t.AsyncStart();
}
}
public static void WaitAll(IEnumerable<FrameAsyncThread> threadList)
{
foreach (FrameAsyncThread t in threadList)
{
t._task.Join();
}
}
public static (Barrier, Barrier) CombineAsync(bool needOuterMonitor, IEnumerable<FrameAsyncThread> taskList)
{
if (taskList.Count() == 0)
{
return (null, null);
}
Barrier b_start = new Barrier(taskList.Count() + (needOuterMonitor ? 1 : 0));
Barrier b_complete = new Barrier(taskList.Count() + (needOuterMonitor ? 1 : 0));
foreach (FrameAsyncThread item in taskList)
{
item._frameSpeedSyncBarrier = b_start;
item._spanCompleteBarrier = b_complete;
}
return (b_start, b_complete);
}
public static (Barrier, Barrier) CombineAsync(bool needOuterMonitor, params FrameAsyncThread[] taskList)
{
if (taskList.Length == 0)
{
return (null, null);
}
Barrier b_start = new Barrier(taskList.Length + (needOuterMonitor ? 1 : 0));
Barrier b_complete = new Barrier(taskList.Length + (needOuterMonitor ? 1 : 0));
foreach (FrameAsyncThread item in taskList)
{
item._frameSpeedSyncBarrier = b_start;
item._spanCompleteBarrier = b_complete;
}
return (b_start, b_complete);
}
public void Terminate()
{
Interlocked.Exchange(ref _terminateToken,0);
}
public static void TerminateAll(params FrameAsyncThread[] threadList)
{
foreach (FrameAsyncThread t in threadList)
{
t.Terminate();
}
}
public static void TerminateAll(IEnumerable<FrameAsyncThread> threadList)
{
foreach (FrameAsyncThread t in threadList)
{
t.Terminate();
}
}
}
}