Improve loading performance for loader/compression classes.

- In RLEZerosCompression use dedicated Array.Clear method instead of open-coded loop.
- In VoxelLoader.GenerateSlicePlanes.Get use TryGetValue to avoid repeated array and dictionary lookups.
- In TmpTSLoader.UnpackTileData use ReadBytes to populate array with less overhead compared to repeated one byte reads.
- Resolve TODO in VqaVideo.
This commit is contained in:
RoosterDragon
2023-06-28 18:47:23 +01:00
committed by Gustas
parent dccb3ce9ce
commit 1c0885c636
4 changed files with 12 additions and 81 deletions

View File

@@ -332,7 +332,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
if (!cbpIsCompressed)
cbf = (byte[])cbp.Clone();
else
LCWDecodeInto(cbp, cbf);
LCWCompression.DecodeInto(cbp, cbf);
chunkBufferOffset = currentChunkBuffer = 0;
}
@@ -352,7 +352,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
s.ReadBytes(fileBuffer, 0, subchunkLength);
Array.Clear(cbf, 0, cbf.Length);
Array.Clear(cbfBuffer, 0, cbfBuffer.Length);
var decodeCount = LCWDecodeInto(fileBuffer, cbfBuffer, decodeMode ? 1 : 0, decodeMode);
var decodeCount = LCWCompression.DecodeInto(fileBuffer, cbfBuffer, decodeMode ? 1 : 0, decodeMode);
if ((videoFlags & 0x10) == 16)
{
var p = 0;
@@ -406,7 +406,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
// Frame data
case "VPTZ":
LCWDecodeInto(s.ReadBytes(subchunkLength), origData);
LCWCompression.DecodeInto(s.ReadBytes(subchunkLength), origData);
// This is the last subchunk
return;
@@ -414,9 +414,9 @@ namespace OpenRA.Mods.Cnc.FileFormats
Array.Clear(origData, 0, origData.Length);
s.ReadBytes(fileBuffer, 0, subchunkLength);
if (fileBuffer[0] != 0)
vtprSize = LCWDecodeInto(fileBuffer, origData);
vtprSize = LCWCompression.DecodeInto(fileBuffer, origData);
else
LCWDecodeInto(fileBuffer, origData, 1, true);
LCWCompression.DecodeInto(fileBuffer, origData, 1, true);
return;
case "VPTR":
Array.Clear(origData, 0, origData.Length);
@@ -541,75 +541,5 @@ namespace OpenRA.Mods.Cnc.FileFormats
}
}
}
// TODO: Maybe replace this with LCWCompression.DecodeInto again later
public static int LCWDecodeInto(byte[] src, byte[] dest, int srcOffset = 0, bool reverse = false)
{
var ctx = new FastByteReader(src, srcOffset);
var destIndex = 0;
while (true)
{
var i = ctx.ReadByte();
if ((i & 0x80) == 0)
{
// case 2
var secondByte = ctx.ReadByte();
var count = ((i & 0x70) >> 4) + 3;
var rpos = ((i & 0xf) << 8) + secondByte;
if (destIndex + count > dest.Length)
return destIndex;
// Replicate previous
var srcIndex = destIndex - rpos;
if (srcIndex > destIndex)
throw new NotImplementedException($"srcIndex > destIndex {srcIndex} {destIndex}");
for (var j = 0; j < count; j++)
{
if (destIndex - srcIndex == 1)
dest[destIndex + j] = dest[destIndex - 1];
else
dest[destIndex + j] = dest[srcIndex + j];
}
destIndex += count;
}
else if ((i & 0x40) == 0)
{
// case 1
var count = i & 0x3F;
if (count == 0)
return destIndex;
ctx.CopyTo(dest, destIndex, count);
destIndex += count;
}
else
{
var count3 = i & 0x3F;
if (count3 == 0x3E)
{
// case 4
var count = ctx.ReadWord();
var color = ctx.ReadByte();
for (var end = destIndex + count; destIndex < end; destIndex++)
dest[destIndex] = color;
}
else
{
// If count3 == 0x3F it's case 5, else case 3
var count = count3 == 0x3F ? ctx.ReadWord() : count3 + 3;
var srcIndex = reverse ? destIndex - ctx.ReadWord() : ctx.ReadWord();
if (srcIndex >= destIndex)
throw new NotImplementedException($"srcIndex >= destIndex {srcIndex} {destIndex}");
for (var end = destIndex + count; destIndex < end; destIndex++)
dest[destIndex] = dest[srcIndex++];
}
}
}
}
}
}

View File

@@ -108,10 +108,10 @@ namespace OpenRA.Mods.Cnc.Graphics
return null;
var v = l.VoxelMap[(byte)x, (byte)y];
if (v == null || !v.ContainsKey((byte)z))
if (v == null || !v.TryGetValue((byte)z, out var element))
return null;
return l.VoxelMap[(byte)x, (byte)y][(byte)z];
return element;
}
// Cull slices without any visible faces

View File

@@ -120,8 +120,7 @@ namespace OpenRA.Mods.Cnc.SpriteLoaders
for (var j = 0; j < size.Height; j++)
{
var start = (j - frameBounds.Y) * frameBounds.Width + (size.Width - width) / 2 - frameBounds.X;
for (var i = 0; i < width; i++)
data[start + i] = s.ReadUInt8();
s.ReadBytes(data, start, width);
width += (j < size.Height / 2 - 1 ? 1 : -1) * 4;
}

View File

@@ -9,6 +9,8 @@
*/
#endregion
using System;
namespace OpenRA.Mods.Common.FileFormats
{
// Run length encoded sequences of zeros (aka Format2)
@@ -24,8 +26,8 @@ namespace OpenRA.Mods.Common.FileFormats
if (cmd == 0)
{
var count = r.ReadByte();
while (count-- > 0)
dest[destIndex++] = 0;
Array.Clear(dest, destIndex, count);
destIndex += count;
}
else
dest[destIndex++] = cmd;