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