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
+68 -34
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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -10,38 +40,63 @@ using System.Xml.Serialization;
namespace StgSharp.Collections namespace StgSharp.Collections
{ {
/// <summary> /// <summary>
/// Part of a collection. This contains a direct reference to origin collection, /// Part of a collection. This contains a direct reference to _origin collection, so all change
/// so all change to origin collection will be reflected in this object. /// to _origin collection will be reflected in this object.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public struct ListSegment<T> : ICollection<T> public struct ListSegment<T> : ICollection<T>
{ {
private List<T> _collection;
private int _begin; private int _begin;
private int _length; 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 ); ArgumentNullException.ThrowIfNull( collection );
ArgumentOutOfRangeException.ThrowIfLessThan( begin, 0 ); ArgumentOutOfRangeException.ThrowIfLessThan( begin, 0 );
ArgumentOutOfRangeException.ThrowIfLessThan( length, 0 ); ArgumentOutOfRangeException.ThrowIfLessThan( length, 0 );
ArgumentOutOfRangeException.ThrowIfLessThan(begin + length, collection.Count); ArgumentOutOfRangeException.ThrowIfLessThan(
begin + length, collection.Count );
_collection = collection; _collection = collection;
_begin = begin; _begin = begin;
_length = length; _length = length;
} }
public int Count => _length; public T this[ int indexValue ]
{
get
{
ArgumentOutOfRangeException.ThrowIfLessThan( indexValue, 0 );
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(
indexValue, _length );
return _collection[ indexValue + _begin ];
}
}
public bool IsReadOnly => true; public bool IsReadOnly => true;
public T this[int indexValue] public int Count => _length;
public bool Contains( T item )
{ {
get { int index = _collection.IndexOf( item );
ArgumentOutOfRangeException.ThrowIfLessThan(indexValue, 0); return index >= _begin && index < _length + index;
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(indexValue, _length); }
return _collection[indexValue + _begin];
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 ];
} }
} }
@@ -55,28 +110,6 @@ namespace StgSharp.Collections
throw new NotSupportedException(); 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(); throw new NotSupportedException();
@@ -86,5 +119,6 @@ namespace StgSharp.Collections
{ {
return GetEnumerator(); 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> /// <summary>
/// A class attempt to reduce cost of boxing, though still a bit slower than direct access to /// 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> /// </summary>
/// <typeparam name="T"> Type of instance to be boxed. </typeparam> /// <typeparam name="T"> Type of instance to be boxed. </typeparam>
public class ValueBox<T> : IValueBox, IValueBox<T> where T: struct 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; } get { return GlobalBuffer.CoordAndRotationList[ BufferId ].XYZ; }
set { GlobalBuffer.CoordAndRotationList[ BufferId ] = new Vec4( set { GlobalBuffer.CoordAndRotationList[ BufferId ] = new Vec4(
value.vec ); } value.reg ); }
} }
public void Move() public void Move()
@@ -47,7 +47,7 @@ namespace StgSharp.Geometries
internal Matrix32 axis; internal Matrix32 axis;
/// <summary> /// <summary>
/// The origin of this coordinate. /// The _origin of this coordinate.
/// </summary> /// </summary>
public Vec3 origin; public Vec3 origin;
@@ -38,30 +38,22 @@ namespace StgSharp.Geometries
{ {
internal readonly float d = -1; internal readonly float d = -1;
internal Vec3 origin; internal Vec3 _origin;
internal Vec3 plainParameter; internal Vec3 plainParameter;
internal Vec3 vec1; internal Vec3 vec1;
internal Vec3 vec2; 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 ) public Plain( Vec3 o, Vec3 v1, Vec3 v2 )
{ {
this.origin = o; this._origin = o;
this.vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //计算平面在xz平面上的方向投影 this.vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //xz
this.vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //计算平面在yz平面上的方向投影 this.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 = _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.X = vec1.X * ( vec1.Z / plainParameter.Z );
plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z ); plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z );
@@ -77,13 +69,13 @@ namespace StgSharp.Geometries
Vec3 v2 = p3.Coord - origin; Vec3 v2 = p3.Coord - origin;
vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //计算平面在xz平面上的方向投影 vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //xz
vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //计算平面在yz平面上的方向投影 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 = 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.X = vec1.X * ( vec1.Z / plainParameter.Z );
plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z ); plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z );
@@ -59,13 +59,13 @@ namespace StgSharp.Geometries
: base( coordination ) : base( coordination )
{ {
vertexMat = new Vec4[6]; vertexMat = new Vec4[6];
vertexMat[ 0 ].vec = vert0.vec; vertexMat[ 0 ].reg = vert0.reg;
vertexMat[ 1 ].vec = vert1.vec; vertexMat[ 1 ].reg = vert1.reg;
vertexMat[ 2 ].vec = vert2.vec; vertexMat[ 2 ].reg = vert2.reg;
vertexMat[ 3 ].vec = vert3.vec; vertexMat[ 3 ].reg = vert3.reg;
vertexMat[ 4 ].vec = vert4.vec; vertexMat[ 4 ].reg = vert4.reg;
vertexMat[ 5 ].vec = vert5.vec; vertexMat[ 5 ].reg = vert5.reg;
vertexMat[ 6 ].vec = vert6.vec; vertexMat[ 6 ].reg = vert6.reg;
} }
public override ReadOnlySpan<int> VertexIndices => Indices; public override ReadOnlySpan<int> VertexIndices => Indices;
@@ -75,7 +75,7 @@ namespace StgSharp.Graphics.OpenGL
int index, int index,
T bufferData, T bufferData,
BufferUsage usage ) BufferUsage usage )
where T: struct, IMat where T: struct, IMatrix<T>
{ {
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
GL.SetBufferData( BufferType.ArrayBuffer, bufferData, usage ); GL.SetBufferData( BufferType.ArrayBuffer, bufferData, usage );
@@ -126,7 +126,7 @@ namespace StgSharp.Graphics.OpenGL
int index, int index,
ReadOnlySpan<T> vectorSpan, ReadOnlySpan<T> vectorSpan,
BufferUsage usage ) BufferUsage usage )
where T: struct, IVector where T: struct, IVector<T>
{ {
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorSpan, usage ); GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorSpan, usage );
@@ -143,7 +143,7 @@ namespace StgSharp.Graphics.OpenGL
int index, int index,
T[] vectorArray, T[] vectorArray,
BufferUsage usage ) BufferUsage usage )
where T: struct, IVector where T: struct, IVector<T>
{ {
GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] );
GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorArray, GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorArray,
@@ -439,7 +439,8 @@ namespace StgSharp.Graphics.OpenGL
{ {
IntPtr sptr = IntPtr.Zero; IntPtr sptr = IntPtr.Zero;
if( InternalIO.glCheckShaderStatus( 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 Marshal.PtrToStringAnsi( sptr );
} }
return string.Empty; return string.Empty;
@@ -485,7 +486,8 @@ namespace StgSharp.Graphics.OpenGL
fixed( byte* ptr = code ) { fixed( byte* ptr = code ) {
int ret = Context.glGetUniformLocation( program.Value, ptr ); int ret = Context.glGetUniformLocation( program.Value, ptr );
#if DEBUG #if DEBUG
if( ( ret == glConst.INVALID_OPERATION ) || ( ret == glConst.INVALID_VALUE ) ) { if( ( ret == glConst.INVALID_OPERATION ) || ( ret ==
glConst.INVALID_VALUE ) ) {
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
if( ret == -1 ) { if( ret == -1 ) {
@@ -512,8 +514,7 @@ namespace StgSharp.Graphics.OpenGL
GlHandle shaderHandle, GlHandle shaderHandle,
ReadOnlySpan<char> codeStream ) ReadOnlySpan<char> codeStream )
{ {
fixed (char* streamPtr = codeStream) fixed( char* streamPtr = codeStream ) {
{
byte* bptr = ( byte* )streamPtr; byte* bptr = ( byte* )streamPtr;
Context.glShaderSource( Context.glShaderSource(
shaderHandle.Value, 1, &bptr, ( void* )0 ); shaderHandle.Value, 1, &bptr, ( void* )0 );
@@ -638,7 +639,7 @@ namespace StgSharp.Graphics.OpenGL
BufferType bufferType, BufferType bufferType,
ReadOnlySpan<T> bufferArray, ReadOnlySpan<T> bufferArray,
BufferUsage usage ) BufferUsage usage )
where T: struct, IVector where T: struct, IVector<T>
{ {
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
if( bufferArray == null ) { if( bufferArray == null ) {
@@ -659,7 +660,7 @@ namespace StgSharp.Graphics.OpenGL
BufferType bufferType, BufferType bufferType,
T[] bufferArray, T[] bufferArray,
BufferUsage usage ) BufferUsage usage )
where T: struct, IVector where T: struct, IVector<T>
{ {
int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) );
if( bufferArray == null ) { if( bufferArray == null ) {
+27 -2
View File
@@ -70,11 +70,36 @@ namespace StgSharp.Graphics
} }
[StructLayout( LayoutKind.Explicit, Size = 32 )] [StructLayout( LayoutKind.Explicit, Size = 32 )]
public unsafe struct Pixel32 public unsafe struct Pixel32RGBA : IPixel
{ {
[FieldOffset( 0 )] private unsafe fixed byte data[ 4 ]; [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 );
}
} }
} }
@@ -66,12 +66,8 @@ namespace StgSharp.Graphics
Image texture, Image texture,
Vec2[] texCoord ) Vec2[] texCoord )
{ {
if( shape == null ) { ArgumentNullException.ThrowIfNull( shape );
throw new ArgumentNullException( nameof( shape ) ); ArgumentNullException.ThrowIfNull( texCoord );
}
if( texCoord == null ) {
throw new ArgumentNullException( nameof( texCoord ) );
}
if( shape.VertexCount > texCoord.Length ) { if( shape.VertexCount > texCoord.Length ) {
throw new ArgumentException( throw new ArgumentException(
+2 -2
View File
@@ -29,7 +29,7 @@
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
using StgSharp.Blueprint; using StgSharp.PipeLine;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -39,7 +39,7 @@ using System.Threading.Tasks;
namespace StgSharp.Graphics namespace StgSharp.Graphics
{ {
public class TexturePipeline : BlueprintPipelineArgs public class TexturePipeline : PipeLineConnectorArgs
{ {
private Image _value; private Image _value;
+18 -14
View File
@@ -34,10 +34,8 @@ using System.Diagnostics.CodeAnalysis;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
#endif
using System.Text; using System.Text;
@@ -48,11 +46,11 @@ namespace StgSharp.HighPerformance
{ {
[FieldOffset( 0 )] internal fixed byte Buffer[ 16 ]; [FieldOffset( 0 )] internal fixed byte Buffer[ 16 ];
[FieldOffset( 0 )] internal Vector128<byte> Vec; [FieldOffset( 0 )] internal Vector128<float> Vec;
internal M128( Vector4 v ) internal M128( Vector4 v )
{ {
Vec = v.AsVector128().AsByte(); Vec = v.AsVector128();
} }
public ref T AsRef<T>() where T: struct, INumber<T> 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 ] ); 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 ) public override bool Equals( [NotNullWhen( true )] object obj )
{ {
if( obj is not M128 other ) { if( obj is not M128 other ) {
@@ -123,61 +127,61 @@ namespace StgSharp.HighPerformance
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<byte>( M128 m ) public static explicit operator Vector128<byte>( M128 m )
{ {
return m.Vec.As<byte, byte>(); return m.Vec.As<float, byte>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<double>( M128 m ) public static explicit operator Vector128<double>( M128 m )
{ {
return m.Vec.As<byte, double>(); return m.Vec.As<float, double>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<float>( M128 m ) public static explicit operator Vector128<float>( M128 m )
{ {
return m.Vec.As<byte, float>(); return m.Vec.As<float, float>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<int>( M128 m ) public static explicit operator Vector128<int>( M128 m )
{ {
return m.Vec.As<byte, int>(); return m.Vec.As<float, int>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<long>( M128 m ) public static explicit operator Vector128<long>( M128 m )
{ {
return m.Vec.As<byte, long>(); return m.Vec.As<float, long>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<sbyte>( M128 m ) public static explicit operator Vector128<sbyte>( M128 m )
{ {
return m.Vec.As<byte, sbyte>(); return m.Vec.As<float, sbyte>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<short>( M128 m ) public static explicit operator Vector128<short>( M128 m )
{ {
return m.Vec.As<byte, short>(); return m.Vec.As<float, short>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<uint>( M128 m ) public static explicit operator Vector128<uint>( M128 m )
{ {
return m.Vec.As<byte, uint>(); return m.Vec.As<float, uint>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<ulong>( M128 m ) public static explicit operator Vector128<ulong>( M128 m )
{ {
return m.Vec.As<byte, ulong>(); return m.Vec.As<float, ulong>();
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static explicit operator Vector128<ushort>( M128 m ) 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 namespace StgSharp.Internal.Intrinsic
{ {
[StructLayout( LayoutKind.Explicit, Size = 12 * sizeof( float ), Pack = 16 )] [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( 0 * sizeof( float ) )] internal float m00;
[FieldOffset( 4 * sizeof( float ) )] internal float m01; [FieldOffset( 4 * sizeof( float ) )] internal float m01;
[FieldOffset( 8 * sizeof( float ) )] internal float m02; [FieldOffset( 8 * sizeof( float ) )] internal float m02;
@@ -39,7 +39,7 @@ using System.Runtime.InteropServices;
namespace StgSharp.Internal.Intrinsic namespace StgSharp.Internal.Intrinsic
{ {
[StructLayout( LayoutKind.Explicit, Size = 16 * sizeof( float ) )] [StructLayout( LayoutKind.Explicit, Size = 16 * sizeof( float ) )]
internal struct ColumnSet4 : IEquatable<ColumnSet4>, IMat internal struct ColumnSet4 : IEquatable<ColumnSet4>
{ {
[FieldOffset( 0 )] internal Vector4 colum0; [FieldOffset( 0 )] internal Vector4 colum0;
+15 -13
View File
@@ -114,9 +114,10 @@ namespace StgSharp.Graphics
ShaderProgram source, ShaderProgram source,
params string[] uniformName ) params string[] uniformName )
{ {
if( uniformName.Length != 1 ) { if( uniformName is null || uniformName.Length != 1 ) {
throw new ArgumentException( throw new ArgumentException(
"Camera needs only one uniform.", nameof( uniformName ) ); "Camera needs exactly one uniform.",
nameof( uniformName ) );
} }
convertedUniform = source.GetUniform<Matrix44>( uniformName[ 0 ] ); convertedUniform = source.GetUniform<Matrix44>( uniformName[ 0 ] );
} }
@@ -149,7 +150,8 @@ namespace StgSharp.Graphics
public void SetViewDirection( Vec3 position, Vec3 target, Vec3 up ) public void SetViewDirection( Vec3 position, Vec3 target, Vec3 up )
{ {
Vec3 direction = position - target; 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 //no difference with precious value
return; return;
} }
@@ -169,10 +171,10 @@ namespace StgSharp.Graphics
Vec3 right = Linear.Orthogonalize( Linear.Cross( up, direction ) ); Vec3 right = Linear.Orthogonalize( Linear.Cross( up, direction ) );
cameraAtt.colum0.vec = right.vec; cameraAtt.colum0.reg = right. reg;
cameraAtt.colum1.vec = up.vec; cameraAtt.colum1.reg = up.reg;
cameraAtt.colum2.vec = direction.vec; cameraAtt.colum2.reg = direction.reg;
cameraAtt.colum3.vec = position.vec; cameraAtt.colum3.reg = position. reg;
InternalPitch(); InternalPitch();
InternalRow(); InternalRow();
@@ -264,8 +266,8 @@ namespace StgSharp.Graphics
Scaler.Cos( angle ) ); Scaler.Cos( angle ) );
partialCoord *= rotation; partialCoord *= rotation;
rotationAtt.colum1.vec = partialCoord.colum0.vec; rotationAtt.colum1.reg = partialCoord.colum0.reg;
rotationAtt.colum2.vec = partialCoord.colum1.vec; rotationAtt.colum2.reg = partialCoord.colum1.reg;
rotationAtt.isTransposed = false; rotationAtt.isTransposed = false;
} }
@@ -282,8 +284,8 @@ namespace StgSharp.Graphics
Scaler.Cos( angle ) ); Scaler.Cos( angle ) );
partialCoord *= rotation; partialCoord *= rotation;
rotationAtt.colum0.vec = partialCoord.colum0.vec; rotationAtt.colum0.reg = partialCoord.colum0.reg;
rotationAtt.colum1.vec = partialCoord.colum1.vec; rotationAtt.colum1.reg = partialCoord.colum1.reg;
rotationAtt.isTransposed = false; rotationAtt.isTransposed = false;
} }
@@ -299,8 +301,8 @@ namespace StgSharp.Graphics
Scaler.Cos( angle ) ); Scaler.Cos( angle ) );
partialCoord *= rotation; partialCoord *= rotation;
rotationAtt.colum0.vec = partialCoord.colum0.vec; rotationAtt.colum0.reg = partialCoord.colum0.reg;
rotationAtt.colum2.vec = partialCoord.colum1.vec; rotationAtt.colum2.reg = partialCoord.colum1.reg;
rotationAtt.isTransposed = false; 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 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, LayoutKind.Explicit,
Size = ( 2 * 2 * 4 * sizeof( float ) ) + sizeof( bool ), Size = ( 2 * 2 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix22 : IMat public struct Matrix22 : IMatrix<Matrix22>
{ {
[FieldOffset( 2 * 2 * 4 * sizeof( float ) )] [FieldOffset( 2 * 2 * 4 * sizeof( float ) )]
@@ -101,7 +101,6 @@ namespace StgSharp.Math
float cache = _transpose.m10; float cache = _transpose.m10;
_transpose.m10 = _transpose.m01; _transpose.m10 = _transpose.m01;
_transpose.m01 = cache; _transpose.m01 = cache;
isTransposed = true; isTransposed = true;
} }
} }
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit, LayoutKind.Explicit,
Size = ( ( 3 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ), Size = ( ( 3 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix23 : IMat public struct Matrix23 : IMatrix<Matrix23>
{ {
[FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed = false; [FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed = false;
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit, LayoutKind.Explicit,
Size = ( ( 4 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ), Size = ( ( 4 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix24 : IMat public struct Matrix24 : IMatrix<Matrix24>
{ {
[FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed; [FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed;
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit, LayoutKind.Explicit,
Size = ( 5 * 4 * sizeof( float ) ) + sizeof( bool ), Size = ( 5 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix32 : IMat public struct Matrix32 : IMatrix<Matrix32>
{ {
[FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed; [FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed;
+4 -4
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit, LayoutKind.Explicit,
Size = ( 6 * 4 * sizeof( float ) ) + sizeof( bool ), Size = ( 6 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix33 : IMat public struct Matrix33 : IMatrix<Matrix33>
{ {
[FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed; [FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed;
@@ -162,9 +162,9 @@ namespace StgSharp.Math
{ {
left.InternalTranspose(); left.InternalTranspose();
return new Vec3( return new Vec3(
Vector4.Dot( left.transpose.colum0, right.vec ), Vector4.Dot( left.transpose.colum0, right.reg.AsVector4() ),
Vector4.Dot( left.transpose.colum1, right.vec ), Vector4.Dot( left.transpose.colum1, right.reg.AsVector4() ),
Vector4.Dot( left.transpose.colum2, right.vec ) ); Vector4.Dot( left.transpose.colum2, right.reg.AsVector4() ) );
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
+1 -1
View File
@@ -42,7 +42,7 @@ namespace StgSharp.Math
LayoutKind.Explicit, LayoutKind.Explicit,
Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ), Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix34 : IMat public struct Matrix34 : IMatrix<Matrix34>
{ {
[FieldOffset( 7 * 4 * sizeof( float ) )] internal bool isTransposed; [FieldOffset( 7 * 4 * sizeof( float ) )] internal bool isTransposed;
+1 -1
View File
@@ -41,7 +41,7 @@ namespace StgSharp.Math
LayoutKind.Explicit, LayoutKind.Explicit,
Size = ( ( 16 + 8 ) * sizeof( float ) ) + sizeof( bool ), Size = ( ( 16 + 8 ) * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix42 : IMat public struct Matrix42 : IMatrix<Matrix42>
{ {
[FieldOffset( ( 16 + 8 ) * sizeof( float ) )] internal bool isTransposed; [FieldOffset( ( 16 + 8 ) * sizeof( float ) )] internal bool isTransposed;
+13 -9
View File
@@ -43,7 +43,7 @@ namespace StgSharp.Math
layoutKind: LayoutKind.Explicit, layoutKind: LayoutKind.Explicit,
Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ), Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public struct Matrix43 : IEquatable<Matrix43>, IMat public struct Matrix43 : IEquatable<Matrix43>, IMatrix<Matrix43>
{ {
[FieldOffset( 7 * 4 * sizeof( float ) )] [FieldOffset( 7 * 4 * sizeof( float ) )]
@@ -54,12 +54,6 @@ namespace StgSharp.Math
[FieldOffset( 3 * 4 * sizeof( float ) )] [FieldOffset( 3 * 4 * sizeof( float ) )]
internal ColumnSet4 transpose; internal ColumnSet4 transpose;
public Matrix43()
{
Unsafe.SkipInit(out this);
isTransposed = false;
}
internal Matrix43( Vector4 c0, Vector4 c1, Vector4 c2 ) internal Matrix43( Vector4 c0, Vector4 c1, Vector4 c2 )
{ {
Unsafe.SkipInit( out this ); Unsafe.SkipInit( out this );
@@ -69,6 +63,12 @@ namespace StgSharp.Math
mat.colum2 = c2; mat.colum2 = c2;
} }
public Matrix43()
{
Unsafe.SkipInit( out this );
isTransposed = false;
}
public Matrix43( public Matrix43(
float a00, float a00,
float a01, float a01,
@@ -145,10 +145,12 @@ namespace StgSharp.Math
internal unsafe void InternalTranspose() internal unsafe void InternalTranspose()
{ {
if( !isTransposed ) { if( !isTransposed ) {
fixed( ColumnSet3* source = &this.mat ) fixed( ColumnSet3* source = &this.mat ) {
fixed( ColumnSet4* target = &this.transpose ) { fixed( ColumnSet4* target = &this.transpose ) {
InternalIO.Intrinsic.transpose34( source, target ); InternalIO.Intrinsic.transpose34( source, target );
} }
}
isTransposed = true; isTransposed = true;
} }
} }
@@ -250,7 +252,9 @@ namespace StgSharp.Math
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [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(); 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 );
+45 -38
View File
@@ -43,7 +43,7 @@ namespace StgSharp.Math
LayoutKind.Explicit, LayoutKind.Explicit,
Size = ( 2 * 16 * sizeof( float ) ) + sizeof( bool ), Size = ( 2 * 16 * sizeof( float ) ) + sizeof( bool ),
Pack = 16 )] Pack = 16 )]
public unsafe struct Matrix44 : IEquatable<Matrix44>, IMat public unsafe struct Matrix44 : IEquatable<Matrix44>, IMatrix<Matrix44>
{ {
[FieldOffset( 2 * 64 * sizeof( float ) )] internal bool isTransposed; [FieldOffset( 2 * 64 * sizeof( float ) )] internal bool isTransposed;
@@ -55,12 +55,6 @@ namespace StgSharp.Math
[FieldOffset( 8 * sizeof( float ) )] internal Vec4 colum2; [FieldOffset( 8 * sizeof( float ) )] internal Vec4 colum2;
[FieldOffset( 12 * sizeof( float ) )] internal Vec4 colum3; [FieldOffset( 12 * sizeof( float ) )] internal Vec4 colum3;
public Matrix44()
{
Unsafe.SkipInit(out this);
isTransposed = false;
}
internal Matrix44( ColumnSet4 mat ) internal Matrix44( ColumnSet4 mat )
{ {
Unsafe.SkipInit( out this ); Unsafe.SkipInit( out this );
@@ -82,6 +76,12 @@ namespace StgSharp.Math
mat.colum3 = vec3; mat.colum3 = vec3;
} }
public Matrix44()
{
Unsafe.SkipInit( out this );
isTransposed = false;
}
public unsafe Matrix44( public unsafe Matrix44(
float a00, float a00,
float a01, float a01,
@@ -195,6 +195,35 @@ namespace StgSharp.Math
mat.colum2.GetHashCode(), mat.colum3.GetHashCode() ); 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() public override string ToString()
{ {
InternalTranspose(); InternalTranspose();
@@ -237,20 +266,9 @@ namespace StgSharp.Math
mat.mat.colum2 * value, mat.mat.colum3 * value ); mat.mat.colum2 * value, mat.mat.colum3 * value );
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [Obsolete(
public unsafe Matrix42 Multiple(in Matrix42 right) "The operand may cause performance loss, use Matrix.Multiple() method instead.",
{ false )]
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)]
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static unsafe Matrix42 operator *( public static unsafe Matrix42 operator *(
Matrix44 left, Matrix44 left,
@@ -259,28 +277,15 @@ namespace StgSharp.Math
return left.Multiple( right ); return left.Multiple( right );
} }
public unsafe Matrix43 Multiple(in Matrix43 right) [Obsolete(
{ "The operand may cause performance loss, use Matrix.Multiple() method instead.",
InternalTranspose(); false )]
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)]
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Matrix43 operator *( Matrix44 left, Matrix43 right ) public static Matrix43 operator *( Matrix44 left, Matrix43 right )
{ {
return left.Multiple( in right ); return left.Multiple( in right );
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Matrix44 operator *( Matrix44 left, Matrix44 right ) public static Matrix44 operator *( Matrix44 left, Matrix44 right )
{ {
@@ -308,7 +313,9 @@ namespace StgSharp.Math
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [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(); 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 );
+37 -6
View File
@@ -28,6 +28,9 @@
// //
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
using StgSharp.HighPerformance;
using System.Net.Http.Headers;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -35,20 +38,20 @@ using System.Runtime.InteropServices;
namespace StgSharp.Math namespace StgSharp.Math
{ {
/// <summary> /// <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. /// vector.
/// </summary> /// </summary>
[StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )] [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 unsafe fixed float num[ 2 ];
[FieldOffset( 0 )] [FieldOffset( 0 )]
internal Vector2 v; internal M128 reg;
[FieldOffset( 0 )] [FieldOffset( 0 )]
internal Vector4 vec; internal Vector2 v;
[FieldOffset( 0 )] [FieldOffset( 0 )]
public float X; public float X;
@@ -57,12 +60,19 @@ namespace StgSharp.Math
internal Vec2( Vector2 vec ) internal Vec2( Vector2 vec )
{ {
Unsafe.SkipInit( out reg );
Unsafe.SkipInit( out X );
Unsafe.SkipInit( out Y );
v = vec; 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 ) public Vec2( float x, float y )
@@ -74,6 +84,27 @@ namespace StgSharp.Math
public static Vec2 Zero => new Vec2( 0, 0 ); 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 )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public float Cross( Vec2 right ) public float Cross( Vec2 right )
{ {
+26 -21
View File
@@ -38,26 +38,26 @@ using System.Runtime.InteropServices;
namespace StgSharp.Math namespace StgSharp.Math
{ {
[StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )] [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 unsafe fixed float num[ 3 ];
[FieldOffset( 0 )] [FieldOffset( 0 )] internal M128 reg;
internal M128 reg;
[FieldOffset( 0 )] [FieldOffset( 0 )] internal Vector3 v;
internal Vector3 v;
[FieldOffset( 0 )]
internal Vector4 vec;
[FieldOffset( 0 )] public float X; [FieldOffset( 0 )] public float X;
[FieldOffset( 4 )] public float Y; [FieldOffset( 4 )] public float Y;
[FieldOffset( 8 )] public float Z; [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 ) internal Vec3( Vector3 vector )
@@ -67,21 +67,26 @@ namespace StgSharp.Math
public Vec3( Vec2 xy, float z ) 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; Z = z;
} }
public Vec3( float x, float y, float z ) public Vec3( float x, float y, float z )
{ {
#if NET5_0_OR_GREATER Unsafe.SkipInit( out reg );
Unsafe.SkipInit( out vec ); Unsafe.SkipInit( out X );
#endif Unsafe.SkipInit( out Y );
Unsafe.SkipInit( out Z );
v = new Vector3( x, y, z ); v = new Vector3( x, y, z );
} }
public unsafe Vec2 XY public unsafe Vec2 XY
{ {
get => new Vec2( this.vec ); get => new Vec2( this.reg );
set set
{ {
fixed( Vector3* vptr = &v ) { fixed( Vector3* vptr = &v ) {
@@ -93,6 +98,7 @@ namespace StgSharp.Math
public Vec3 XYZ public Vec3 XYZ
{ {
get { return new Vec3( v ); } get { return new Vec3( v ); }
set { this = value; }
} }
public static Vec3 Zero public static Vec3 Zero
@@ -122,7 +128,7 @@ namespace StgSharp.Math
public bool Equals( Vec3 other ) public bool Equals( Vec3 other )
{ {
return this.vec == other.vec; return this.reg == other.reg;
} }
public override bool Equals( object obj ) public override bool Equals( object obj )
@@ -168,7 +174,7 @@ namespace StgSharp.Math
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Vec3 operator -( Vec3 vec ) public static Vec3 operator -( Vec3 vec )
{ {
return new Vec3( -vec.vec ); return new Vec3( -vec.v );
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
@@ -204,7 +210,7 @@ namespace StgSharp.Math
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Vec3 operator +( Vec3 left, Vec3 right ) 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 )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
@@ -217,9 +223,8 @@ namespace StgSharp.Math
public static unsafe implicit operator Vec3( public static unsafe implicit operator Vec3(
(float, float, float) tuple ) (float, float, float) tuple )
{ {
Vec3 v = *( Vec3* )&tuple; Vec3 vec = new Vec3( *( Vector3* )&tuple );
v.vec.W = 0.0f; return vec;
return v;
} }
} }
+29 -8
View File
@@ -41,7 +41,7 @@ using System.Runtime.InteropServices;
namespace StgSharp.Math namespace StgSharp.Math
{ {
[StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )] [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 ]; [FieldOffset( 0 )] internal unsafe fixed float num[ 4 ];
@@ -57,12 +57,33 @@ namespace StgSharp.Math
internal Vec4( Vector4 v ) 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; 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; W = w;
} }
@@ -73,7 +94,7 @@ namespace StgSharp.Math
public unsafe Vec2 XY public unsafe Vec2 XY
{ {
get => new Vec2( vec ); get => new Vec2( reg );
set set
{ {
X = value.X; X = value.X;
@@ -83,23 +104,23 @@ namespace StgSharp.Math
public unsafe Vec3 XYZ public unsafe Vec3 XYZ
{ {
get => new Vec3( vec ); get => new Vec3( reg );
set set
{ {
float w = W; float w = W;
vec = value.vec; reg = value.reg;
W = w; W = w;
} }
} }
public static Vec4 One public static Vec4 One
{ {
get => new Vec4( Vector4.One ); get => new Vec4( 1, 1, 1, 1 );
} }
public static Vec4 Zero public static Vec4 Zero
{ {
get => new Vec4( Vector4.Zero ); get => new Vec4( 0, 0, 0, 0 );
} }
[MethodImpl( MethodImplOptions.AggressiveInlining )] [MethodImpl( MethodImplOptions.AggressiveInlining )]
@@ -51,7 +51,7 @@ namespace StgSharp.Math
public static Vec3 Normalize( Vec3 vec ) 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 ) public static unsafe void Normalize( ref Vec4 source, ref Vec4 target )
+5 -5
View File
@@ -60,7 +60,7 @@ namespace StgSharp.Math
throw new ArgumentException(); throw new ArgumentException();
} }
float r, s, u, v = 0.0f; float r, s, u, vec = 0.0f;
bool transform = (y >= 0.5f); bool transform = (y >= 0.5f);
if (transform) if (transform)
@@ -93,16 +93,16 @@ namespace StgSharp.Math
c = (r - s1 * s1) / (s + s1); c = (r - s1 * s1) / (s + s1);
p = 2.0F * s * u - (piby2_tail - 2.0F * c); p = 2.0F * s * u - (piby2_tail - 2.0F * c);
q = hpiby2_head - 2.0F * s1; q = hpiby2_head - 2.0F * s1;
v = hpiby2_head - (p - q); vec = hpiby2_head - (p - q);
} }
else 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(); throw new ArgumentException();
} }
float r, s, u, v = 0.0f; float r, s, u, vec = 0.0f;
bool transform = (y >= 0.5f); bool transform = (y >= 0.5f);
if (transform) if (transform)
@@ -101,14 +101,14 @@ namespace StgSharp.Math
c = (r - s1 * s1) / (s + s1); c = (r - s1 * s1) / (s + s1);
p = 2.0F * s * u - (piby2_tail - 2.0F * c); p = 2.0F * s * u - (piby2_tail - 2.0F * c);
q = hpiby2_head - 2.0F * s1; q = hpiby2_head - 2.0F * s1;
v = hpiby2_head - (p - q); vec = hpiby2_head - (p - q);
} }
else 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; angle = 0.7853981634f;
} }
float v = 0.7853981634f * x + x * (1 - x) * (0.2447f + 0.0663f * x); float vec = 0.7853981634f * x + x * (1 - x) * (0.2447f + 0.0663f * x);
v += angle; vec += angle;
v *= sign; vec *= sign;
return v; return vec;
} }
@@ -105,13 +105,13 @@ namespace StgSharp.Math
angle2 = 0.7853981634f; angle2 = 0.7853981634f;
} }
float v = 0.7853981634f * z + z * (1 - z) * (0.2447f + 0.0663f * z); float vec = 0.7853981634f * z + z * (1 - z) * (0.2447f + 0.0663f * z);
v *= 57.29577951f; vec *= 57.29577951f;
v += angle2; vec += angle2;
v += angle; vec += angle;
v *= sign; 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> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Logic\" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">
</Target> </Target>
@@ -50,8 +50,7 @@ namespace StgSharp.Threading
{ {
if( isNotMainThread.Value ) { if( isNotMainThread.Value ) {
throw new InvalidOperationException( throw new InvalidOperationException(
$"Attempt to call sensitive operation which can be only called from main thread " $"Attempt to call sensitive operation which can be only called from main thread " + $"from thread {Environment.CurrentManagedThreadId}." );
+ $"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.AssemblyCompanyAttribute("StgSharp.Common")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [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.AssemblyProductAttribute("StgSharp.Common")]
[assembly: System.Reflection.AssemblyTitleAttribute("StgSharp.Common")] [assembly: System.Reflection.AssemblyTitleAttribute("StgSharp.Common")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -32,7 +32,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace StgSharp.Blueprint namespace StgSharp.PipeLine
{ {
[AttributeUsage( AttributeTargets.Method, AllowMultiple = false )] [AttributeUsage( AttributeTargets.Method, AllowMultiple = false )]
public class BlueprintNodeExecutionAttribute : Attribute { } public class BlueprintNodeExecutionAttribute : Attribute { }
@@ -33,7 +33,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using StgSharp.Blueprint; using StgSharp.PipeLine;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -44,64 +44,51 @@ namespace StgSharp.Generator
{ {
internal class BpNodeSyntaxReceiver : ISyntaxReceiver internal class BpNodeSyntaxReceiver : ISyntaxReceiver
{ {
private static BpNodeSyntaxReceiver receiver = new BpNodeSyntaxReceiver(
);
private static readonly string _indexTypeName = typeof( PartialDictionary<string, object> ).Name; 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 BpNodeSyntaxReceiver() { }
public List<MethodDeclarationSyntax> InvalidMethod { get; private set; } = new List<MethodDeclarationSyntax>();
public BpNodeSyntaxReceiver()
{
}
public BpNodeSyntaxReceiver( SyntaxNode node ) public BpNodeSyntaxReceiver( SyntaxNode node )
{ {
OnVisitSyntaxNode( node ); OnVisitSyntaxNode( node );
} }
public void OnVisitSyntaxNode( SyntaxNode syntaxNode ) public List<MethodDeclarationSyntax> ValidMethod
{ {
if( syntaxNode is MethodDeclarationSyntax mds && mds.AttributeLists get;
private set;
} = new List<MethodDeclarationSyntax>();
public List<MethodDeclarationSyntax> InvalidMethod
{
get;
private set;
} = new List<MethodDeclarationSyntax>();
public static void BuildNode(
SourceProductionContext context,
MethodDeclarationSyntax mds )
{
if( mds.AttributeLists
.SelectMany( list => list.Attributes ) .SelectMany( list => list.Attributes )
.Any( syntax => syntax.Name.ToString() == .Any(
syntax => syntax.Name.ToString() ==
typeof( BlueprintNodeExecutionAttribute ).Name ) ) { typeof( BlueprintNodeExecutionAttribute ).Name ) ) {
SeparatedSyntaxList<ParameterSyntax> paramList = mds.ParameterList.Parameters; SeparatedSyntaxList<ParameterSyntax> paramList = mds.ParameterList.Parameters;
if( mds.Modifiers.Any( SyntaxKind.StaticKeyword ) && paramList.Count == if( mds.Modifiers.Any( SyntaxKind.StaticKeyword ) && paramList.Count ==
2 && paramList[ 0 ].Type!.ToString() == _indexTypeName && paramList[ 2 && paramList[ 0 ].Type!.ToString() == _indexTypeName && paramList[
1 ].Type!.ToString() == 1 ].Type!.ToString() ==
_indexTypeName ) { _indexTypeName ) {
ValidMethod.Add(mds); string methodName = mds.Identifier.Text;
} SourceText sourceText = SourceText.From(
else string.Empty, encoding: Encoding.UTF8 );
{ context.AddSource( "GeneratedBlueprintNode.cs",
InvalidMethod.Add(mds); sourceText );
} } else {
} Diagnostic diagnostic = Diagnostic.Create(
}
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(
new DiagnosticDescriptor( new DiagnosticDescriptor(
id: "SSE0001", id: "SSE0001",
title: "Invalid Blueprint Node Method", title: "Invalid Blueprint Node Method",
@@ -115,5 +102,25 @@ namespace StgSharp.Generator
} }
} }
} }
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.Geometries;
using StgSharp.Math; using StgSharp.Math;
using StgSharp.PipeLine;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -10,12 +40,32 @@ 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 Point this[ int index ]
public abstract CoordinationBase Coordination { get; } {
public abstract int VertexCount { get; } get;
public abstract ReadOnlySpan<int> VertexIndices { 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;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;