Daily update on 20250316-095544 by Nitload Youmu. Additional Message : Linear math inmprovement

Signed-off-by: Nitload <YoumuLiu_NSI@whv0t.onmicrosoft.com>
This commit is contained in:
Nitload
2025-03-16 09:55:44 +08:00
parent 753cc167bc
commit a5aef8506d
58 changed files with 3162 additions and 506 deletions
+78 -44
View File
@@ -1,4 +1,34 @@
using System;
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="ListSegment.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;
using System.Collections.Generic;
using System.Linq;
@@ -10,42 +40,67 @@ using System.Xml.Serialization;
namespace StgSharp.Collections
{
/// <summary>
/// Part of a collection. This contains a direct reference to origin collection,
/// so all change to origin collection will be reflected in this object.
/// Part of a collection. This contains a direct reference to _origin collection, so all change
/// to _origin collection will be reflected in this object.
/// </summary>
/// <typeparam name="T"></typeparam>
public struct ListSegment<T> : ICollection<T>
{
private List<T> _collection;
private int _begin;
private int _length;
private List<T> _collection;
public ListSegment(List<T> collection, int begin, int length)
public ListSegment( List<T> collection, int begin, int length )
{
ArgumentNullException.ThrowIfNull(collection);
ArgumentOutOfRangeException.ThrowIfLessThan(begin, 0);
ArgumentOutOfRangeException.ThrowIfLessThan(length, 0);
ArgumentOutOfRangeException.ThrowIfLessThan(begin + length, collection.Count);
ArgumentNullException.ThrowIfNull( collection );
ArgumentOutOfRangeException.ThrowIfLessThan( begin, 0 );
ArgumentOutOfRangeException.ThrowIfLessThan( length, 0 );
ArgumentOutOfRangeException.ThrowIfLessThan(
begin + length, collection.Count );
_collection = collection;
_begin = begin;
_length = length;
}
}
public int Count => _length;
public bool IsReadOnly => true;
public T this[int indexValue]
public T this[ int indexValue ]
{
get {
ArgumentOutOfRangeException.ThrowIfLessThan(indexValue, 0);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(indexValue, _length);
return _collection[indexValue + _begin];
get
{
ArgumentOutOfRangeException.ThrowIfLessThan( indexValue, 0 );
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(
indexValue, _length );
return _collection[ indexValue + _begin ];
}
}
void ICollection<T>.Add(T item)
public bool IsReadOnly => true;
public int Count => _length;
public bool Contains( T item )
{
int index = _collection.IndexOf( item );
return index >= _begin && index < _length + index;
}
public void CopyTo( T[] array, int arrayIndex )
{
ArgumentNullException.ThrowIfNull( array );
Span<T> span = CollectionsMarshal.AsSpan<T>( _collection )
.Slice( _begin, _length );
Span<T> target = new Span<T>( array, arrayIndex, _length );
span.CopyTo( target );
}
public IEnumerator<T> GetEnumerator()
{
for( int i = _begin; i < _length; i++ ) {
yield return this[ i ];
}
}
void ICollection<T>.Add( T item )
{
throw new NotSupportedException();
}
@@ -55,29 +110,7 @@ namespace StgSharp.Collections
throw new NotSupportedException();
}
public bool Contains(T item)
{
var index= _collection.IndexOf(item);
return index >= _begin && index < _length + index;
}
public void CopyTo(T[] array, int arrayIndex)
{
ArgumentNullException.ThrowIfNull(array);
var span = CollectionsMarshal.AsSpan<T>(_collection).Slice(_begin, _length);
var target = new Span<T>(array, arrayIndex,_length);
span.CopyTo(target);
}
public IEnumerator<T> GetEnumerator()
{
for (int i = _begin; i < _length; i++)
{
yield return this[i];
}
}
bool ICollection<T>.Remove(T item)
bool ICollection<T>.Remove( T item )
{
throw new NotSupportedException();
}
@@ -86,5 +119,6 @@ namespace StgSharp.Collections
{
return GetEnumerator();
}
}
}
+117
View File
@@ -0,0 +1,117 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="Counter.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.Numerics;
namespace StgSharp
{
public class Counter<T> where T: struct, INumber<T>
{
internal dynamic _value;
internal readonly T _defaultValue;
internal readonly T _defualtDecreament;
internal readonly T _defualtIncreament;
public Counter(
T defualtValue,
T defualtIncreament,
T defualtDecreament )
{
_value = defualtValue;
_defaultValue = defualtValue;
_defualtIncreament = defualtIncreament;
_defualtDecreament = defualtDecreament;
}
public T DecreamentSoan => _defualtDecreament;
public T IncreamentSpan => _defualtIncreament;
public T CurrentSpan => _value - _defaultValue;
public T Value
{
get => _value;
set => _value = value;
}
public void Add( T value )
{
_value += value;
}
public void QuickAdd()
{
_value += _defualtIncreament;
}
public void QuickSub()
{
_value -= _defualtDecreament;
}
public void Reset()
{
_value = _defaultValue;
}
public void Sub( T value )
{
_value -= value;
}
public override string ToString() => Value.ToString();
public static Counter<T> operator --( Counter<T> counter )
{
counter.QuickSub();
return counter;
}
public static Counter<T> operator ++( Counter<T> counter )
{
counter.QuickAdd();
return counter;
}
public static implicit operator T( Counter<T> counter )
{
return counter switch
{
null => T.Zero,
_ => counter.Value
};
}
}
}
+1 -1
View File
@@ -75,7 +75,7 @@ namespace StgSharp.Data
/// <summary>
/// A class attempt to reduce cost of boxing, though still a bit slower than direct access to
/// origin value type instance.
/// _origin value type instance.
/// </summary>
/// <typeparam name="T"> Type of instance to be boxed. </typeparam>
public class ValueBox<T> : IValueBox, IValueBox<T> where T: struct
+1 -1
View File
@@ -88,7 +88,7 @@ namespace StgSharp.Geometries
{
get { return GlobalBuffer.CoordAndRotationList[ BufferId ].XYZ; }
set { GlobalBuffer.CoordAndRotationList[ BufferId ] = new Vec4(
value.vec ); }
value.reg ); }
}
public void Move()
@@ -47,14 +47,14 @@ namespace StgSharp.Geometries
internal Matrix32 axis;
/// <summary>
/// The origin of this coordinate.
/// The _origin of this coordinate.
/// </summary>
public Vec3 origin;
public PartialPlainCoordinate(
Vec3 origin,
Vec3 horiziontial,
Vec3 vertical )
Vec3 origin,
Vec3 horiziontial,
Vec3 vertical )
{
this.origin = origin;
axis = new Matrix32();
@@ -38,30 +38,22 @@ namespace StgSharp.Geometries
{
internal readonly float d = -1;
internal Vec3 origin;
internal Vec3 _origin;
internal Vec3 plainParameter;
internal Vec3 vec1;
internal Vec3 vec2;
internal Plain( Vector4 origin, Vector4 p1, Vector4 p2 )
{
this.origin = new Vec3( origin );
vec1 = new Vec3( p1 - origin );
vec2 = new Vec3( p2 - origin );
}
public Plain( Vec3 o, Vec3 v1, Vec3 v2 )
{
this.origin = o;
this.vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //计算平面在xz平面上的方向投影
this.vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //计算平面在yz平面上的方向投影
this._origin = o;
this.vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //xz
this.vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //yz
//|origin|-k1*|vec1|-k2*|vec2|计算plainParameter.Z;
plainParameter.Z = origin.Z - ( vec1.Z * ( origin.X / vec1.X ) ) - ( vec2.Z * ( origin.Y / vec2.Y ) );
//|_origin|-k1*|vec1|-k2*|vec2| --> plainParameter.Z;
plainParameter.Z = _origin.Z - ( vec1.Z * ( _origin.X / vec1.X ) ) - ( vec2.Z * ( _origin.Y / vec2.Y ) );
//根据plainParameter.Z和对应的方向矢量计算plainParameter.X和plainParameter.Y
//plainParameter.Z -> plainParameter.X, plainParameter.Y
plainParameter.X = vec1.X * ( vec1.Z / plainParameter.Z );
plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z );
@@ -77,13 +69,13 @@ namespace StgSharp.Geometries
Vec3 v2 = p3.Coord - origin;
vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //计算平面在xz平面上的方向投影
vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //计算平面在yz平面上的方向投影
vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //xz
vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //yz
//|origin|-k1*|vec1|-k2*|vec2|计算plainParameter.Z;
//|_origin|-k1*|vec1|-k2*|vec2| --> plainParameter.Z;
plainParameter.Z = origin.Z - ( vec1.Z * ( origin.X / vec1.X ) ) - ( vec2.Z * ( origin.Y / vec2.Y ) );
//根据plainParameter.Z和对应的方向矢量计算plainParameter.X和plainParameter.Y
//plainParameter.Z --> plainParameter.X, plainParameter.Y
plainParameter.X = vec1.X * ( vec1.Z / plainParameter.Z );
plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z );
@@ -48,24 +48,24 @@ namespace StgSharp.Geometries
}
public Polygon6(
PlainCoordinate coordination,
Vec2 vert0,
Vec2 vert1,
Vec2 vert2,
Vec2 vert3,
Vec2 vert4,
Vec2 vert5,
Vec2 vert6 )
PlainCoordinate coordination,
Vec2 vert0,
Vec2 vert1,
Vec2 vert2,
Vec2 vert3,
Vec2 vert4,
Vec2 vert5,
Vec2 vert6 )
: base( coordination )
{
vertexMat = new Vec4[6];
vertexMat[ 0 ].vec = vert0.vec;
vertexMat[ 1 ].vec = vert1.vec;
vertexMat[ 2 ].vec = vert2.vec;
vertexMat[ 3 ].vec = vert3.vec;
vertexMat[ 4 ].vec = vert4.vec;
vertexMat[ 5 ].vec = vert5.vec;
vertexMat[ 6 ].vec = vert6.vec;
vertexMat[ 0 ].reg = vert0.reg;
vertexMat[ 1 ].reg = vert1.reg;
vertexMat[ 2 ].reg = vert2.reg;
vertexMat[ 3 ].reg = vert3.reg;
vertexMat[ 4 ].reg = vert4.reg;
vertexMat[ 5 ].reg = vert5.reg;
vertexMat[ 6 ].reg = vert6.reg;
}
public override ReadOnlySpan<int> VertexIndices => Indices;
+18 -18
View File
@@ -72,10 +72,10 @@ namespace StgSharp.Graphics.OpenGL
/// <param _name="bufferData"> Data to write in </param>
/// <param _name="usage"> How OpenGL use these _data, defined by <see cref="BufferUsage" /></param>
public void WriteMatrixData<T>(
int index,
T bufferData,
BufferUsage usage )
where T: struct, IMat
int index,
T bufferData,
BufferUsage usage )
where T: struct, IMatrix<T>
{
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
GL.SetBufferData( BufferType.ArrayBuffer, bufferData, usage );
@@ -89,9 +89,9 @@ namespace StgSharp.Graphics.OpenGL
/// <param _name="bufferArray"> Data to write in </param>
/// <param _name="usage"> How OpenGL use these _data, defined by <see cref="BufferUsage" /></param>
public void WriteScalerData<T>(
int index,
T[] bufferArray,
BufferUsage usage )
int index,
T[] bufferArray,
BufferUsage usage )
where T: struct, INumber<T>
{
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
@@ -106,9 +106,9 @@ namespace StgSharp.Graphics.OpenGL
/// <param _name="scalerSpan"> A <see cref="Span{T}" /> of _data to write in </param>
/// <param _name="usage"> How OpenGL use these _data, defined by <see cref="BufferUsage" /></param>
public void WriteScalerData<T>(
int index,
ReadOnlySpan<T> scalerSpan,
BufferUsage usage )
int index,
ReadOnlySpan<T> scalerSpan,
BufferUsage usage )
where T: struct,INumber<T>
{
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
@@ -123,10 +123,10 @@ namespace StgSharp.Graphics.OpenGL
/// <param _name="vectorSpan"> A <see cref="Span{T}" /> of _data to write in </param>
/// <param _name="usage"> How OpenGL use these _data, defined by <see cref="BufferUsage" /></param>
public void WriteVectorData<T>(
int index,
ReadOnlySpan<T> vectorSpan,
BufferUsage usage )
where T: struct, IVector
int index,
ReadOnlySpan<T> vectorSpan,
BufferUsage usage )
where T: struct, IVector<T>
{
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorSpan, usage );
@@ -140,10 +140,10 @@ namespace StgSharp.Graphics.OpenGL
/// <param _name="vectorArray"> A array of _data to write in </param>
/// <param _name="usage"> How OpenGL use these _data, defined by <see cref="BufferUsage" /></param>
public void WriteVectorData<T>(
int index,
T[] vectorArray,
BufferUsage usage )
where T: struct, IVector
int index,
T[] vectorArray,
BufferUsage usage )
where T: struct, IVector<T>
{
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorArray,
+117 -116
View File
@@ -157,7 +157,7 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public FrameBufferStatus CheckFrameBufferStatus(
FrameBufferTarget target )
FrameBufferTarget target )
{
return ( FrameBufferStatus )Context.glCheckFramebufferStatus(
( uint )target );
@@ -201,8 +201,8 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void CombineFrameBufferRenderBuffer(
FrameBufferAttachment attachment,
GlHandle rboHandle )
FrameBufferAttachment attachment,
GlHandle rboHandle )
{
Context.glFramebufferRenderbuffer(
glConst.FRAMEBUFFER, ( uint )attachment, glConst.RENDERBUFFER,
@@ -298,10 +298,10 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void DrawElements(
GeometryType mode,
uint count,
TypeCode type,
IntPtr ptr )
GeometryType mode,
uint count,
TypeCode type,
IntPtr ptr )
{
uint a;
a = type switch
@@ -317,11 +317,11 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void DrawElementsInstanced(
GeometryType mode,
uint count,
TypeCode type,
IntPtr ptr,
uint amount )
GeometryType mode,
uint count,
TypeCode type,
IntPtr ptr,
uint amount )
{
uint a;
switch( type ) {
@@ -355,11 +355,11 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void FrameBufferTexture2d(
FrameBufferTarget target,
uint attachment,
Texture2DTarget texTarget,
GlHandle textureHandle,
int level )
FrameBufferTarget target,
uint attachment,
Texture2DTarget texTarget,
GlHandle textureHandle,
int level )
{
Context.glFramebufferTexture2D(
( uint )target, attachment, ( uint )texTarget,
@@ -439,7 +439,8 @@ namespace StgSharp.Graphics.OpenGL
{
IntPtr sptr = IntPtr.Zero;
if( InternalIO.glCheckShaderStatus(
ref Context, s.handle[ index ].Value, key, ref sptr ) == 0 ) {
ref Context, s.handle[ index ].Value, key, ref sptr ) ==
0 ) {
return Marshal.PtrToStringAnsi( sptr );
}
return string.Empty;
@@ -447,11 +448,11 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void GetTextureImage<T>(
Texture2DTarget target,
int level,
ImageChannel channel,
PixelChannelLayout channelLayout,
T[] dataStream )
Texture2DTarget target,
int level,
ImageChannel channel,
PixelChannelLayout channelLayout,
T[] dataStream )
where T: struct,INumber<T>
{
#pragma warning disable CS8500
@@ -465,10 +466,10 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void GetTextureLevelProperty(
uint textureTypeMask,
int level,
uint propertyMask,
out int propertyValue )
uint textureTypeMask,
int level,
uint propertyMask,
out int propertyValue )
{
fixed( int* iptr = &propertyValue ) {
Context.glGetTexLevelParameteriv(
@@ -478,14 +479,15 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe GlHandle GetUniformLocation(
GlHandle program,
string name )
GlHandle program,
string name )
{
byte[] code = Encoding.UTF8.GetBytes( name );
fixed( byte* ptr = code ) {
int ret = Context.glGetUniformLocation( program.Value, ptr );
#if DEBUG
if( ( ret == glConst.INVALID_OPERATION ) || ( ret == glConst.INVALID_VALUE ) ) {
if( ( ret == glConst.INVALID_OPERATION ) || ( ret ==
glConst.INVALID_VALUE ) ) {
throw new InvalidOperationException();
}
if( ret == -1 ) {
@@ -499,8 +501,8 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void LoadShaderSource(
GlHandle shaderHandle,
byte[] codeStream )
GlHandle shaderHandle,
byte[] codeStream )
{
fixed( byte* streamPtr = codeStream ) {
Context.glShaderSource(
@@ -509,24 +511,23 @@ namespace StgSharp.Graphics.OpenGL
}
public unsafe void LoadShaderSource(
GlHandle shaderHandle,
ReadOnlySpan<char> codeStream)
GlHandle shaderHandle,
ReadOnlySpan<char> codeStream )
{
fixed (char* streamPtr = codeStream)
{
byte* bptr = (byte*)streamPtr;
fixed( char* streamPtr = codeStream ) {
byte* bptr = ( byte* )streamPtr;
Context.glShaderSource(
shaderHandle.Value, 1, &bptr, (void*)0);
shaderHandle.Value, 1, &bptr, ( void* )0 );
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void ReadPixels(
(int X, int Y) beginPosition,
(int width, int height) size,
FrameBufferChannel format,
PixelChannelLayout dataType,
ref byte[] stream )
(int X, int Y) beginPosition,
(int width, int height) size,
FrameBufferChannel format,
PixelChannelLayout dataType,
ref byte[] stream )
{
fixed( byte* bptr = stream ) {
Context.glReadPixels(
@@ -536,10 +537,10 @@ namespace StgSharp.Graphics.OpenGL
}
public void RereadImage(
in Image i,
(int X, int Y) beginPosition,
FrameBufferChannel format,
PixelChannelLayout dataType )
in Image i,
(int X, int Y) beginPosition,
FrameBufferChannel format,
PixelChannelLayout dataType )
{
byte[] pixels = i.PixelBuffer;
if( !pixels.CheckArrayFormat( dataType ) ) {
@@ -555,9 +556,9 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetBufferData<T>(
BufferType bufferType,
T bufferData,
BufferUsage usage )
BufferType bufferType,
T bufferData,
BufferUsage usage )
where T: struct
{
int size = Marshal.SizeOf<T>();
@@ -571,30 +572,9 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetBufferData<T>(
BufferType bufferType,
T[] bufferArray,
BufferUsage usage )
where T: struct,INumber<T>
{
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
if( bufferArray == null ) {
return;
}
#pragma warning disable CS8500
fixed( void* bufferPtr = bufferArray )
#pragma warning restore CS8500
{
Context.glBufferData(
( uint )bufferType, ( IntPtr )size, ( IntPtr )bufferPtr,
( uint )usage );
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetBufferData<T>(
BufferType bufferType,
ReadOnlySpan<T> bufferArray,
BufferUsage usage )
BufferType bufferType,
T[] bufferArray,
BufferUsage usage )
where T: struct,INumber<T>
{
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
@@ -613,9 +593,30 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetBufferData<T>(
BufferType bufferType,
Span<T> bufferArray,
BufferUsage usage )
BufferType bufferType,
ReadOnlySpan<T> bufferArray,
BufferUsage usage )
where T: struct,INumber<T>
{
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
if( bufferArray == null ) {
return;
}
#pragma warning disable CS8500
fixed( void* bufferPtr = bufferArray )
#pragma warning restore CS8500
{
Context.glBufferData(
( uint )bufferType, ( IntPtr )size, ( IntPtr )bufferPtr,
( uint )usage );
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetBufferData<T>(
BufferType bufferType,
Span<T> bufferArray,
BufferUsage usage )
where T: struct, INumber<T>
{
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
@@ -635,10 +636,10 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetBufferVectorData<T>(
BufferType bufferType,
ReadOnlySpan<T> bufferArray,
BufferUsage usage )
where T: struct, IVector
BufferType bufferType,
ReadOnlySpan<T> bufferArray,
BufferUsage usage )
where T: struct, IVector<T>
{
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
if( bufferArray == null ) {
@@ -656,10 +657,10 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetBufferVectorData<T>(
BufferType bufferType,
T[] bufferArray,
BufferUsage usage )
where T: struct, IVector
BufferType bufferType,
T[] bufferArray,
BufferUsage usage )
where T: struct, IVector<T>
{
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
if( bufferArray == null ) {
@@ -677,8 +678,8 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetRenderBufferStorage(
RenderBufferInternalFormat internalFormat,
(int width, int height) size )
RenderBufferInternalFormat internalFormat,
(int width, int height) size )
{
Context.glRenderbufferStorage(
glConst.RENDERBUFFER, ( uint )internalFormat, size.width,
@@ -687,8 +688,8 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe void SetRenderBufferStorage(
RenderBufferInternalFormat internalFormat,
(uint width, uint height) size )
RenderBufferInternalFormat internalFormat,
(uint width, uint height) size )
{
Context.glRenderbufferStorage(
glConst.RENDERBUFFER, ( uint )internalFormat, ( int )size.width,
@@ -697,12 +698,12 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void SetVertexAttribute(
uint index,
int size,
TypeCode t,
bool normalized,
uint stride,
int pointer )
uint index,
int size,
TypeCode t,
bool normalized,
uint stride,
int pointer )
{
uint type = InternalIO.GLtype[ t ];
Context.glVertexAttribPointer(
@@ -713,20 +714,20 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void TextureImage2d<T>(
Texture2DTarget target,
int level,
ImageChannel sourceChannel,
uint width,
uint height,
ImageChannel targetChannel,
PixelChannelLayout type,
T[] pixels )
Texture2DTarget target,
int level,
ImageChannel sourceChannel,
uint width,
uint height,
ImageChannel targetChannel,
PixelChannelLayout type,
T[] pixels )
where T: struct, INumber<T>
{
#pragma warning disable CS8500
fixed( T* tptr = pixels ) {
T* ptr = ( ( pixels == null ) || ( pixels.Length == 0 ) ) ?
( T* )IntPtr.Zero : tptr;
( T* )IntPtr.Zero : tptr;
Context.glTexImage2D(
( uint )target, level, ( uint )sourceChannel, width, height,
0, ( uint )targetChannel, ( uint )type, tptr );
@@ -736,23 +737,23 @@ namespace StgSharp.Graphics.OpenGL
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void TextureImage2d<T>(
Texture2DTarget target,
int level,
ImageChannel sourceChannel,
uint width,
uint height,
ImageChannel targetChannel,
PixelChannelLayout type,
Span<T> pixelSpan )
Texture2DTarget target,
int level,
ImageChannel sourceChannel,
uint width,
uint height,
ImageChannel targetChannel,
PixelChannelLayout type,
Span<T> pixelSpan )
where T: struct, INumber<T>
{
#pragma warning disable CS8500
#pragma warning disable CS8500
fixed( T* tptr = pixelSpan ) {
Context.glTexImage2D(
( uint )target, level, ( uint )sourceChannel, width, height,
0, ( uint )targetChannel, ( uint )type, tptr );
}
#pragma warning restore CS8500
#pragma warning restore CS8500
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
@@ -762,8 +763,8 @@ namespace StgSharp.Graphics.OpenGL
}
public static bool TryGetFunctionPackage(
IntPtr handle,
out OpenGLFunction functionPackage )
IntPtr handle,
out OpenGLFunction functionPackage )
{
return contextToGLMap.TryGetValue( handle, out functionPackage );
}
+27 -2
View File
@@ -70,11 +70,36 @@ namespace StgSharp.Graphics
}
[StructLayout( LayoutKind.Explicit, Size = 32 )]
public unsafe struct Pixel32
public unsafe struct Pixel32RGBA : IPixel
{
[FieldOffset( 0 )] private unsafe fixed byte data[ 4 ];
internal int Size => 4;
public int Size => 4;
float IPixel.Alpha
{
get => data[ 3 ] / 256 ;
set => data[ 3 ] = ( byte )( value * 256 );
}
float IPixel.Blue
{
get => data[ 2 ] / 256 ;
set => data[ 2 ] = ( byte )( value * 256 );
}
float IPixel.Green
{
get => data[ 1 ] / 256 ;
set => data[ 1 ] = ( byte )( value * 256 );
}
float IPixel.Red
{
get => data[ 0 ] / 256 ;
set => data[ 0 ] = ( byte )( value * 256 );
}
}
}
+7 -11
View File
@@ -47,8 +47,8 @@ namespace StgSharp.Graphics
private TextureProvider _texture;
public PlainGeometryMesh(
[NotNull] PlainGeometry shape,
[NotNull] TextureProvider texture )
[NotNull] PlainGeometry shape,
[NotNull] TextureProvider texture )
{
if( shape.VertexCount > texture.TextureCoordinate.Length ) {
throw new ArgumentException(
@@ -62,16 +62,12 @@ namespace StgSharp.Graphics
//private Image _texture;
public PlainGeometryMesh(
PlainGeometry shape,
Image texture,
Vec2[] texCoord )
PlainGeometry shape,
Image texture,
Vec2[] texCoord )
{
if( shape == null ) {
throw new ArgumentNullException( nameof( shape ) );
}
if( texCoord == null ) {
throw new ArgumentNullException( nameof( texCoord ) );
}
ArgumentNullException.ThrowIfNull( shape );
ArgumentNullException.ThrowIfNull( texCoord );
if( shape.VertexCount > texCoord.Length ) {
throw new ArgumentException(
+2 -2
View File
@@ -29,7 +29,7 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using StgSharp.Blueprint;
using StgSharp.PipeLine;
using System;
using System.Collections.Generic;
@@ -39,7 +39,7 @@ using System.Threading.Tasks;
namespace StgSharp.Graphics
{
public class TexturePipeline : BlueprintPipelineArgs
public class TexturePipeline : PipeLineConnectorArgs
{
private Image _value;
+18 -14
View File
@@ -34,10 +34,8 @@ using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
using System.Text;
@@ -48,11 +46,11 @@ namespace StgSharp.HighPerformance
{
[FieldOffset( 0 )] internal fixed byte Buffer[ 16 ];
[FieldOffset( 0 )] internal Vector128<byte> Vec;
[FieldOffset( 0 )] internal Vector128<float> Vec;
internal M128( Vector4 v )
{
Vec = v.AsVector128().AsByte();
Vec = v.AsVector128();
}
public ref T AsRef<T>() where T: struct, INumber<T>
@@ -60,6 +58,12 @@ namespace StgSharp.HighPerformance
return ref Unsafe.As<byte, T>( ref Buffer[ 0 ] );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public Vector4 AsVector4()
{
return Vec.As<float, float>().AsVector4();
}
public override bool Equals( [NotNullWhen( true )] object obj )
{
if( obj is not M128 other ) {
@@ -123,61 +127,61 @@ namespace StgSharp.HighPerformance
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<byte>( M128 m )
{
return m.Vec.As<byte, byte>();
return m.Vec.As<float, byte>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<double>( M128 m )
{
return m.Vec.As<byte, double>();
return m.Vec.As<float, double>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<float>( M128 m )
{
return m.Vec.As<byte, float>();
return m.Vec.As<float, float>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<int>( M128 m )
{
return m.Vec.As<byte, int>();
return m.Vec.As<float, int>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<long>( M128 m )
{
return m.Vec.As<byte, long>();
return m.Vec.As<float, long>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<sbyte>( M128 m )
{
return m.Vec.As<byte, sbyte>();
return m.Vec.As<float, sbyte>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<short>( M128 m )
{
return m.Vec.As<byte, short>();
return m.Vec.As<float, short>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<uint>( M128 m )
{
return m.Vec.As<byte, uint>();
return m.Vec.As<float, uint>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<ulong>( M128 m )
{
return m.Vec.As<byte, ulong>();
return m.Vec.As<float, ulong>();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<ushort>( M128 m )
{
return m.Vec.As<byte, ushort>();
return m.Vec.As<float, ushort>();
}
}
@@ -39,8 +39,9 @@ using System.Runtime.InteropServices;
namespace StgSharp.Internal.Intrinsic
{
[StructLayout( LayoutKind.Explicit, Size = 12 * sizeof( float ), Pack = 16 )]
internal struct ColumnSet3 : IEquatable<ColumnSet3>, IMat
internal struct ColumnSet3 : IEquatable<ColumnSet3>
{
[FieldOffset( 0 * sizeof( float ) )] internal float m00;
[FieldOffset( 4 * sizeof( float ) )] internal float m01;
[FieldOffset( 8 * sizeof( float ) )] internal float m02;
@@ -39,7 +39,7 @@ using System.Runtime.InteropServices;
namespace StgSharp.Internal.Intrinsic
{
[StructLayout( LayoutKind.Explicit, Size = 16 * sizeof( float ) )]
internal struct ColumnSet4 : IEquatable<ColumnSet4>, IMat
internal struct ColumnSet4 : IEquatable<ColumnSet4>
{
[FieldOffset( 0 )] internal Vector4 colum0;
+22 -20
View File
@@ -111,12 +111,13 @@ namespace StgSharp.Graphics
/// </param>
/// <exception cref="ArgumentException"></exception>
public unsafe void GainAllUniforms(
ShaderProgram source,
params string[] uniformName )
ShaderProgram source,
params string[] uniformName )
{
if( uniformName.Length != 1 ) {
if( uniformName is null || uniformName.Length != 1 ) {
throw new ArgumentException(
"Camera needs only one uniform.", nameof( uniformName ) );
"Camera needs exactly one uniform.",
nameof( uniformName ) );
}
convertedUniform = source.GetUniform<Matrix44>( uniformName[ 0 ] );
}
@@ -143,13 +144,14 @@ namespace StgSharp.Graphics
{
//Console.WriteLine(Projection * ViewBase);
OpenGL.OpenGLFunction.CurrentGL
.SetUniformValue( convertedUniform, Projection * View );
.SetUniformValue( convertedUniform, Projection * View );
}
public void SetViewDirection( Vec3 position, Vec3 target, Vec3 up )
{
Vec3 direction = position - target;
if( ( position.vec == cameraAtt.colum3.vec ) && ( this.up == up ) && ( cameraAtt.colum2.vec == direction.vec ) ) {
if( ( position.reg == cameraAtt.colum3.reg ) && ( this.up == up ) && ( cameraAtt.colum2.reg ==
direction.reg ) ) {
//no difference with precious value
return;
}
@@ -169,10 +171,10 @@ namespace StgSharp.Graphics
Vec3 right = Linear.Orthogonalize( Linear.Cross( up, direction ) );
cameraAtt.colum0.vec = right.vec;
cameraAtt.colum1.vec = up.vec;
cameraAtt.colum2.vec = direction.vec;
cameraAtt.colum3.vec = position.vec;
cameraAtt.colum0.reg = right. reg;
cameraAtt.colum1.reg = up.reg;
cameraAtt.colum2.reg = direction.reg;
cameraAtt.colum3.reg = position. reg;
InternalPitch();
InternalRow();
@@ -180,10 +182,10 @@ namespace StgSharp.Graphics
}
public void SetViewRange(
Radius fovRadius,
Vec2 size,
Vec2 offset,
(float front, float back) dephRange )
Radius fovRadius,
Vec2 size,
Vec2 offset,
(float front, float back) dephRange )
{
float
distance = _target.GetLength(),
@@ -264,8 +266,8 @@ namespace StgSharp.Graphics
Scaler.Cos( angle ) );
partialCoord *= rotation;
rotationAtt.colum1.vec = partialCoord.colum0.vec;
rotationAtt.colum2.vec = partialCoord.colum1.vec;
rotationAtt.colum1.reg = partialCoord.colum0.reg;
rotationAtt.colum2.reg = partialCoord.colum1.reg;
rotationAtt.isTransposed = false;
}
@@ -282,8 +284,8 @@ namespace StgSharp.Graphics
Scaler.Cos( angle ) );
partialCoord *= rotation;
rotationAtt.colum0.vec = partialCoord.colum0.vec;
rotationAtt.colum1.vec = partialCoord.colum1.vec;
rotationAtt.colum0.reg = partialCoord.colum0.reg;
rotationAtt.colum1.reg = partialCoord.colum1.reg;
rotationAtt.isTransposed = false;
}
@@ -299,8 +301,8 @@ namespace StgSharp.Graphics
Scaler.Cos( angle ) );
partialCoord *= rotation;
rotationAtt.colum0.vec = partialCoord.colum0.vec;
rotationAtt.colum2.vec = partialCoord.colum1.vec;
rotationAtt.colum0.reg = partialCoord.colum0.reg;
rotationAtt.colum2.reg = partialCoord.colum1.reg;
rotationAtt.isTransposed = false;
}
+40
View File
@@ -0,0 +1,40 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="IMatrix.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.Graphics;
using System;
using System.Collections.Generic;
using System.Text;
namespace StgSharp.Math
{
public interface IMatrix<TSelf> where TSelf: IMatrix<TSelf> { }
}
+21 -5
View File
@@ -37,14 +37,30 @@ using System.Threading.Tasks;
namespace StgSharp.Math
{
public interface IVector
public interface IVector<TSelf> where TSelf: struct, IVector<TSelf>
{
/*
public static TItem Create<TItem>(Vector4 source) where TItem : IVector
public static abstract TSelf Zero
{
return TItem
get;
}
public static abstract TSelf One
{
get;
}
public Vec2 XY
{
get;
set;
}
public Vec3 XYZ
{
get;
set;
}
/**/
}
}
+1 -2
View File
@@ -40,7 +40,7 @@ namespace StgSharp.Math
LayoutKind.Explicit,
Size = ( 2 * 2 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix22 : IMat
public struct Matrix22 : IMatrix<Matrix22>
{
[FieldOffset( 2 * 2 * 4 * sizeof( float ) )]
@@ -101,7 +101,6 @@ namespace StgSharp.Math
float cache = _transpose.m10;
_transpose.m10 = _transpose.m01;
_transpose.m01 = cache;
isTransposed = true;
}
}
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit,
Size = ( ( 3 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix23 : IMat
public struct Matrix23 : IMatrix<Matrix23>
{
[FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed = false;
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit,
Size = ( ( 4 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix24 : IMat
public struct Matrix24 : IMatrix<Matrix24>
{
[FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed;
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit,
Size = ( 5 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix32 : IMat
public struct Matrix32 : IMatrix<Matrix32>
{
[FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed;
+4 -4
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit,
Size = ( 6 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix33 : IMat
public struct Matrix33 : IMatrix<Matrix33>
{
[FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed;
@@ -162,9 +162,9 @@ namespace StgSharp.Math
{
left.InternalTranspose();
return new Vec3(
Vector4.Dot( left.transpose.colum0, right.vec ),
Vector4.Dot( left.transpose.colum1, right.vec ),
Vector4.Dot( left.transpose.colum2, right.vec ) );
Vector4.Dot( left.transpose.colum0, right.reg.AsVector4() ),
Vector4.Dot( left.transpose.colum1, right.reg.AsVector4() ),
Vector4.Dot( left.transpose.colum2, right.reg.AsVector4() ) );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
+1 -1
View File
@@ -42,7 +42,7 @@ namespace StgSharp.Math
LayoutKind.Explicit,
Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix34 : IMat
public struct Matrix34 : IMatrix<Matrix34>
{
[FieldOffset( 7 * 4 * sizeof( float ) )] internal bool isTransposed;
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit,
Size = ( ( 16 + 8 ) * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix42 : IMat
public struct Matrix42 : IMatrix<Matrix42>
{
[FieldOffset( ( 16 + 8 ) * sizeof( float ) )] internal bool isTransposed;
+34 -30
View File
@@ -40,10 +40,10 @@ using System.Security.AccessControl;
namespace StgSharp.Math
{
[StructLayout(
layoutKind: LayoutKind.Explicit,
Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix43 : IEquatable<Matrix43>, IMat
layoutKind: LayoutKind.Explicit,
Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public struct Matrix43 : IEquatable<Matrix43>, IMatrix<Matrix43>
{
[FieldOffset( 7 * 4 * sizeof( float ) )]
@@ -54,36 +54,36 @@ namespace StgSharp.Math
[FieldOffset( 3 * 4 * sizeof( float ) )]
internal ColumnSet4 transpose;
public Matrix43()
{
Unsafe.SkipInit(out this);
isTransposed = false;
}
internal Matrix43( Vector4 c0, Vector4 c1, Vector4 c2 )
{
Unsafe.SkipInit(out this);
Unsafe.SkipInit( out this );
isTransposed = false;
mat.colum0 = c0;
mat.colum1 = c1;
mat.colum2 = c2;
}
public Matrix43(
float a00,
float a01,
float a02,
float a10,
float a11,
float a12,
float a20,
float a21,
float a22,
float a30,
float a31,
float a32 )
public Matrix43()
{
Unsafe.SkipInit(out this);
Unsafe.SkipInit( out this );
isTransposed = false;
}
public Matrix43(
float a00,
float a01,
float a02,
float a10,
float a11,
float a12,
float a20,
float a21,
float a22,
float a30,
float a31,
float a32 )
{
Unsafe.SkipInit( out this );
isTransposed = false;
mat.colum0 = new Vector4( a00, a10, a20, a30 );
mat.colum1 = new Vector4( a01, a11, a21, a31 );
@@ -145,10 +145,12 @@ namespace StgSharp.Math
internal unsafe void InternalTranspose()
{
if( !isTransposed ) {
fixed( ColumnSet3* source = &this.mat )
fixed( ColumnSet4* target = &this.transpose ) {
InternalIO.Intrinsic.transpose34( source, target );
fixed( ColumnSet3* source = &this.mat ) {
fixed( ColumnSet4* target = &this.transpose ) {
InternalIO.Intrinsic.transpose34( source, target );
}
}
isTransposed = true;
}
}
@@ -250,10 +252,12 @@ namespace StgSharp.Math
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static unsafe Matrix43 operator +( Matrix43 left, Matrix43 right )
public static unsafe Matrix43 operator +(
Matrix43 left,
Matrix43 right )
{
Matrix43 ret = new Matrix43();
InternalIO.Intrinsic.add_mat_3(&left.mat, &right.mat, &ret.mat);
InternalIO.Intrinsic.add_mat_3( &left.mat, &right.mat, &ret.mat );
return ret;
}
+79 -72
View File
@@ -40,10 +40,10 @@ using System.Runtime.InteropServices;
namespace StgSharp.Math
{
[StructLayout(
LayoutKind.Explicit,
Size = ( 2 * 16 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public unsafe struct Matrix44 : IEquatable<Matrix44>, IMat
LayoutKind.Explicit,
Size = ( 2 * 16 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )]
public unsafe struct Matrix44 : IEquatable<Matrix44>, IMatrix<Matrix44>
{
[FieldOffset( 2 * 64 * sizeof( float ) )] internal bool isTransposed;
@@ -55,26 +55,20 @@ namespace StgSharp.Math
[FieldOffset( 8 * sizeof( float ) )] internal Vec4 colum2;
[FieldOffset( 12 * sizeof( float ) )] internal Vec4 colum3;
public Matrix44()
{
Unsafe.SkipInit(out this);
isTransposed = false;
}
internal Matrix44( ColumnSet4 mat )
{
Unsafe.SkipInit(out this);
Unsafe.SkipInit( out this );
isTransposed = false;
this.mat = mat;
}
internal Matrix44(
Vector4 vec0,
Vector4 vec1,
Vector4 vec2,
Vector4 vec3 )
Vector4 vec0,
Vector4 vec1,
Vector4 vec2,
Vector4 vec3 )
{
Unsafe.SkipInit(out this);
Unsafe.SkipInit( out this );
isTransposed = false;
mat.colum0 = vec0;
mat.colum1 = vec1;
@@ -82,25 +76,31 @@ namespace StgSharp.Math
mat.colum3 = vec3;
}
public unsafe Matrix44(
float a00,
float a01,
float a02,
float a03,
float a10,
float a11,
float a12,
float a13,
float a20,
float a21,
float a22,
float a23,
float a30,
float a31,
float a32,
float a33 )
public Matrix44()
{
Unsafe.SkipInit(out this);
Unsafe.SkipInit( out this );
isTransposed = false;
}
public unsafe Matrix44(
float a00,
float a01,
float a02,
float a03,
float a10,
float a11,
float a12,
float a13,
float a20,
float a21,
float a22,
float a23,
float a30,
float a31,
float a32,
float a33 )
{
Unsafe.SkipInit( out this );
isTransposed = false;
mat.colum0 = new Vector4( a00, a10, a20, a30 );
mat.colum1 = new Vector4( a01, a11, a21, a31 );
@@ -195,6 +195,35 @@ namespace StgSharp.Math
mat.colum2.GetHashCode(), mat.colum3.GetHashCode() );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe Matrix42 Multiple( in Matrix42 right )
{
InternalTranspose();
Matrix42 ans = new Matrix42();
fixed( ColumnSet4* lptr = &transpose ) {
fixed( Vector4* rptr = &right.mat.colum0 ) {
InternalIO.Intrinsic.dot_42( lptr, rptr, &ans.mat.colum0 );
}
}
return ans;
}
public unsafe Matrix43 Multiple( in Matrix43 right )
{
InternalTranspose();
Matrix43 ans = new Matrix43();
fixed( Vector4* rptr = &right.mat.colum0 ) {
fixed( ColumnSet4* lptr = &transpose ) {
InternalIO.Intrinsic.dot_43( lptr, rptr, &ans.mat.colum0 );
}
}
return ans;
}
public override string ToString()
{
InternalTranspose();
@@ -214,8 +243,8 @@ namespace StgSharp.Math
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static unsafe Matrix44 operator -(
Matrix44 left,
Matrix44 right )
Matrix44 left,
Matrix44 right )
{
return new Matrix44(
right.mat.colum0 - left.mat.colum0,
@@ -237,50 +266,26 @@ namespace StgSharp.Math
mat.mat.colum2 * value, mat.mat.colum3 * value );
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe Matrix42 Multiple(in Matrix42 right)
{
InternalTranspose();
Matrix42 ans = new Matrix42();
fixed (ColumnSet4* lptr = &transpose)
fixed (Vector4* rptr = &right.mat.colum0)
{
InternalIO.Intrinsic.dot_42(lptr,rptr, &ans.mat.colum0);
}
return ans;
}
[Obsolete("The operand may cause performance loss, use Matrix.Multiple() method instead.",false)]
[Obsolete(
"The operand may cause performance loss, use Matrix.Multiple() method instead.",
false )]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static unsafe Matrix42 operator *(
Matrix44 left,
Matrix42 right )
Matrix44 left,
Matrix42 right )
{
return left.Multiple(right);
return left.Multiple( right );
}
public unsafe Matrix43 Multiple(in Matrix43 right)
{
InternalTranspose();
Matrix43 ans = new Matrix43();
fixed(Vector4* rptr = &right.mat.colum0)
fixed (ColumnSet4* lptr = &transpose)
{
InternalIO.Intrinsic.dot_43(lptr,rptr,&ans.mat.colum0);
}
return ans;
}
[Obsolete("The operand may cause performance loss, use Matrix.Multiple() method instead.", false)]
[Obsolete(
"The operand may cause performance loss, use Matrix.Multiple() method instead.",
false )]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Matrix43 operator *( Matrix44 left, Matrix43 right )
{
return left.Multiple(in right);
return left.Multiple( in right );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Matrix44 operator *( Matrix44 left, Matrix44 right )
{
@@ -308,10 +313,12 @@ namespace StgSharp.Math
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right )
public static unsafe Matrix44 operator +(
Matrix44 left,
Matrix44 right )
{
Matrix44 ret = new Matrix44();
InternalIO.Intrinsic.add_mat_4(&left.mat, &right.mat, &ret.mat);
InternalIO.Intrinsic.add_mat_4( &left.mat, &right.mat, &ret.mat );
return ret;
}
+37 -6
View File
@@ -28,6 +28,9 @@
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using StgSharp.HighPerformance;
using System.Net.Http.Headers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -35,20 +38,20 @@ using System.Runtime.InteropServices;
namespace StgSharp.Math
{
/// <summary>
/// A two dimension vector defined by two elements. Vec2Ds in StgSharp are default used as colum
/// A two dimension vector defined by two elements. Vec2 in StgSharp are default used as colum
/// vector.
/// </summary>
[StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )]
public struct Vec2 : IVector
public struct Vec2 : IVector<Vec2>
{
[FieldOffset( 0 )] internal unsafe fixed float num[ 2 ];
[FieldOffset( 0 )]
internal Vector2 v;
internal M128 reg;
[FieldOffset( 0 )]
internal Vector4 vec;
internal Vector2 v;
[FieldOffset( 0 )]
public float X;
@@ -57,12 +60,19 @@ namespace StgSharp.Math
internal Vec2( Vector2 vec )
{
Unsafe.SkipInit( out reg );
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
v = vec;
}
internal Vec2( Vector4 vec )
internal Vec2( M128 vec )
{
this.vec = vec;
Unsafe.SkipInit( out reg );
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
reg = vec;
reg.Write<ulong>( 1, 0 );
}
public Vec2( float x, float y )
@@ -74,6 +84,27 @@ namespace StgSharp.Math
public static Vec2 Zero => new Vec2( 0, 0 );
public static Vec2 One
{
get => new Vec2( 1, 1 );
}
public Vec2 XY
{
get => this;
set => this = value;
}
public Vec3 XYZ
{
get => new Vec3( reg );
set
{
reg = value.reg;
reg.Write<ulong>( 1, 0 );
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public float Cross( Vec2 right )
{
+26 -21
View File
@@ -38,26 +38,26 @@ using System.Runtime.InteropServices;
namespace StgSharp.Math
{
[StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )]
public struct Vec3 : IEquatable<Vec3>, IVector
public struct Vec3 : IEquatable<Vec3>, IVector<Vec3>
{
[FieldOffset( 0 )] internal unsafe fixed float num[ 3 ];
[FieldOffset( 0 )]
internal M128 reg;
[FieldOffset( 0 )] internal M128 reg;
[FieldOffset( 0 )]
internal Vector3 v;
[FieldOffset( 0 )]
internal Vector4 vec;
[FieldOffset( 0 )] internal Vector3 v;
[FieldOffset( 0 )] public float X;
[FieldOffset( 4 )] public float Y;
[FieldOffset( 8 )] public float Z;
internal Vec3( Vector4 vector )
internal Vec3( M128 vector )
{
vec = vector;
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
Unsafe.SkipInit( out Z );
Unsafe.SkipInit( out v );
reg = vector;
reg.Write<uint>( 3, 0 );
}
internal Vec3( Vector3 vector )
@@ -67,21 +67,26 @@ namespace StgSharp.Math
public Vec3( Vec2 xy, float z )
{
vec = xy.vec;
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
Unsafe.SkipInit( out Z );
Unsafe.SkipInit( out v );
reg = xy.reg;
Z = z;
}
public Vec3( float x, float y, float z )
{
#if NET5_0_OR_GREATER
Unsafe.SkipInit( out vec );
#endif
Unsafe.SkipInit( out reg );
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
Unsafe.SkipInit( out Z );
v = new Vector3( x, y, z );
}
public unsafe Vec2 XY
{
get => new Vec2( this.vec );
get => new Vec2( this.reg );
set
{
fixed( Vector3* vptr = &v ) {
@@ -93,6 +98,7 @@ namespace StgSharp.Math
public Vec3 XYZ
{
get { return new Vec3( v ); }
set { this = value; }
}
public static Vec3 Zero
@@ -122,7 +128,7 @@ namespace StgSharp.Math
public bool Equals( Vec3 other )
{
return this.vec == other.vec;
return this.reg == other.reg;
}
public override bool Equals( object obj )
@@ -168,7 +174,7 @@ namespace StgSharp.Math
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Vec3 operator -( Vec3 vec )
{
return new Vec3( -vec.vec );
return new Vec3( -vec.v );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
@@ -204,7 +210,7 @@ namespace StgSharp.Math
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Vec3 operator +( Vec3 left, Vec3 right )
{
return new Vec3( left.vec + right.vec );
return new Vec3( left.v + right.v );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
@@ -217,9 +223,8 @@ namespace StgSharp.Math
public static unsafe implicit operator Vec3(
(float, float, float) tuple )
{
Vec3 v = *( Vec3* )&tuple;
v.vec.W = 0.0f;
return v;
Vec3 vec = new Vec3( *( Vector3* )&tuple );
return vec;
}
}
+29 -8
View File
@@ -41,7 +41,7 @@ using System.Runtime.InteropServices;
namespace StgSharp.Math
{
[StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )]
public struct Vec4 : IEquatable<Vec4>, IVector
public struct Vec4 : IEquatable<Vec4>, IVector<Vec4>
{
[FieldOffset( 0 )] internal unsafe fixed float num[ 4 ];
@@ -57,12 +57,33 @@ namespace StgSharp.Math
internal Vec4( Vector4 v )
{
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
Unsafe.SkipInit( out Z );
Unsafe.SkipInit( out W );
Unsafe.SkipInit( out reg );
vec = v;
}
public Vec4( Vec3 v, float w )
internal Vec4( M128 v )
{
vec = v.vec;
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
Unsafe.SkipInit( out Z );
Unsafe.SkipInit( out W );
Unsafe.SkipInit( out vec );
reg = v;
}
public Vec4( Vec3 v3, float w )
{
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
Unsafe.SkipInit( out Z );
Unsafe.SkipInit( out W );
reg = v3.reg;
W = w;
}
@@ -73,7 +94,7 @@ namespace StgSharp.Math
public unsafe Vec2 XY
{
get => new Vec2( vec );
get => new Vec2( reg );
set
{
X = value.X;
@@ -83,23 +104,23 @@ namespace StgSharp.Math
public unsafe Vec3 XYZ
{
get => new Vec3( vec );
get => new Vec3( reg );
set
{
float w = W;
vec = value.vec;
reg = value.reg;
W = w;
}
}
public static Vec4 One
{
get => new Vec4( Vector4.One );
get => new Vec4( 1, 1, 1, 1 );
}
public static Vec4 Zero
{
get => new Vec4( Vector4.Zero );
get => new Vec4( 0, 0, 0, 0 );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
@@ -51,7 +51,7 @@ namespace StgSharp.Math
public static Vec3 Normalize( Vec3 vec )
{
return new Vec3 { vec = Vector4.Normalize( vec.vec ) };
return new Vec3 { v = Vector3.Normalize( vec.v ) };
}
public static unsafe void Normalize( ref Vec4 source, ref Vec4 target )
@@ -55,8 +55,8 @@ namespace StgSharp.Math
}
public static unsafe void Orthogonalize(
ref Vec4 source,
ref Vec4 target )
ref Vec4 source,
ref Vec4 target )
{
Vector4 s = source.vec;
Vector4 t = target.vec;
@@ -79,8 +79,8 @@ namespace StgSharp.Math
/// <param _name="source"></param>
/// <param _name="target"></param>
public static unsafe void Orthogonalize(
ref Vec3 source,
ref Vec3 target )
ref Vec3 source,
ref Vec3 target )
{
Vector3 s = source.v;
Vector3 t = target.v;
+5 -5
View File
@@ -60,7 +60,7 @@ namespace StgSharp.Math
throw new ArgumentException();
}
float r, s, u, v = 0.0f;
float r, s, u, vec = 0.0f;
bool transform = (y >= 0.5f);
if (transform)
@@ -93,16 +93,16 @@ namespace StgSharp.Math
c = (r - s1 * s1) / (s + s1);
p = 2.0F * s * u - (piby2_tail - 2.0F * c);
q = hpiby2_head - 2.0F * s1;
v = hpiby2_head - (p - q);
vec = hpiby2_head - (p - q);
}
else
{
v = y + y * u;
vec = y + y * u;
}
v = sign * v;
vec = sign * vec;
return piby2 - v;
return piby2 - vec;
*/
}
+4 -4
View File
@@ -68,7 +68,7 @@ namespace StgSharp.Math
throw new ArgumentException();
}
float r, s, u, v = 0.0f;
float r, s, u, vec = 0.0f;
bool transform = (y >= 0.5f);
if (transform)
@@ -101,14 +101,14 @@ namespace StgSharp.Math
c = (r - s1 * s1) / (s + s1);
p = 2.0F * s * u - (piby2_tail - 2.0F * c);
q = hpiby2_head - 2.0F * s1;
v = hpiby2_head - (p - q);
vec = hpiby2_head - (p - q);
}
else
{
v = y + y * u;
vec = y + y * u;
}/*
return sign * v;
return sign * vec;
*/
}
+10 -10
View File
@@ -63,11 +63,11 @@ namespace StgSharp.Math
angle = 0.7853981634f;
}
float v = 0.7853981634f * x + x * (1 - x) * (0.2447f + 0.0663f * x);
v += angle;
v *= sign;
float vec = 0.7853981634f * x + x * (1 - x) * (0.2447f + 0.0663f * x);
vec += angle;
vec *= sign;
return v;
return vec;
}
@@ -105,13 +105,13 @@ namespace StgSharp.Math
angle2 = 0.7853981634f;
}
float v = 0.7853981634f * z + z * (1 - z) * (0.2447f + 0.0663f * z);
v *= 57.29577951f;
v += angle2;
v += angle;
v *= sign;
float vec = 0.7853981634f * z + z * (1 - z) * (0.2447f + 0.0663f * z);
vec *= 57.29577951f;
vec += angle2;
vec += angle;
vec *= sign;
return v;
return vec;
*/
}
@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="PipeLine.NodeCraeater.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.PipeLine
{
public partial class BlueprintScheduler
{
public PipeLineNode CreateBlueprintNode(
string name,
BlueprintNodeOperation operation,
string[] inputPort,
string[] outputPort,
bool isNative )
{
PipeLineNode node = new PipeLineNode(
operation, name, isNative, inputPort, outputPort );
if( isNative ) {
mainThreadNodeList.Add( node );
} else {
globalNodeList.Add( node );
}
return node;
}
}
}
+177
View File
@@ -0,0 +1,177 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="Blueprint.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.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
namespace StgSharp.PipeLine
{
/// <summary>
/// A sets of complex logic designed for running in multi threads environment. Warning: do not
/// run a <see cref="BlueprintScheduler" /> instance in multi threads more than once.
/// </summary>
public partial class BlueprintScheduler : IConvertableToBlueprintNode
{
private List<PipeLineNode>[] _concurrentNodes, _mainThreadNodes;
private BeginningNode beginNode;
private Dictionary<string, PipeLineNode> allNode;
private EndingNode endNode;
private Func<bool> terminate;
private List<PipeLineNode> globalNodeList;
private List<PipeLineNode> mainThreadNodeList;
private SemaphoreSlim runningStat;
internal int currentGlobalNodeIndex;
internal int currentNativeNodeIndex;
public BlueprintScheduler()
{
allNode = new Dictionary<string, PipeLineNode>();
globalNodeList = new List<PipeLineNode>();
mainThreadNodeList = new List<PipeLineNode>();
runningStat = new SemaphoreSlim( 1, 1 );
beginNode = new BeginningNode( this );
endNode = new EndingNode( this );
}
public BlueprintNodeOperation Operation
{
get => ExecuteMain;
}
public bool IsRunning
{
get => runningStat.CurrentCount == 0;
}
public IEnumerable<string> InputInterfacesName
{
get { return beginNode.OutputInterfaces.Keys; }
}
public IEnumerable<string> OutputInterfacesName
{
get { return beginNode.OutputInterfaces.Keys; }
}
public PipeLineNode BeginLayer => beginNode;
public PipeLineNode EndLayer => endNode;
/**/
internal SemaphoreSlim RunningStat
{
get => runningStat;
}
/**/
public void AddNode( PipeLineNode node, bool isNative )
{
_ = node ?? throw new ArgumentNullException( nameof( node ) );
node.IsNative = isNative;
allNode.Add( node.Name, node );
}
public void ExecuteMain(
in Dictionary<string, PipelineConnector> input,
in Dictionary<string, PipelineConnector> output )
{
PipeLineRunner.Run( this );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public (string name, PipeLineConnectorArgs arg)[] GetOutput()
{
return endNode.OutputData;
}
public void Init()
{
foreach( KeyValuePair<string, PipeLineNode> item in allNode ) {
if( item.Value.IsNative ) {
mainThreadNodeList.Add( item.Value );
} else {
globalNodeList.Add( item.Value );
}
}
mainThreadNodeList.Sort();
globalNodeList.Sort();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void SetInput(
params (string name, PipeLineConnectorArgs arg)[] parameters )
{
beginNode.InputData = parameters;
}
public void Terminate()
{
Interlocked.Exchange( ref currentGlobalNodeIndex, int.MaxValue );
Interlocked.Exchange( ref currentNativeNodeIndex, int.MaxValue );
}
internal bool RequestNexGlobalNode( out PipeLineNode node )
{
if( currentGlobalNodeIndex < globalNodeList.Count ) {
node = globalNodeList[ currentGlobalNodeIndex ];
Interlocked.Increment( ref currentGlobalNodeIndex );
return true;
}
node = default!;
return false;
}
internal bool RequestNextNativeNode( out PipeLineNode node )
{
if( currentNativeNodeIndex < mainThreadNodeList.Count ) {
node = mainThreadNodeList[ currentNativeNodeIndex ];
Interlocked.Increment( ref currentNativeNodeIndex );
return true;
}
node = default!;
return false;
}
~BlueprintScheduler()
{
runningStat.Dispose();
}
}
}
+168
View File
@@ -0,0 +1,168 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="Connector.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.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security.Authentication.ExtendedProtection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.PipeLine
{
public class PipelineConnector
{
private protected PipeLineNode after;
private protected PipeLineNode former;
private protected PipeLineConnectorArgs args;
private protected SemaphoreSlim formerCompleteSemaphore;
public PipelineConnector( PipeLineNode former, PipeLineNode after )
{
this.former = former;
this.after = after;
formerCompleteSemaphore = new SemaphoreSlim(
initialCount: 0, maxCount: 1 );
}
public PipeLineNode After => after;
public PipeLineNode Former => former;
public PipeLineConnectorArgs Args
{
get => args;
set => args = value;
}
public int Level => former.Level;
public static void SkipAll(
Dictionary<string, PipelineConnector> ports )
{
if( ports == null ) {
return;
}
foreach( KeyValuePair<string, PipelineConnector> item in ports ) {
if( item.Value != null ) {
item.Value.CompleteAndSkip();
}
}
}
public static void WaitAll(
Dictionary<string, PipelineConnector> ports )
{
if( ports == null ) {
return;
}
foreach( KeyValuePair<string, PipelineConnector> item in ports ) {
if( item.Value != null ) {
item.Value.WaitForStart();
}
}
}
public virtual void WaitForStart()
{
//Console.WriteLine($"Waiting \t{former.ContextName}\t->\t{after.ContextName}");
formerCompleteSemaphore.Wait();
}
~PipelineConnector()
{
formerCompleteSemaphore.Dispose();
}
#region pipline op
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void CompleteAndSkip()
{
//Console.WriteLine($"Complete\t{former.Name}\t->\t{after.Name}");
formerCompleteSemaphore.Release();
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void CompleteAndWriteData( PipeLineConnectorArgs args )
{
this.args = args;
CompleteAndSkip();
}
#endregion
}
public abstract class PipeLineConnectorArgs
{
public object? Value
{
get;
set;
}
public object? ValueDefault
{
get;
}
}
public sealed class SealedBlueprintPiipeline : PipelineConnector
{
internal SealedBlueprintPiipeline(
PipeLineNode former,
PipeLineNode after )
: base( former, after ) { }
public static SealedBlueprintPiipeline SealInput(
PipeLineNode node,
string portName )
{
return new SealedBlueprintPiipeline( PipeLineNode.Empty, node );
}
public static SealedBlueprintPiipeline SealOutput(
PipeLineNode node,
string portName )
{
return new SealedBlueprintPiipeline( node, PipeLineNode.Empty );
}
public override sealed void WaitForStart() { }
}
}
@@ -0,0 +1,91 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="CrossFramePipelineNode.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.PipeLine;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.PipeLine
{
public class CrossFrameOperation : IConvertableToBlueprintNode
{
private static string[] _inputName = ["TaskIn"];
private static string[] _outputName = ["TaskOut"];
private Action _mainExecution;
private int currentCount;
private readonly int cycleCount;
public CrossFrameOperation( Action startup, int cycleCount )
{
MainExecution = startup;
this.cycleCount = ( cycleCount > 1 ) ?
cycleCount : throw new ArgumentException(
$"{$"The {typeof(CrossFrameOperation).Name} crosses only one cycle, "}{$"please use a {typeof(PipeLineNode).Name} instead."}" );
this.cycleCount = cycleCount;
currentCount = cycleCount;
}
public Action MainExecution
{
get => _mainExecution;
private protected set => _mainExecution = value;
}
public BlueprintNodeOperation Operation
{
get => ExecuteMain;
}
public IEnumerable<string> InputInterfacesName => _inputName;
public IEnumerable<string> OutputInterfacesName => _outputName;
public void ExecuteMain(
in Dictionary<string, PipelineConnector> input,
in Dictionary<string, PipelineConnector> output )
{
if( currentCount < cycleCount ) {
Interlocked.Increment( ref currentCount );
} else {
Interlocked.Exchange( ref currentCount, 0 );
Task.Run( MainExecution );
}
//Console.WriteLine(currentCount);
PipelineConnector.SkipAll( output );
}
}
}
@@ -0,0 +1,86 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="IConvertableToBlueprintNode.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.Runtime.CompilerServices;
using System.Text;
namespace StgSharp.PipeLine
{
public delegate void BlueprintNodeOperation(
in Dictionary<string, PipelineConnector> input,
in Dictionary<string, PipelineConnector> output );
public interface IConvertableToBlueprintNode
{
BlueprintNodeOperation Operation
{
get;
}
public IEnumerable<string> InputInterfacesName
{
get;
}
public IEnumerable<string> OutputInterfacesName
{
get;
}
}
internal class DefaultConvertableToBlueprintNode : IConvertableToBlueprintNode
{
private string[] _input;
private string[] _output;
private BlueprintNodeOperation _execution;
public DefaultConvertableToBlueprintNode(
BlueprintNodeOperation execution,
string[] input,
string[] output )
{
_input = input;
_output = output;
_execution = execution;
}
public BlueprintNodeOperation Operation => _execution;
public IEnumerable<string> InputInterfacesName => _input;
public IEnumerable<string> OutputInterfacesName => _output;
}
}
+300
View File
@@ -0,0 +1,300 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="PipeLineNode.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.Entities;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.PipeLine
{
/// <summary>
///
/// </summary>
/// <risk>
/// Reset pipeline has risk, this operation is a direct operation to port in current node, the
/// port on the other node cannot get the change.
/// </risk>
#pragma warning disable CA1036
public class PipeLineNode : IComparable<PipeLineNode>
#pragma warning restore CA1036
{
private static Dictionary<string, PipelineConnector> _emptyLayer = new();
private static PipeLineNode _emptyNode = new PipeLineNode(
string.Empty, null!, false );
private IConvertableToBlueprintNode _mainOperation;
private string _name;
private protected bool _levelAvailable, _nativeRequested;
private protected Dictionary<string, PipelineConnector> _inputInterfaces;
private protected Dictionary<string, PipelineConnector> _outputInterfaces;
private protected int _level;
internal PipeLineNode(
string name,
IConvertableToBlueprintNode node,
bool isNative )
{
_levelAvailable = false;
_name = name;
_nativeRequested = isNative;
_mainOperation = node;
_inputInterfaces = new Dictionary<string, PipelineConnector>();
_outputInterfaces = new Dictionary<string, PipelineConnector>();
foreach( string portName in node.InputInterfacesName ) {
_inputInterfaces.Add( portName, null! );
}
foreach( string portName in node.OutputInterfacesName ) {
_outputInterfaces.Add( portName, null! );
}
}
#pragma warning disable CS8618
internal PipeLineNode(
BlueprintNodeOperation operation,
string name,
bool isNative,
string[] inputPorts,
string[] outputPorts )
#pragma warning restore CS8618
{
if( ( inputPorts == null ) || ( inputPorts.Length == 0 ) ) {
throw new ArgumentNullException( nameof( inputPorts ) );
}
if( ( outputPorts == null ) || ( outputPorts.Length == 0 ) ) {
throw new ArgumentNullException( nameof( outputPorts ) );
}
_levelAvailable = false;
_name = name;
_nativeRequested = isNative;
operation = operation ?? DefaultOperation;
_mainOperation = new DefaultConvertableToBlueprintNode(
operation, inputPorts, outputPorts );
_inputInterfaces = new Dictionary<string, PipelineConnector>();
_outputInterfaces = new Dictionary<string, PipelineConnector>();
foreach( string portName in inputPorts ) {
_inputInterfaces.Add(
portName,
SealedBlueprintPiipeline.SealOutput( this, name ) );
}
foreach( string portName in outputPorts ) {
_outputInterfaces.Add( portName, null! );
}
}
public bool IsNative
{
get => _nativeRequested;
internal set => _nativeRequested = value;
}
public static Dictionary<string, PipelineConnector> EmptyPortLayer
{
get => _emptyLayer;
}
public int Level
{
get
{
if( _levelAvailable ) {
return _level;
}
_level = 0;
foreach( KeyValuePair<string, PipelineConnector> item in _inputInterfaces ) {
if( item.Value == null ) {
continue;
}
if( _level < item.Value.Level ) {
_level = item.Value.Level;
}
}
_level += 1;
_levelAvailable = true;
return _level;
}
}
public static PipeLineNode Empty
{
get => _emptyNode;
}
public string Name => _name;
internal Dictionary<string, PipelineConnector> InputInterfaces => _inputInterfaces;
internal Dictionary<string, PipelineConnector> OutputInterfaces => _outputInterfaces;
internal IConvertableToBlueprintNode Value
{
get => _mainOperation;
}
public void Append(
[NotNull] PipeLineNode next,
string thisOutputPortName,
string afterInputPortName )
{
this._levelAvailable = false;
PipelineConnector pipeline = new PipelineConnector( this, next );
if( next is EndingNode enode ) {
enode.SetCertainInputPort( afterInputPortName, pipeline );
} else {
next.SetCertainInputPort( afterInputPortName, pipeline );
}
SetCertainOutputPort( thisOutputPortName, pipeline );
}
public int CompareTo( PipeLineNode other )
{
if( null == other ) {
throw new ArgumentNullException( nameof( other ) );
}
return this.Level.CompareTo( other.Level );
}
public void Prepend(
[NotNull] PipeLineNode former,
string formerOutputPortName,
string thisInputPortName )
{
this._levelAvailable = false;
PipelineConnector pipeline = new PipelineConnector( former, this );
if( former is BeginningNode bnode ) {
bnode.SetCertainOutputPort( formerOutputPortName, pipeline );
} else {
former.SetCertainOutputPort( formerOutputPortName, pipeline );
}
SetCertainInputPort( thisInputPortName, pipeline );
}
public virtual void Run()
{
try {
//Console.WriteLine(_name);
PipelineConnector.WaitAll( _inputInterfaces );
if( _mainOperation != null ) {
_mainOperation.Operation(
in _inputInterfaces, in _outputInterfaces );
}
}
catch( Exception ) {
throw;
}
}
protected static void DefaultOperation(
in Dictionary<string, PipelineConnector> input,
in Dictionary<string, PipelineConnector> output )
{
PipelineConnector.SkipAll( output );
}
#region port operation
public PipelineConnector GetInputPort( string name )
{
PipelineConnector ret;
if( !_inputInterfaces.TryGetValue( name, out ret ) ) {
throw new ArgumentOutOfRangeException(
$"Cannot find the interface named {name} in node {Name}." );
}
return ret;
}
public PipelineConnector GetOutputPort( string name )
{
PipelineConnector ret;
if( !_outputInterfaces.TryGetValue( name, out ret ) ) {
throw new ArgumentOutOfRangeException(
$"Cannot find the interface named {name} in node {Name}." );
}
return ret;
}
public void SetCertainInputPort(
string name,
PipelineConnector pipeline )
{
if( !_inputInterfaces.ContainsKey( name ) ) {
throw new ArgumentException(
$"Cannot find the interface named {name} in node {Name}." );
}
_inputInterfaces[ name ] = pipeline;
}
public void SetCertainOutputPort(
string name,
PipelineConnector pipeline )
{
if( !_outputInterfaces.ContainsKey( name ) ) {
throw new ArgumentOutOfRangeException(
$"Cannot find the interface named {name} in node {Name}." );
}
_outputInterfaces[ name ] = pipeline;
}
#endregion
}//--------------------------------- end of class -----------------------------------
public class BlueprintNodeRunException : Exception
{
protected BlueprintNodeRunException(
SerializationInfo info,
StreamingContext context )
: base( info, context ) { }
public BlueprintNodeRunException() { }
public BlueprintNodeRunException( Exception ex )
: base( string.Empty, ex ) { }
public BlueprintNodeRunException( string message ) : base( message ) { }
public BlueprintNodeRunException(
string message,
Exception innerException )
: base( message, innerException ) { }
}
}
+228
View File
@@ -0,0 +1,228 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="PipeLineRunner.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.Threading;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.PipeLine
{
public static class PipeLineRunner
{
private static NodeRunner[] allAvailableTask = CreateBlueprintRunnerArray(
);
private static CancellationTokenSource cts = new CancellationTokenSource(
);
private static ConcurrentStack<BlueprintScheduler> blueprintInWaiting
= new ConcurrentStack<BlueprintScheduler>();
private static int _callingThread;
private static SemaphoreSlim bpLock = new SemaphoreSlim( 0, 1 );
/// <summary>
/// <para> Only the following occasions of calling are valid: </para> <para> 1. no bp is
/// running or the only bp is quitting. </para><para> 2. calling from the main thread or a
/// thread the current bp is running on.</para>
/// </summary>
internal static bool IsValidCalling
{
get
{
if( ( NodeRunner.CurrentBlueprint == null ) || //no bp running at all
( ( blueprintInWaiting.IsEmpty ) && ( NodeRunner.CurrentBlueprint.IsRunning ==
false ) ) ) {
// a bp is quitting
//in case no bp is running
return true;
}
int? id = Task.CurrentId;
if( id is null ) {
// in case calling from main thread and current running bp
return _callingThread == Environment.CurrentManagedThreadId;
}
foreach( NodeRunner item in allAvailableTask ) {
if( item.Id == id ) {
//if calling from any bp running task
return true;
}
}
return false;
}
}
public static void Run( BlueprintScheduler blueprint )
{
//Console.WriteLine();
if( blueprint == null ) {
return;
}
if( blueprint.IsRunning ) {
throw new InvalidOperationException(
"Attempt to run a blueprint instance twice." );
}
if( IsValidCalling ) {
//Console.WriteLine("valid and run");
if( InterruptAndRunNewBp( blueprint ) ) {
while( InterruptAndRunNewBp( NodeRunner.CurrentBlueprint ) ) { }
;
}
} else {
bpLock.Wait();
if( InterruptAndRunNewBp( blueprint ) ) {
while( InterruptAndRunNewBp( NodeRunner.CurrentBlueprint ) ) { }
}
bpLock.Release();
}
Interlocked.Exchange( ref _callingThread, -1 );
}
public static void SetMaxTaskCount( int size )
{
if( size < 1 ) {
size = 1;
}
if( allAvailableTask.Length >= size ) {
for( int i = size; i < allAvailableTask.Length; i++ ) {
if( allAvailableTask[ i ] != null ) {
allAvailableTask[ i ].Cancel();
}
}
}
Array.Resize( ref allAvailableTask, size );
}
public static void Terminate()
{
cts.Cancel();
NodeRunner.CurrentBlueprint.Terminate();
foreach( NodeRunner task in allAvailableTask ) {
task.Cts.Cancel();
}
foreach( BlueprintScheduler bp in blueprintInWaiting ) {
bp.Terminate();
}
blueprintInWaiting.Clear();
}
internal static bool InterruptAndRunNewBp( BlueprintScheduler newBp )
{
Debug.Assert( newBp != null );
if( ( newBp != NodeRunner.CurrentBlueprint ) && ( NodeRunner.CurrentBlueprint !=
null ) ) {
//if a running bp exists
blueprintInWaiting.Push( NodeRunner.CurrentBlueprint );
}
//load new bp to current bp
Interlocked.Exchange( ref NodeRunner.CurrentBlueprint!, newBp );
Interlocked.Exchange(
ref _callingThread, Environment.CurrentManagedThreadId );
//run beginning node to init it first.
if( !NodeRunner.CurrentBlueprint.IsRunning ) {
( NodeRunner.CurrentBlueprint.BeginLayer as BeginningNode )!.Run(
);
}
//refresh all tasks
for( int i = 0; i < allAvailableTask.Length; i++ ) {
NodeRunner item = allAvailableTask[ i ];
if( ( item is null ) || item.IsCompleted ) {
allAvailableTask[ i ] = NodeRunner.Run();
}
}
PipeLineNode node;
while( !cts.Token.IsCancellationRequested && NodeRunner.CurrentBlueprint
.RequestNextNativeNode( out node ) ) {
node.Run();
if( !NodeRunner.CurrentBlueprint.IsRunning ) {
break;
}
}
( NodeRunner.CurrentBlueprint.EndLayer as EndingNode )!.Run();
return blueprintInWaiting.TryPeek( out NodeRunner.CurrentBlueprint );
}
private static NodeRunner[] CreateBlueprintRunnerArray()
{
int count = Environment.ProcessorCount;
return new NodeRunner[ count < 2 ? count : count - 2];
}
}
internal class NodeRunner : CancellableTask
{
private static BlueprintScheduler _current;
internal NodeRunner()
: base()
{
_startup = InternalRun;
}
internal static ref BlueprintScheduler CurrentBlueprint
{
get => ref _current;
}
internal static NodeRunner Run()
{
NodeRunner ret = new NodeRunner { _startup = InternalRun };
ret._internalTask = Task.Run( ret.InternalAction );
return ret;
}
private static void InternalRun( CancellationToken token )
{
//Console.WriteLine("Task Begin");
PipeLineNode item;
while( ( CurrentBlueprint != null ) && CurrentBlueprint.IsRunning && !token.IsCancellationRequested && CurrentBlueprint.RequestNexGlobalNode(
out item ) ) {
//Console.WriteLine($"Get node of {item.Name}, going to run.");
item.Run();
}
//Console.WriteLine("Task Completed");
}
}//------------------------------------- End of Class ------------------------------------------
}
+112
View File
@@ -0,0 +1,112 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="RouteSwitch.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.Linq;
using System.Reflection.Emit;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace StgSharp.PipeLine
{
public class RouteSwitch : PipeLineNode
{
private protected Dictionary<string, (PipelineConnector pipeline, Func<bool> openingRule)> outputDictionary;
public RouteSwitch( string name, bool isNative, string inputPorts )
: base(
DefaultOperation, name, isNative, [inputPorts], [string.Empty] )
{
outputDictionary = new Dictionary<string, (PipelineConnector pipeline, Func<bool> openingRule)>(
);
}
public new int Level
{
get
{
if( _levelAvailable ) {
return _level;
}
_level = 0;
KeyValuePair<string, PipelineConnector> item = _inputInterfaces.First(
);
if( item.Value == null ) {
throw new InvalidOperationException();
}
if( _level <= item.Value.Level ) {
_level = item.Value.Level;
}
return _level;
}
}
public new void AddBefore(
PipeLineNode after,
string thisOutputPortName,
string afterInputPortName )
{
this.AppendNode( after, afterInputPortName, () => true );
}
public void AppendNode(
PipeLineNode node,
string portName,
Func<bool> openningRule )
{
if( node == null ) {
throw new ArgumentNullException( nameof( node ) );
}
string indexName = $"{node.Name}.{portName}";
PipelineConnector p = new PipelineConnector( this, node );
node.InputInterfaces[ portName ] = p;
outputDictionary.Add( indexName, (p, openningRule) );
}
public new void Run()
{
try {
PipelineConnector input = InputInterfaces.First().Value;
input.WaitForStart();
foreach( KeyValuePair<string, (PipelineConnector pipeline, Func<bool> openingRule)> item in outputDictionary ) {
if( item.Value.openingRule() ) {
item.Value.pipeline.CompleteAndWriteData( input.Args );
}
}
}
catch( Exception ) {
throw;
}
}
}
}
+125
View File
@@ -0,0 +1,125 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="SideNode.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.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.PipeLine
{
internal sealed class BeginningNode : PipeLineNode
{
private BlueprintScheduler _bp;
public BeginningNode( BlueprintScheduler bp )
: base(
DefaultOperation, name: "BeginningNode", true, ["default"],
["default"] )
{
_bp = bp;
}
internal (string name, PipeLineConnectorArgs arg)[] InputData
{
set
{
if( value == null ) {
return;
}
foreach( (string name, PipeLineConnectorArgs arg) parameter in value ) {
OutputInterfaces[ parameter.name ].Args = parameter.arg;
}
}
}
public override void Run()
{
_bp.RunningStat.Wait();
PipelineConnector.SkipAll( _outputInterfaces );
}
public new void SetCertainOutputPort(
string name,
PipelineConnector pipeline )
{
if( _outputInterfaces.ContainsKey( name ) ) {
_outputInterfaces[ name ] = pipeline;
}
_outputInterfaces.Add( name, pipeline );
}
}
internal sealed class EndingNode : PipeLineNode
{
private BlueprintScheduler _bp;
public EndingNode( BlueprintScheduler bp )
: base(
DefaultOperation, name: "EndingNode", true, ["default"],
["default"] )
{
_bp = bp;
}
internal (string name, PipeLineConnectorArgs arg)[] OutputData
{
get { return InputInterfaces.Select(
key => (key.Key, key.Value.Args) )
.ToArray(); }
}
public override void Run()
{
PipelineConnector.WaitAll( _inputInterfaces );
Interlocked.Exchange( ref _bp.currentGlobalNodeIndex, 0 );
Interlocked.Exchange( ref _bp.currentNativeNodeIndex, 0 );
_bp.RunningStat.Release();
}
public new void SetCertainInputPort(
string name,
PipelineConnector pipeline )
{
if( _inputInterfaces.ContainsKey( name ) ) {
_inputInterfaces[ name ] = pipeline;
}
_inputInterfaces.Add( name, pipeline );
}
}
}
@@ -0,0 +1,81 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="PlainGeometryCollisionSensor.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.Geometries;
using System;
namespace StgSharp
{
public class CollisionEventArgs:EventArgs
{
public CollisionEventArgs(IGeometry target, IGeometry boarder)
{
Target = target;
Boarder = boarder;
}
public IGeometry Target { get; set; }
public IGeometry Boarder { get; set; }
}
public class PlainGeometryCollisionSensor<TBoarder,TTarget>
where TBoarder : IGeometry
where TTarget : IGeometry
{
internal PlainGeometry _boarder;
internal PlainGeometry _target;
internal EventHandler<CollisionEventArgs> _rule;
public event EventHandler<CollisionEventArgs> Rule
{
add { _rule += value; }
remove
{
if (value == null)
{
return;
}
#pragma warning disable CS8601
_rule -= value;
#pragma warning restore CS8601
}
}
public PlainGeometry boarder => _boarder;
public PlainGeometry target
{
get => _target;
set => _target = value;
}
}
}
+72
View File
@@ -0,0 +1,72 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StateMachine.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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp
{
public interface IStateMachine<T> where T: Enum
{
public T LastStableState
{
get;
}
public bool TryEnterState();
public bool TryExitState();
public bool TrySwitchState();
}
public interface IStateMachineWithSwitchSpan<TState, TSpan> : IStateMachine<TState>
where TState: Enum
{
public bool IsInStabelState
{
get;
}
public TState NextStableState
{
get;
}
public bool TrySwitchState();
}
}
+4
View File
@@ -83,6 +83,10 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Logic\" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
</Target>
@@ -50,8 +50,7 @@ namespace StgSharp.Threading
{
if( isNotMainThread.Value ) {
throw new InvalidOperationException(
$"Attempt to call sensitive operation which can be only called from main thread "
+ $"from thread {Environment.CurrentManagedThreadId}." );
$"Attempt to call sensitive operation which can be only called from main thread " + $"from thread {Environment.CurrentManagedThreadId}." );
}
}
+164
View File
@@ -0,0 +1,164 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="TimeFunction.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.Timing
{
public class TimeFunction
{
private float _beginning, _ending;
private Func<float, float> _timeRelatedCalculation;
private TimeSpanProvider _timeProvider;
internal TimeFunction() { }
public TimeFunction(
TimeSpanProvider timeSpanProvider,
Func<float, float> timeRelatedCalculation,
float range )
{
_timeProvider = timeSpanProvider;
_timeRelatedCalculation = timeRelatedCalculation;
if( timeSpanProvider == null ) {
return;
}
_beginning = _timeProvider.CurrentSecond;
_ending = _timeProvider.CurrentSecond + range;
}
public virtual bool IsComplete
{
get => _timeProvider.CurrentSecond > _ending;
}
public Func<float, float> TimeRelatedCalculation
{
get { return _timeRelatedCalculation; }
set { _timeRelatedCalculation = value; }
}
public static TimeFunction One
{
get => new TimeFunctionOne();
}
public TimeSpanProvider TimeSpanProvider
{
get { return _timeProvider; }
set { _timeProvider = value; }
}
public virtual float Calculate()
{
if( _timeProvider.CurrentSecond < _ending ) {
return 0;
}
return _timeRelatedCalculation(
_timeProvider.CurrentSecond - _beginning );
}
public static TimeFunction Proportional(
TimeSpanProvider time,
float begin,
float range )
{
return new TimeFunction( time, ( float t ) => t + begin, range );
}
public virtual TimeFunction Renew(
(Func<float, float> func, float range) funcPair )
{
return new TimeFunction(
_timeProvider, funcPair.func, funcPair.range );
}
public virtual TimeFunction Renew(
Func<float, float> func,
float range )
{
return new TimeFunction( _timeProvider, func, range );
}
public void Reset()
{
float range = _ending - _beginning;
_beginning = _timeProvider.CurrentSecond;
_ending = _beginning + range;
}
public virtual TimeFunction Reverse()
{
float range = _ending - _beginning;
return new TimeFunction(
_timeProvider, p => _timeRelatedCalculation( range - p ),
range );
}
}
public sealed class TimeFunctionOne : TimeFunction
{
internal TimeFunctionOne() : base() { }
public override bool IsComplete
{
get => true;
}
public override float Calculate()
{
return 1;
}
public override TimeFunction Renew(
(Func<float, float> func, float range) funcPair )
{
throw new NotSupportedException();
}
public override TimeFunction Renew(
Func<float, float> func,
float range )
{
throw new NotSupportedException();
}
#pragma warning disable CA1822
public new void Reset()
#pragma warning restore CA1822
{ }
}
}
+152
View File
@@ -0,0 +1,152 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="TimeProvider.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.Timing;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
namespace StgSharp
{
public static partial class StgSharp
{
internal static StgSharpTime mainTimeProvider = new StgSharpTime();
internal static TimeSourceProviderBase MainTimeProvider => mainTimeProvider;
}
public sealed class StgSharpTime : TimeSourceProviderBase
{
private static List<TimeSpanProvider> subscriberList = new List<TimeSpanProvider>(
);
private static long accuracy;
private static Stopwatch mainProvider = new Stopwatch();
private static Thread timeProvideThread;
internal StgSharpTime() { }
public static TimeSourceProviderBase OnlyInstance => StgSharp.MainTimeProvider;
public override sealed void StartProvidingTime()
{
if( mainProvider.IsRunning ) {
return;
}
mainProvider.Start();
//speed test
long totalMS, internalFrequncy = Stopwatch.Frequency;
for( int i = 0; i < 100; i++ ) {
totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) );
for( int t = 0; t < 10; t++ ) {
if( totalMS < 1000 ) {
subscriberList.Add(
new TimeSpanProvider(
100L, TimeSpanProvider.DefaultProvider ) );
}
}
}
mainProvider.Stop();
subscriberList.Clear();
totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) ) / 100L;
accuracy = ( totalMS * 2 ) / 3;
mainProvider.Reset();
timeProvideThread = new Thread( new ThreadStart( ProvideTime ) );
timeProvideThread.Start();
}
public override void StopProvidingTime()
{
lock( mainProvider ) {
mainProvider.Stop();
}
}
public void Terminate()
{
lock( mainProvider ) {
mainProvider.Stop();
}
}
protected override sealed void AddSubscriberUnsynced(
TimeSpanProvider subscriber )
{
subscriberList.Add( subscriber );
}
protected override sealed void RemoveSubscriberUnsynced(
TimeSpanProvider subscriber )
{
subscriberList.Remove( subscriber );
}
private void ProvideTime()
{
long totalMS, internalFrequncy = Stopwatch.Frequency;
lock( mainProvider ) {
mainProvider.Restart();
}
while( mainProvider.IsRunning ) {
totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) );
if( subscriberList.Count == 0 ) {
continue;
}
CheckSubscriberSemaphore.Wait();
List<TimeSpanProvider> toRemoveList = new List<TimeSpanProvider>(
);
foreach( TimeSpanProvider subscriber in subscriberList ) {
if( !subscriber.CheckTime( totalMS ) ) {
toRemoveList.Add( subscriber );
InternalIO.InternalWriteLog(
$"Time subscriber {subscriber} is to be removed.",
LogType.Info );
}
;
}
if( toRemoveList.Count != 0 ) {
foreach( TimeSpanProvider subscriber in toRemoveList ) {
subscriberList.Remove( subscriber );
}
}
CheckSubscriberSemaphore.Release();
}
}
}
}
@@ -0,0 +1,89 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="TimeSourceProvider.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;
using System;
using System.Linq;
using System.Threading;
namespace StgSharp.Timing
{
public abstract class TimeSourceProviderBase
{
private SemaphoreSlim _addSubscriberSemaphore = new SemaphoreSlim(
1, 1 );
protected SemaphoreSlim CheckSubscriberSemaphore
{
get => _addSubscriberSemaphore;
}
public void AddSubscriber( TimeSpanProvider subscriber )
{
try {
_addSubscriberSemaphore.Wait();
AddSubscriberUnsynced( subscriber );
}
catch( Exception ) {
throw;
}
finally {
_addSubscriberSemaphore.Release();
}
}
public void RemoveSubscriber( TimeSpanProvider subscriber )
{
_addSubscriberSemaphore.Wait();
try {
RemoveSubscriberUnsynced( subscriber );
}
catch( Exception ) {
throw;
}
finally {
_addSubscriberSemaphore.Release();
}
}
public abstract void StartProvidingTime();
public abstract void StopProvidingTime();
protected abstract void AddSubscriberUnsynced(
TimeSpanProvider subscriber );
protected abstract void RemoveSubscriberUnsynced(
TimeSpanProvider subscriber );
}
}
@@ -0,0 +1,165 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="TimeSpanAwaitingToken.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.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.Timing
{
#nullable enable
public sealed class TimeSpanAwaitingToken : IDisposable
{
private static readonly ConcurrentStack<int> s_unusedID = new ConcurrentStack<int>(
[0] );
private static int s_maxID;
private static readonly object s_lock = new object();
private EventHandler? _refreshHandler,_missHandler;
private int _size, _id;
private object _participantObject = new object();
private SemaphoreSlim _awaitingSemaphore;
private TimeSpanProvider _provider;
internal TimeSpanAwaitingToken( TimeSpanProvider provider )
{
if( s_unusedID.Count == 1 ) {
lock( s_lock ) {
s_unusedID.TryPop( out int id );
TokenID = id;
s_unusedID.Push( s_maxID++ );
}
} else {
s_unusedID.TryPop( out int id );
TokenID = id;
}
_provider = provider;
_size = 1;
_awaitingSemaphore = new SemaphoreSlim( 0, 1 );
}
internal TimeSpanAwaitingToken( TimeSpanProvider provider, int count )
{
if( s_unusedID.Count == 1 ) {
lock( s_lock ) {
s_unusedID.TryPop( out int id );
TokenID = id;
s_unusedID.Push( s_maxID++ );
}
} else {
s_unusedID.TryPop( out int id );
TokenID = id;
}
_provider = provider;
_size = count;
_awaitingSemaphore = new SemaphoreSlim( 0, _size );
}
public event EventHandler MissTimeSpanRefreshed
{
add { _missHandler += value; }
remove { _missHandler -= value; }
}
public event EventHandler TimeSpanRefreshed
{
add { _refreshHandler += value; }
remove { _refreshHandler -= value; }
}
public int TokenID
{
get => _id;
private set => _id = value;
}
internal SemaphoreSlim AwaitingSemaphoreSlim
{
get => _awaitingSemaphore;
}
public void Dispose()
{
_provider.QuitSpanAwaiting( this );
s_unusedID.Push( TokenID );
_awaitingSemaphore.Dispose();
GC.SuppressFinalize( this );
}
public override int GetHashCode()
{
return _id;
}
public void Participant()
{
lock( _participantObject ) {
_size++;
SemaphoreSlim newSemaphore = new SemaphoreSlim(
_awaitingSemaphore.CurrentCount, _size );
Interlocked.Exchange( ref _awaitingSemaphore, newSemaphore )
.Dispose();
}
}
public void WaitNextSpan()
{
_awaitingSemaphore.Wait();
}
internal void MissRefresh()
{
_missHandler?.Invoke( this, EventArgs.Empty );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
internal void Refresh()
{
_refreshHandler?.Invoke( this, EventArgs.Empty );
}
~TimeSpanAwaitingToken()
{
Dispose();
}
}
#nullable restore
}
+233
View File
@@ -0,0 +1,233 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="TimeSpanProvider.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.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
namespace StgSharp.Timing
{
/// <summary>
/// A microsecond-accuracy timer. It will refresh every a certain time span.
/// </summary>
public class TimeSpanProvider
{
private bool _subscribed;
private ConcurrentQueue<TimeSpanAwaitingToken> _tokenToAdd = new ConcurrentQueue<TimeSpanAwaitingToken>(
);
private ConcurrentQueue<TimeSpanAwaitingToken> _tokenToQuit;
private Counter<int> timeSpanCount = new Counter<int>( -1, 1, 1 );
private HashSet<TimeSpanAwaitingToken> _awaitingTokens;
private long _maxSpanCount;
private long _spanBegin;
private readonly long _spanLength;
private readonly TimeSourceProviderBase _timeSource;
/// <summary>
/// Create a new <see cref="TimeSpanProvider" /> and define the length of time span. Length
/// of a single time span is defined in microseconds.
/// </summary>
/// <param _name="spanMicroSeconds"></param>
/// <param _name="provider"></param>
public TimeSpanProvider(
long spanMicroSeconds,
TimeSourceProviderBase provider )
{
if( provider == null ) {
throw new ArgumentNullException( nameof( provider ) );
}
_timeSource = provider;
_spanLength = spanMicroSeconds;
_maxSpanCount = int.MaxValue;
provider.AddSubscriber( this );
_subscribed = true;
_awaitingTokens = new HashSet<TimeSpanAwaitingToken>();
_tokenToQuit = new ConcurrentQueue<TimeSpanAwaitingToken>();
}
/// <summary>
/// Create a new <see cref="TimeSpanProvider" /> and define the length of time span. Length
/// of a single time span is defined in seconds.
/// </summary>
/// <param _name="spanSeconds"></param>
/// <param _name="provider"></param>
public TimeSpanProvider(
double spanSeconds,
TimeSourceProviderBase provider )
{
if( provider == null ) {
throw new ArgumentNullException( nameof( provider ) );
}
_timeSource = provider;
_spanLength = ( long )( spanSeconds * 1000L * 1000L );
_spanBegin = -_spanLength;
_maxSpanCount = long.MaxValue;
provider.AddSubscriber( this );
_subscribed = true;
_awaitingTokens = new HashSet<TimeSpanAwaitingToken>();
_tokenToQuit = new ConcurrentQueue<TimeSpanAwaitingToken>();
}
/// <summary>
/// Create a new <see cref="TimeSpanProvider" /> and define the length of time span. Length
/// of a single time span is defined in microseconds.
/// </summary>
/// <param _name="spanLength"></param>
/// <param _name="maxSpan"></param>
/// <param _name="provider"></param>
public TimeSpanProvider(
long spanLength,
long maxSpan,
TimeSourceProviderBase provider )
{
if( provider == null ) {
throw new ArgumentNullException( nameof( provider ) );
}
if( maxSpan <= 0 ) {
throw new ArgumentException(
"Sapn count cannot be smaller than zero" );
}
_timeSource = provider;
_spanLength = spanLength;
_spanBegin = -_spanLength;
provider.AddSubscriber( this );
_subscribed = true;
_awaitingTokens = new HashSet<TimeSpanAwaitingToken>();
_tokenToQuit = new ConcurrentQueue<TimeSpanAwaitingToken>();
}
public double SpanLength
{
get => ( _spanLength * 1.0 ) / ( 1000L * 1000L );
}
public float CurrentSecond
{
get => timeSpanCount.Value * SpanLengthLowPrecession;
}
public float SpanLengthLowPrecession
{
get => ( _spanLength * 1.0f ) / ( 1000 * 1000 );
}
public int CurrentSpan
{
get => timeSpanCount.Value;
}
/// <summary>
/// Time source provider provided in <see cref="StgSharp" /> internal framework.
/// </summary>
public static TimeSourceProviderBase DefaultProvider => StgSharpTime.OnlyInstance;
public TimeSpanAwaitingToken ParticipantSpanAwaiting( int count )
{
TimeSpanAwaitingToken token = new TimeSpanAwaitingToken(
this, count );
_tokenToAdd.Enqueue( token );
return token;
}
public void QuitSpanAwaiting( TimeSpanAwaitingToken token )
{
_tokenToQuit.Enqueue( token );
}
public void StopSpanProviding()
{
Interlocked.Exchange( ref _maxSpanCount, 0 );
}
public void SubscribeToTimeSource(
TimeSourceProviderBase serviceHandler )
{
if( serviceHandler == null ) {
throw new ArgumentNullException( nameof( serviceHandler ) );
}
if( _subscribed ) {
return;
}
_subscribed = true;
serviceHandler.AddSubscriber( this );
}
public int ToInt32()
{
return timeSpanCount.Value;
}
internal bool CheckTime( long microseconds )
{
if( microseconds - _spanBegin < _spanLength ) {
return true;
}
while( !_tokenToAdd.IsEmpty ) {
_tokenToAdd.TryDequeue( out TimeSpanAwaitingToken tokenAdd );
_awaitingTokens.Add( tokenAdd );
}
while( !_tokenToQuit.IsEmpty ) {
_tokenToQuit.TryDequeue( out TimeSpanAwaitingToken tokenQuit );
_awaitingTokens.Remove( tokenQuit );
InternalIO.InternalWriteLog(
$"Awaiting token {tokenQuit!.TokenID} has been removed.",
LogType.Info );
}
_spanBegin = microseconds;
timeSpanCount++;
foreach( TimeSpanAwaitingToken item in _awaitingTokens ) {
if( item.AwaitingSemaphoreSlim.CurrentCount == 0 ) {
item.AwaitingSemaphoreSlim.Release();
item.Refresh();
} else {
item.MissRefresh();
}
}
return timeSpanCount < _maxSpanCount;
}
public static explicit operator int(
[NotNull]TimeSpanProvider provider )
{
return provider.ToInt32();
}
}
}
@@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("StgSharp.Common")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6222f8c8be57d511d2ec40523717e20b87fcff9d")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+753cc167bc352df7a47cd17a1ea877666683f5f0")]
[assembly: System.Reflection.AssemblyProductAttribute("StgSharp.Common")]
[assembly: System.Reflection.AssemblyTitleAttribute("StgSharp.Common")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -32,7 +32,7 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace StgSharp.Blueprint
namespace StgSharp.PipeLine
{
[AttributeUsage( AttributeTargets.Method, AllowMultiple = false )]
public class BlueprintNodeExecutionAttribute : Attribute { }
@@ -33,7 +33,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using StgSharp.Blueprint;
using StgSharp.PipeLine;
using System;
using System.Collections.Generic;
@@ -44,76 +44,83 @@ namespace StgSharp.Generator
{
internal class BpNodeSyntaxReceiver : ISyntaxReceiver
{
private static BpNodeSyntaxReceiver receiver = new BpNodeSyntaxReceiver(
);
private static readonly string _indexTypeName = typeof( PartialDictionary<string, object> ).Name;
private static BpNodeSyntaxReceiver receiver = new BpNodeSyntaxReceiver();
public List<MethodDeclarationSyntax> ValidMethod { get; private set; } = new List<MethodDeclarationSyntax>();
public List<MethodDeclarationSyntax> InvalidMethod { get; private set; } = new List<MethodDeclarationSyntax>();
public BpNodeSyntaxReceiver() { }
public BpNodeSyntaxReceiver()
public BpNodeSyntaxReceiver( SyntaxNode node )
{
OnVisitSyntaxNode( node );
}
public BpNodeSyntaxReceiver(SyntaxNode node)
public List<MethodDeclarationSyntax> ValidMethod
{
OnVisitSyntaxNode(node);
}
get;
private set;
} = new List<MethodDeclarationSyntax>();
public void OnVisitSyntaxNode( SyntaxNode syntaxNode )
public List<MethodDeclarationSyntax> InvalidMethod
{
if( syntaxNode is MethodDeclarationSyntax mds && mds.AttributeLists
get;
private set;
} = new List<MethodDeclarationSyntax>();
public static void BuildNode(
SourceProductionContext context,
MethodDeclarationSyntax mds )
{
if( mds.AttributeLists
.SelectMany( list => list.Attributes )
.Any( syntax => syntax.Name.ToString() ==
.Any(
syntax => syntax.Name.ToString() ==
typeof( BlueprintNodeExecutionAttribute ).Name ) ) {
SeparatedSyntaxList<ParameterSyntax> paramList = mds.ParameterList.Parameters;
if( mds.Modifiers.Any( SyntaxKind.StaticKeyword ) && paramList.Count ==
2 && paramList[ 0 ].Type!.ToString() == _indexTypeName && paramList[
1 ].Type!.ToString() ==
_indexTypeName ) {
ValidMethod.Add(mds);
}
else
{
InvalidMethod.Add(mds);
}
}
}
public static void BuildNode(SourceProductionContext context, MethodDeclarationSyntax mds)
{
if (mds.AttributeLists
.SelectMany(list => list.Attributes)
.Any(syntax => syntax.Name.ToString() ==
typeof(BlueprintNodeExecutionAttribute).Name))
{
SeparatedSyntaxList<ParameterSyntax> paramList = mds.ParameterList.Parameters;
if (mds.Modifiers.Any(SyntaxKind.StaticKeyword) && paramList.Count ==
2 && paramList[0].Type!.ToString() == _indexTypeName && paramList[
1].Type!.ToString() ==
_indexTypeName)
{
var methodName = mds.Identifier.Text;
var sourceText = SourceText.From( """
""",encoding:Encoding.UTF8);
context.AddSource("GeneratedBlueprintNode.cs", sourceText);
}
else
{
var diagnostic = Diagnostic.Create(
string methodName = mds.Identifier.Text;
SourceText sourceText = SourceText.From(
string.Empty, encoding: Encoding.UTF8 );
context.AddSource( "GeneratedBlueprintNode.cs",
sourceText );
} else {
Diagnostic diagnostic = Diagnostic.Create(
new DiagnosticDescriptor(
id:"SSE0001",
id: "SSE0001",
title: "Invalid Blueprint Node Method",
messageFormat: "Blueprint Node Method must be static and have two parameters of type PartialDictionary<string, object>",
category: "Blueprint Node",
DiagnosticSeverity.Error,
isEnabledByDefault: true),
mds.GetLocation(),mds.Identifier.Text);
context.ReportDiagnostic(diagnostic);
isEnabledByDefault: true ),
mds.GetLocation(), mds.Identifier.Text );
context.ReportDiagnostic( diagnostic );
}
}
}
public void OnVisitSyntaxNode( SyntaxNode syntaxNode )
{
if( syntaxNode is MethodDeclarationSyntax mds && mds.AttributeLists
.SelectMany( list => list.Attributes )
.Any(
syntax => syntax.Name.ToString() ==
typeof( BlueprintNodeExecutionAttribute ).Name ) ) {
SeparatedSyntaxList<ParameterSyntax> paramList = mds.ParameterList.Parameters;
if( mds.Modifiers.Any( SyntaxKind.StaticKeyword ) && paramList.Count ==
2 && paramList[ 0 ].Type!.ToString() == _indexTypeName && paramList[
1 ].Type!.ToString() ==
_indexTypeName ) {
ValidMethod.Add( mds );
} else {
InvalidMethod.Add( mds );
}
}
}
}
}
@@ -1,6 +1,36 @@
using StgSharp.Blueprint;
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="IStepObject.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.Geometries;
using StgSharp.Math;
using StgSharp.PipeLine;
using System;
using System.Collections.Generic;
@@ -8,14 +38,34 @@ using System.Text;
namespace StgSharp.Modeling.STEP
{
public abstract class IStepObject: StepExpressionBase , IGeometry
public abstract class IStepObject : StepExpressionBase, IGeometry
{
public abstract Point this[int index] { get; set; }
public abstract Vec4[] VertexStream { get; }
public abstract CoordinationBase Coordination { get; }
public abstract int VertexCount { get; }
public abstract ReadOnlySpan<int> VertexIndices { get; }
public abstract Point this[ int index ]
{
get;
set;
}
public abstract Vec4[] VertexStream
{
get;
}
public abstract CoordinationBase Coordination
{
get;
}
public abstract int VertexCount
{
get;
}
public abstract ReadOnlySpan<int> VertexIndices
{
get;
}
}
}
@@ -28,7 +28,7 @@
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using StgSharp.Blueprint;
using StgSharp.PipeLine;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;