Mesh decoding performance improvements

This commit is contained in:
ds5678 2024-09-02 21:00:40 -07:00
parent 8c1728e2af
commit d392a8c57a

View File

@ -2,6 +2,7 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace AssetRipper.SourceGenerated.Extensions namespace AssetRipper.SourceGenerated.Extensions
{ {
@ -189,20 +190,33 @@ namespace AssetRipper.SourceGenerated.Extensions
ArgumentNullException.ThrowIfNull(input); ArgumentNullException.ThrowIfNull(input);
ArgumentOutOfRangeException.ThrowIfLessThan(dimension, 1); ArgumentOutOfRangeException.ThrowIfLessThan(dimension, 1);
ArgumentOutOfRangeException.ThrowIfGreaterThan(dimension, 4);
ValidateLength(input, dimension);
if (input.Length % dimension != 0) Vector2[] result = GC.AllocateUninitializedArray<Vector2>(input.Length / dimension);
switch (dimension)
{ {
throw new ArgumentException($"Input array length {input.Length} is not divisible by dimension {dimension}", nameof(input)); case 1:
} for (int i = result.Length - 1; i >= 0; i--)
{
Vector2[] result = new Vector2[input.Length / dimension]; result[i] = new Vector2(input[i], 0);
for (int i = 0; i < result.Length; i++) }
{ break;
result[i] = dimension switch case 2:
{ MemoryMarshal.Cast<float, Vector2>(input).CopyTo(result);
1 => new Vector2(input[dimension * i], 0), break;
_ => new Vector2(input[dimension * i], input[dimension * i + 1]), case 3:
}; for (int i = result.Length - 1; i >= 0; i--)
{
result[i] = new Vector2(input[3 * i], input[3 * i + 1]);
}
break;
case 4:
for (int i = result.Length - 1; i >= 0; i--)
{
result[i] = new Vector2(input[4 * i], input[4 * i + 1]);
}
break;
} }
return result; return result;
} }
@ -213,22 +227,36 @@ namespace AssetRipper.SourceGenerated.Extensions
ArgumentNullException.ThrowIfNull(input); ArgumentNullException.ThrowIfNull(input);
ArgumentOutOfRangeException.ThrowIfLessThan(dimension, 1); ArgumentOutOfRangeException.ThrowIfLessThan(dimension, 1);
ArgumentOutOfRangeException.ThrowIfGreaterThan(dimension, 4);
ValidateLength(input, dimension);
if (input.Length % dimension != 0) //In the four dimensional case for Normals, the fourth dimension was always zero
{ //This is seemingly intended to maintain data alignment
throw new ArgumentException($"Input array length {input.Length} is not divisible by dimension {dimension}", nameof(input));
}
Vector3[] result = new Vector3[input.Length / dimension]; Vector3[] result = GC.AllocateUninitializedArray<Vector3>(input.Length / dimension);
for (int i = 0; i < result.Length; i++) switch (dimension)
{ {
result[i] = dimension switch case 1:
{ for (int i = result.Length - 1; i >= 0; i--)
1 => new Vector3(input[dimension * i], input[dimension * i + 1], input[dimension * i + 2]), {
2 => new Vector3(input[dimension * i], input[dimension * i + 1], input[dimension * i + 2]), result[i] = new Vector3(input[i], 0, 0);
_ => new Vector3(input[dimension * i], input[dimension * i + 1], input[dimension * i + 2]), //In the four dimensional case for Normals, the fourth dimension was always zero }
//This is seemingly intended to maintain data alignment break;
}; case 2:
for (int i = result.Length - 1; i >= 0; i--)
{
result[i] = new Vector3(input[2 * i], input[2 * i + 1], 0);
}
break;
case 3:
MemoryMarshal.Cast<float, Vector3>(input).CopyTo(result);
break;
case 4:
for (int i = result.Length - 1; i >= 0; i--)
{
result[i] = new Vector3(input[4 * i], input[4 * i + 1], input[4 * i + 2]);
}
break;
} }
return result; return result;
} }
@ -239,24 +267,43 @@ namespace AssetRipper.SourceGenerated.Extensions
ArgumentNullException.ThrowIfNull(input); ArgumentNullException.ThrowIfNull(input);
ArgumentOutOfRangeException.ThrowIfLessThan(dimension, 1); ArgumentOutOfRangeException.ThrowIfLessThan(dimension, 1);
ArgumentOutOfRangeException.ThrowIfGreaterThan(dimension, 4);
ValidateLength(input, dimension);
Vector4[] result = GC.AllocateUninitializedArray<Vector4>(input.Length / dimension);
switch (dimension)
{
case 1:
for (int i = result.Length - 1; i >= 0; i--)
{
result[i] = new Vector4(input[i], 0, 0, 0);
}
break;
case 2:
for (int i = result.Length - 1; i >= 0; i--)
{
result[i] = new Vector4(input[2 * i], input[2 * i + 1], 0, 0);
}
break;
case 3:
for (int i = result.Length - 1; i >= 0; i--)
{
result[i] = new Vector4(input[3 * i], input[3 * i + 1], input[3 * i + 2], 0);
}
break;
case 4:
MemoryMarshal.Cast<float, Vector4>(input).CopyTo(result);
break;
}
return result;
}
private static void ValidateLength(float[] input, int dimension)
{
if (input.Length % dimension != 0) if (input.Length % dimension != 0)
{ {
throw new ArgumentException($"Input array length {input.Length} is not divisible by dimension {dimension}", nameof(input)); throw new ArgumentException($"Input array length {input.Length} is not divisible by dimension {dimension}", nameof(input));
} }
Vector4[] result = new Vector4[input.Length / dimension];
for (int i = 0; i < result.Length; i++)
{
result[i] = dimension switch
{
1 => new Vector4(input[dimension * i], 0, 0, 0),
2 => new Vector4(input[dimension * i], input[dimension * i + 1], 0, 0),
3 => new Vector4(input[dimension * i], input[dimension * i + 1], input[dimension * i + 2], 0),
_ => new Vector4(input[dimension * i], input[dimension * i + 1], input[dimension * i + 2], input[dimension * i + 3]),
};
}
return result;
} }
public static ColorFloat[] FloatArrayToColorFloat(float[] input) public static ColorFloat[] FloatArrayToColorFloat(float[] input)
@ -268,12 +315,7 @@ namespace AssetRipper.SourceGenerated.Extensions
throw new ArgumentException($"Input array length {input.Length} is not divisible by four", nameof(input)); throw new ArgumentException($"Input array length {input.Length} is not divisible by four", nameof(input));
} }
ColorFloat[] result = new ColorFloat[input.Length / 4]; return MemoryMarshal.Cast<float, ColorFloat>(input).ToArray();
for (int i = 0; i < result.Length; i++)
{
result[i] = new ColorFloat(input[4 * i], input[4 * i + 1], input[4 * i + 2], input[4 * i + 3]);
}
return result;
} }
} }
} }