daily update on 20240320 by nitload youmu
This commit is contained in:
@@ -58,22 +58,22 @@ namespace StgSharp.Graphics
|
||||
internal int width;
|
||||
private GLFWwindow* windowID;
|
||||
|
||||
internal TimeSpanProvider frameTimeProvider;
|
||||
#endregion metadata
|
||||
|
||||
#region glapicount
|
||||
private int missingAPIcount = 0;
|
||||
private int problemAPIcount = 0;
|
||||
#endregion glapicount
|
||||
#region form main
|
||||
#region form time
|
||||
|
||||
private short fpsCount;
|
||||
internal TimeSpanProvider frameTimeProvider;
|
||||
internal TimeSpanProvider fpsCountProvider = new TimeSpanProvider(1.0, TimeSpanProvider.DefaultProvider);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region form thread setting
|
||||
private bool isSingleThread = true;
|
||||
private List<FrameAsyncTask> frameAsyncTaskList = new List<FrameAsyncTask>();
|
||||
#endregion form thread setting
|
||||
|
||||
|
||||
|
||||
protected Form()
|
||||
{
|
||||
}
|
||||
@@ -129,8 +129,6 @@ namespace StgSharp.Graphics
|
||||
|
||||
public unsafe IntPtr WindowID => (IntPtr)windowID;
|
||||
|
||||
internal unsafe GLFWwindow* id => windowID;
|
||||
|
||||
protected FrameBufferSizeHandler FrameBufferSizeCallback
|
||||
{
|
||||
set
|
||||
@@ -140,8 +138,26 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe GLFWwindow* id => windowID;
|
||||
|
||||
internal bool IsSingleThread => isSingleThread;
|
||||
|
||||
|
||||
|
||||
public abstract void Deinit(params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Necessary operation to init this form.
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
public abstract void Init(params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Behaviour of current form when in a frame cycle.
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
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.
|
||||
@@ -179,7 +195,12 @@ namespace StgSharp.Graphics
|
||||
gl = new GLonRender(contextID);
|
||||
}
|
||||
InternalIO.glfwMakeContextCurrent(windowID);
|
||||
gl.SwitchContext();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void PollEvents()
|
||||
{
|
||||
InternalIO.glfwPollEvents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -250,33 +271,12 @@ namespace StgSharp.Graphics
|
||||
public void SetSizeLimit(int minWidth, int minHeight, int maxWidth, int maxHeight)
|
||||
{ InternalIO.glfwSetWindowSizeLimits(this.windowID, minWidth, minHeight, maxWidth, maxHeight); }
|
||||
|
||||
unsafe ~Form() { Marshal.FreeHGlobal(graphicContextID); }
|
||||
|
||||
|
||||
|
||||
public abstract void Deinit(params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Necessary operation to init this form.
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
public abstract void Init(params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Behaviour of current form when in a render cycle. When this form
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
public abstract void Main(params object[] args);
|
||||
|
||||
public unsafe void PollEvents()
|
||||
{
|
||||
InternalIO.glfwPollEvents();
|
||||
}
|
||||
#region form main
|
||||
|
||||
/// <summary>
|
||||
/// Init this form and render it on screen, and respond with operation
|
||||
/// </summary>
|
||||
public unsafe void Show(params object[] args)
|
||||
public unsafe void Show()
|
||||
{
|
||||
if (gl == null)
|
||||
{
|
||||
@@ -284,40 +284,46 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
else
|
||||
{
|
||||
frameTimeProvider = new TimeSpanProvider(1 / 60.0, TimeSpanProvider.DefaultProvider);
|
||||
if (isSingleThread)
|
||||
{
|
||||
while (!ShouldClose)
|
||||
{
|
||||
Main(args);
|
||||
Main();
|
||||
SwapBuffers();
|
||||
PollEvents();
|
||||
frameTimeProvider.WaitNextSpan();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GLonUpdate update = new GLonUpdate((GLcontext*)graphicContextID);
|
||||
FrameAsyncTask renderTask = new FrameAsyncTask(update);
|
||||
FrameAsyncTask updateTask = new FrameAsyncTask(update);
|
||||
FrameAsyncTask updateTask = new AsyncUpdateDataTask(this);
|
||||
FrameAsyncTask renderTask = new AsyncRenderFrameTask(this);
|
||||
frameAsyncTaskList.Add(renderTask);
|
||||
frameAsyncTaskList.Add(updateTask);
|
||||
gl = update;
|
||||
update.ActivatedOperationBuffer = updateTask.opBuffer;
|
||||
SemaphoreSlim frameBeginSemaphore = FrameAsyncTask.CombineAsync(renderTask, updateTask);
|
||||
SemaphoreSlim renderCompleteSemaphor = renderTask.StartAsync();
|
||||
SemaphoreSlim updateCompleteSemaphor = updateTask.StartAsync();
|
||||
while (!ShouldClose)
|
||||
{
|
||||
renderTask.StartAsync();
|
||||
updateTask.StartAsync();
|
||||
FrameAsyncTask.CombineAsync(renderTask, updateTask);
|
||||
frameBeginSemaphore.Release(2);
|
||||
renderCompleteSemaphor.Wait();
|
||||
updateCompleteSemaphor.Wait();
|
||||
SwapBuffers();
|
||||
PollEvents();
|
||||
FrameAsyncTask.ExchangeBuffer(updateTask, renderTask);
|
||||
update.ActivatedOperationBuffer = updateTask.opBuffer;
|
||||
frameTimeProvider.WaitNextSpan();
|
||||
}
|
||||
//TODO 对逻辑线程和渲染线程进行同步,两种gl模式包需要改名字
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static unsafe void InternalSwapBuffers(FrameOperationBuffer operationBuffer, GLcontext* context)
|
||||
{
|
||||
IntPtr window = default;
|
||||
operationBuffer.TryDequeue(out window);
|
||||
InternalIO.glfwSwapBuffers((GLFWwindow*)window);
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void InternalDeinit(params object[] args) { Deinit(args); }
|
||||
@@ -373,8 +379,11 @@ namespace StgSharp.Graphics
|
||||
throw new ArgumentException("Amount of threads should be bigger than 0");
|
||||
}
|
||||
}
|
||||
#endregion form main
|
||||
|
||||
unsafe ~Form() { Marshal.FreeHGlobal(graphicContextID); }
|
||||
|
||||
|
||||
|
||||
#endregion form main
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ using StgSharp.Math;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
@@ -47,6 +48,12 @@ namespace StgSharp.Graphics
|
||||
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))
|
||||
@@ -481,22 +488,60 @@ namespace StgSharp.Graphics
|
||||
|
||||
#endregion gl param queue
|
||||
|
||||
|
||||
}
|
||||
|
||||
//TODO 任务组绑定机制有问题,现在一次只能绑定两个
|
||||
//TODO 目前还不能加载任何任务
|
||||
//TODO 任务的启动逻辑需要重构
|
||||
|
||||
internal class FrameAsyncTask
|
||||
public class FrameAsyncTask
|
||||
{
|
||||
|
||||
private SemaphoreSlim _refrshSemaphore;
|
||||
private SemaphoreSlim _frameCompleteSemaphore;
|
||||
private Task _task;
|
||||
private FrameOperationBuffer opBuffer = new FrameOperationBuffer();
|
||||
protected SemaphoreSlim _frameCompleteSemaphore = new SemaphoreSlim(0, 1);
|
||||
protected SemaphoreSlim _refreshSemaphore;
|
||||
private Task _task;
|
||||
protected Action _taskTODO;
|
||||
protected Func<bool> _terminateSignature;
|
||||
internal FrameOperationBuffer opBuffer;
|
||||
|
||||
internal FrameAsyncTask(GLonUpdate gl)
|
||||
public Action TaskTODO
|
||||
{
|
||||
get => _taskTODO;
|
||||
set => _taskTODO = value;
|
||||
}
|
||||
|
||||
internal FrameAsyncTask(Action action, IglFunc gl)
|
||||
{
|
||||
_taskTODO = action;
|
||||
opBuffer = new FrameOperationBuffer(gl);
|
||||
}
|
||||
|
||||
public static SemaphoreSlim CombineAsync(params FrameAsyncTask[] taskList)
|
||||
{
|
||||
if (taskList.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SemaphoreSlim refresh = new SemaphoreSlim(taskList.Length);
|
||||
foreach (FrameAsyncTask item in taskList)
|
||||
{
|
||||
item._refreshSemaphore = refresh;
|
||||
}
|
||||
return refresh;
|
||||
}
|
||||
|
||||
public static SemaphoreSlim CombineAsync(List<FrameAsyncTask> taskList)
|
||||
{
|
||||
if (taskList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SemaphoreSlim refresh = new SemaphoreSlim(taskList.Count);
|
||||
foreach (FrameAsyncTask item in taskList)
|
||||
{
|
||||
item._refreshSemaphore = refresh;
|
||||
}
|
||||
return refresh;
|
||||
}
|
||||
|
||||
public static void ExchangeBuffer(FrameAsyncTask task0, FrameAsyncTask task1)
|
||||
@@ -506,25 +551,51 @@ namespace StgSharp.Graphics
|
||||
task1.opBuffer = cache;
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
public virtual SemaphoreSlim StartAsync()
|
||||
{
|
||||
_task = new Task(
|
||||
() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_refreshSemaphore.Wait();
|
||||
_taskTODO();
|
||||
_frameCompleteSemaphore.Release();
|
||||
}
|
||||
});
|
||||
_task.Start();
|
||||
await _task;
|
||||
return _frameCompleteSemaphore;
|
||||
}
|
||||
|
||||
public static SemaphoreSlim CombineAsync(FrameAsyncTask task0, FrameAsyncTask task1)
|
||||
|
||||
}
|
||||
|
||||
|
||||
internal sealed class AsyncUpdateDataTask : FrameAsyncTask
|
||||
{
|
||||
public AsyncUpdateDataTask(Form f) : base(f.Main, f.GL)
|
||||
{
|
||||
SemaphoreSlim refresh = new SemaphoreSlim(2);
|
||||
task0._refrshSemaphore = refresh;
|
||||
task1._refrshSemaphore = refresh;
|
||||
return refresh;
|
||||
}
|
||||
public static SemaphoreSlim AsyncWait(FrameAsyncTask task0, FrameAsyncTask task1)
|
||||
}
|
||||
|
||||
internal sealed class AsyncRenderFrameTask : FrameAsyncTask
|
||||
{
|
||||
|
||||
public AsyncRenderFrameTask(Form f) : base(null, f.gl)
|
||||
{
|
||||
SemaphoreSlim refresh = new SemaphoreSlim(2);
|
||||
task0._refrshSemaphore = refresh;
|
||||
task1._refrshSemaphore = refresh;
|
||||
return refresh;
|
||||
TaskTODO = new (
|
||||
() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
FrameOperation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void FrameOperation()
|
||||
{
|
||||
while (opBuffer.CallNext()){}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ namespace StgSharp.Graphics
|
||||
|
||||
#endregion texture setting
|
||||
|
||||
|
||||
}
|
||||
|
||||
public enum Filter
|
||||
|
||||
@@ -149,7 +149,6 @@ namespace StgSharp.Graphics
|
||||
|
||||
}
|
||||
|
||||
//TODO 发现一个大问题,paramQueue大多数时候取出的是数组,不是数组句柄,也就是说其内存将被长期固定且不能回收,这是内存泄漏
|
||||
public unsafe class glArrayHandle
|
||||
{
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace StgSharp.Graphics
|
||||
|
||||
default:
|
||||
InternalIO.InternalWriteLog(
|
||||
$"{($"Parameter error in parameter {nameof(type)} method DrawElements. ")}{($"Only {typeof(uint).Name},{typeof(ushort).Name},{typeof(byte).Name} types are suporrted.")}",
|
||||
$"{$"Parameter error in parameter {nameof(type)} method DrawElements. "}{$"Only {typeof(uint).Name},{typeof(ushort).Name},{typeof(byte).Name} types are suporrted."}",
|
||||
LogType.Error);
|
||||
return;
|
||||
}
|
||||
@@ -333,9 +333,6 @@ namespace StgSharp.Graphics
|
||||
api->glEnableVertexAttribArray(index);
|
||||
}
|
||||
|
||||
void IglFunc.SwitchContext()
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.TextureImage2d<T>(int target, int level, uint internalformat, uint width, uint height, uint format, uint type, glHandle pixels)
|
||||
|
||||
@@ -48,14 +48,9 @@ namespace StgSharp.Graphics
|
||||
|
||||
private GLcontext* api;
|
||||
private FrameOperationBuffer frameOpBuffer;
|
||||
private glSHandle unupdatedFrame = glSHandle.Alloc(0);
|
||||
|
||||
internal GLonUpdate(GLcontext* context)
|
||||
{
|
||||
if (frameOpBuffer == null)
|
||||
{
|
||||
frameOpBuffer = new FrameOperationBuffer();
|
||||
}
|
||||
api = context;
|
||||
}
|
||||
|
||||
@@ -263,7 +258,7 @@ namespace StgSharp.Graphics
|
||||
|
||||
default:
|
||||
InternalIO.InternalWriteLog(
|
||||
$"{($"Parameter error in parameter {type} method DrawElements. ")}{($"Only {TypeCode.Byte}, {TypeCode.UInt16}, {TypeCode.UInt32} types are suporrted.")}",
|
||||
$"{$"Parameter error in parameter {type} method DrawElements. "}{$"Only {TypeCode.Byte}, {TypeCode.UInt16}, {TypeCode.UInt32} types are suporrted."}",
|
||||
LogType.Error);
|
||||
return;
|
||||
}
|
||||
@@ -369,9 +364,6 @@ namespace StgSharp.Graphics
|
||||
frameOpBuffer.MethodEnqueue(SetVertexArrayPtr);
|
||||
}
|
||||
|
||||
void IglFunc.SwitchContext()
|
||||
{
|
||||
}
|
||||
|
||||
unsafe void IglFunc.TextureImage2d<T>(int target, int level, uint internalformat, uint width, uint height, uint format, uint type, glHandle pixels)
|
||||
{
|
||||
@@ -404,8 +396,7 @@ namespace StgSharp.Graphics
|
||||
frameOpBuffer.MethodEnqueue(ViewPortPtr);
|
||||
}
|
||||
|
||||
GLcontext* IglFunc.Context
|
||||
=> api;
|
||||
GLcontext* IglFunc.Context => api;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -997,7 +997,7 @@ namespace StgSharp.Graphics
|
||||
catch (Exception ex)
|
||||
{
|
||||
InternalIO.InternalWriteLog(
|
||||
$"{($"Failed to convert the api {typeof(T).Name}.\n")}{ex.Message}", LogType.Warning);
|
||||
$"{$"Failed to convert the api {typeof(T).Name}.\n"}{ex.Message}", LogType.Warning);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +331,6 @@ namespace StgSharp.Graphics
|
||||
|
||||
internal void frameworkHandleEnqueue(IntPtr handle, params M128[] param);
|
||||
|
||||
internal void SwitchContext();
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user