Browse Source

made some structs ReadOnly
refactored VertexList so it doesn't require s threadstatic hack.

Vicente Penades 5 years ago
parent
commit
a1f6e41571

+ 4 - 4
src/SharpGLTF.Core/Animations/CubicSamplers.cs

@@ -9,7 +9,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="Vector3"/> curve sampler that can be sampled with CUBIC interpolation.
     /// </summary>
-    struct Vector3CubicSampler : ICurveSampler<Vector3>, IConvertibleCurve<Vector3>
+    readonly struct Vector3CubicSampler : ICurveSampler<Vector3>, IConvertibleCurve<Vector3>
     {
         #region lifecycle
 
@@ -73,7 +73,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="Quaternion"/> curve sampler that can be sampled with CUBIC interpolation.
     /// </summary>
-    struct QuaternionCubicSampler : ICurveSampler<Quaternion>, IConvertibleCurve<Quaternion>
+    readonly struct QuaternionCubicSampler : ICurveSampler<Quaternion>, IConvertibleCurve<Quaternion>
     {
         #region lifecycle
 
@@ -137,7 +137,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="Transforms.SparseWeight8"/> curve sampler that can be sampled with CUBIC interpolation.
     /// </summary>
-    struct SparseCubicSampler : ICurveSampler<Transforms.SparseWeight8>, IConvertibleCurve<Transforms.SparseWeight8>
+    readonly struct SparseCubicSampler : ICurveSampler<Transforms.SparseWeight8>, IConvertibleCurve<Transforms.SparseWeight8>
     {
         #region lifecycle
 
@@ -201,7 +201,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="float"/>[] curve sampler that can be sampled with CUBIC interpolation.
     /// </summary>
-    struct ArrayCubicSampler : ICurveSampler<float[]>, IConvertibleCurve<float[]>
+    readonly struct ArrayCubicSampler : ICurveSampler<float[]>, IConvertibleCurve<float[]>
     {
         #region lifecycle
 

+ 1 - 1
src/SharpGLTF.Core/Animations/FastSampler.cs

@@ -9,7 +9,7 @@ namespace SharpGLTF.Animations
     /// Wraps a collection of samplers split over time to speed up key retrieval.
     /// </summary>
     /// <typeparam name="T">The value sampled at any offset</typeparam>
-    struct FastSampler<T> : ICurveSampler<T>
+    readonly struct FastSampler<T> : ICurveSampler<T>
     {
         public FastSampler(IEnumerable<ICurveSampler<T>> samplers)
         {

+ 5 - 5
src/SharpGLTF.Core/Animations/LinearSamplers.cs

@@ -6,7 +6,7 @@ using System.Text;
 
 namespace SharpGLTF.Animations
 {
-    struct SingleValueSampler<T> : ICurveSampler<T>, IConvertibleCurve<T>
+    readonly struct SingleValueSampler<T> : ICurveSampler<T>, IConvertibleCurve<T>
     {
         #region lifecycle
 
@@ -64,7 +64,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="Vector3"/> curve sampler that can be sampled with STEP or LINEAR interpolations.
     /// </summary>
-    struct Vector3LinearSampler : ICurveSampler<Vector3>, IConvertibleCurve<Vector3>
+    readonly struct Vector3LinearSampler : ICurveSampler<Vector3>, IConvertibleCurve<Vector3>
     {
         #region lifecycle
 
@@ -130,7 +130,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="Quaternion"/> curve sampler that can be sampled with STEP or LINEAR interpolations.
     /// </summary>
-    struct QuaternionLinearSampler : ICurveSampler<Quaternion>, IConvertibleCurve<Quaternion>
+    readonly struct QuaternionLinearSampler : ICurveSampler<Quaternion>, IConvertibleCurve<Quaternion>
     {
         #region lifecycle
 
@@ -196,7 +196,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="Transforms.SparseWeight8"/> curve sampler that can be sampled with STEP or LINEAR interpolation.
     /// </summary>
-    struct SparseLinearSampler : ICurveSampler<Transforms.SparseWeight8>, IConvertibleCurve<Transforms.SparseWeight8>
+    readonly struct SparseLinearSampler : ICurveSampler<Transforms.SparseWeight8>, IConvertibleCurve<Transforms.SparseWeight8>
     {
         #region lifecycle
 
@@ -263,7 +263,7 @@ namespace SharpGLTF.Animations
     /// <summary>
     /// Defines a <see cref="float"/>[] curve sampler that can be sampled with STEP or LINEAR interpolations.
     /// </summary>
-    struct ArrayLinearSampler : ICurveSampler<float[]>, IConvertibleCurve<float[]>
+    readonly struct ArrayLinearSampler : ICurveSampler<float[]>, IConvertibleCurve<float[]>
     {
         #region lifecycle
 

+ 2 - 2
src/SharpGLTF.Core/Collections/LinqDictionary.cs

@@ -12,7 +12,7 @@ namespace SharpGLTF.Collections
     /// <typeparam name="TKey">The dictionary key type.</typeparam>
     /// <typeparam name="TValueIn">The internal value type.</typeparam>
     /// <typeparam name="TValueOut">The exposed value type.</typeparam>
-    struct ReadOnlyLinqDictionary<TKey, TValueIn, TValueOut> : IReadOnlyDictionary<TKey, TValueOut>
+    readonly struct ReadOnlyLinqDictionary<TKey, TValueIn, TValueOut> : IReadOnlyDictionary<TKey, TValueOut>
     {
         #region lifecycle
 
@@ -81,7 +81,7 @@ namespace SharpGLTF.Collections
         #endregion
     }
 
-    struct LinqDictionary<TKey, TValueIn, TValueOut> : IDictionary<TKey, TValueOut>
+    readonly struct LinqDictionary<TKey, TValueIn, TValueOut> : IDictionary<TKey, TValueOut>
     {
         #region lifecycle
 

+ 8 - 1
src/SharpGLTF.Core/Schema2/gltf.MaterialChannel.cs

@@ -12,7 +12,7 @@ namespace SharpGLTF.Schema2
     /// to have an homogeneous and easy to use API.
     /// </remarks>
     [System.Diagnostics.DebuggerDisplay("Channel {_Key}")]
-    public struct MaterialChannel
+    public readonly struct MaterialChannel
     {
         #region lifecycle
 
@@ -68,6 +68,13 @@ namespace SharpGLTF.Schema2
         private readonly Func<Vector4> _ParameterGetter;
         private readonly Action<Vector4> _ParameterSetter;
 
+        public override int GetHashCode()
+        {
+            if (_Key == null) return 0;
+
+            return _Key.GetHashCode() ^ _Material.GetHashCode();
+        }
+
         #endregion
 
         #region properties

+ 41 - 30
src/SharpGLTF.Toolkit/Collections/VertexList.cs

@@ -16,10 +16,7 @@ namespace SharpGLTF.Collections
 
         private readonly List<T> _Vertices = new List<T>();
 
-        private readonly Dictionary<VertexKey, int> _VertexCache = new Dictionary<VertexKey, int>();
-
-        [ThreadStatic]
-        private readonly T[] _VertexProbe = new T[1];
+        private readonly Dictionary<IVertexKey, int> _VertexCache = new Dictionary<IVertexKey, int>(_KeyComparer.Instance);
 
         #endregion
 
@@ -35,9 +32,7 @@ namespace SharpGLTF.Collections
 
         public int Use(T v)
         {
-            _VertexProbe[0] = v;
-
-            if (_VertexCache.TryGetValue(new VertexKey(_VertexProbe, 0), out int index))
+            if (_VertexCache.TryGetValue(new QueryKey(v), out int index))
             {
                 System.Diagnostics.Debug.Assert(Object.Equals(v, _Vertices[index]), "Vertex equality failed");
                 return index;
@@ -47,7 +42,7 @@ namespace SharpGLTF.Collections
 
             _Vertices.Add(v);
 
-            var key = new VertexKey(_Vertices, index);
+            var key = new StoredKey(_Vertices, index);
 
             _VertexCache[key] = index;
 
@@ -62,7 +57,7 @@ namespace SharpGLTF.Collections
             {
                 _Vertices[i] = transformFunc(_Vertices[i]);
 
-                var key = new VertexKey(_Vertices, i);
+                var key = new StoredKey(_Vertices, i);
 
                 _VertexCache[key] = i;
             }
@@ -76,7 +71,7 @@ namespace SharpGLTF.Collections
 
                 var idx = dst._Vertices.Count;
                 dst._Vertices.Add(v);
-                dst._VertexCache[new VertexKey(dst._Vertices, idx)] = idx;
+                dst._VertexCache[new StoredKey(dst._Vertices, idx)] = idx;
             }
         }
 
@@ -84,26 +79,20 @@ namespace SharpGLTF.Collections
 
         #region types
 
-        [System.Diagnostics.DebuggerDisplay("{_Index} {GetHashCode()}")]
-        private struct VertexKey : IEquatable<VertexKey>
+        interface IVertexKey
         {
-            public VertexKey(IReadOnlyList<T> src, int idx)
-            {
-                _Source = src;
-                _Index = idx;
-            }
-
-            private readonly IReadOnlyList<T> _Source;
-            private readonly int _Index;
+            T GetValue();
+        }
 
-            public T GetValue() { return _Source[_Index]; }
+        sealed class _KeyComparer : IEqualityComparer<IVertexKey>
+        {
+            static _KeyComparer() { }
+            private _KeyComparer() { }
 
-            public override int GetHashCode()
-            {
-                return GetValue().GetHashCode();
-            }
+            private static readonly _KeyComparer _Instance = new _KeyComparer();
+            public static _KeyComparer Instance => _Instance;
 
-            public static bool AreEqual(VertexKey x, VertexKey y)
+            public bool Equals(IVertexKey x, IVertexKey y)
             {
                 var xx = x.GetValue();
                 var yy = y.GetValue();
@@ -111,15 +100,37 @@ namespace SharpGLTF.Collections
                 return object.Equals(xx, yy);
             }
 
-            public override bool Equals(object obj)
+            public int GetHashCode(IVertexKey obj)
             {
-                return AreEqual(this, (VertexKey)obj);
+                return obj
+                    .GetValue()
+                    .GetHashCode();
             }
+        }
+
+        [System.Diagnostics.DebuggerDisplay("{GetValue()} {GetHashCode()}")]
+        private readonly struct QueryKey : IVertexKey
+        {
+            public QueryKey(T value) { _Value = value; }
+
+            private readonly T _Value;
 
-            public bool Equals(VertexKey other)
+            public T GetValue() { return _Value; }
+        }
+
+        [System.Diagnostics.DebuggerDisplay("{GetValue()} {GetHashCode()}")]
+        private readonly struct StoredKey : IVertexKey
+        {
+            public StoredKey(IReadOnlyList<T> src, int idx)
             {
-                return AreEqual(this, other);
+                _Source = src;
+                _Index = idx;
             }
+
+            private readonly IReadOnlyList<T> _Source;
+            private readonly int _Index;
+
+            public T GetValue() { return _Source[_Index]; }
         }
 
         #endregion

+ 1 - 1
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexEmpty.cs

@@ -8,7 +8,7 @@ using SharpGLTF.Transforms;
 namespace SharpGLTF.Geometry.VertexTypes
 {
     [System.Diagnostics.DebuggerDisplay("Empty")]
-    public struct VertexEmpty : IVertexMaterial, IVertexSkinning
+    public readonly struct VertexEmpty : IVertexMaterial, IVertexSkinning
     {
         public void Validate() { }
 

+ 9 - 8
tests/SharpGLTF.NUnit/gltf_validator.cs

@@ -46,18 +46,19 @@ namespace SharpGLTF
             psi.UseShellExecute = false;            
             psi.RedirectStandardError = true;
 
-            var p = System.Diagnostics.Process.Start(psi);
-
-            if (!p.WaitForExit(1000 * 10))
+            using (var p = System.Diagnostics.Process.Start(psi))
             {
-                try { p.Kill(); } catch { }
-            }
+                if (!p.WaitForExit(1000 * 10))
+                {
+                    try { p.Kill(); } catch { }
+                }
 
-            var rawReport = p.StandardError.ReadToEnd();
+                var rawReport = p.StandardError.ReadToEnd();
 
-            if (string.IsNullOrWhiteSpace(rawReport)) return null;
+                if (string.IsNullOrWhiteSpace(rawReport)) return null;
 
-            return new ValidationReport(gltfFilePath, rawReport);
+                return new ValidationReport(gltfFilePath, rawReport);
+            }
         }
 
         public sealed class ValidationReport

+ 1 - 1
tests/SharpGLTF.Tests/AssemblyAPITests.cs

@@ -111,6 +111,6 @@ namespace SharpGLTF
             }
 
             Warn.If(!backwardsCompatible, "Current API is not backwards compatible");
-        }
+        }        
     }
 }

+ 1 - 0
tests/SharpGLTF.Tests/Collections/VertexListTests.cs

@@ -10,6 +10,7 @@ namespace SharpGLTF.Collections
     [Category("Core")]
     public class VertexListTests
     {
+        [System.Diagnostics.DebuggerDisplay("{Value}")]
         struct _VertexExample
         {
             public static implicit operator _VertexExample(int value)

+ 7 - 1
tests/SharpGLTF.Tests/SharpGLTF.Tests.csproj

@@ -11,7 +11,13 @@
     <ProjectReference Include="..\SharpGLTF.NUnit\SharpGLTF.NUnit.csproj" />
   </ItemGroup>
 
-  <ItemGroup>    
+  <ItemGroup>
+    
+    <!--
+    <PackageReference Include="Mono.ApiTools.NuGetDiff" Version="1.3.1" />    
+    <PackageReference Include="Mono.ApiTools" Version="5.14.0.2" />
+    -->
+    
     <PackageReference Include="NUnit3TestAdapter" Version="3.16.1">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>