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:
@@ -332,7 +332,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
|||||||
if (!cbpIsCompressed)
|
if (!cbpIsCompressed)
|
||||||
cbf = (byte[])cbp.Clone();
|
cbf = (byte[])cbp.Clone();
|
||||||
else
|
else
|
||||||
LCWDecodeInto(cbp, cbf);
|
LCWCompression.DecodeInto(cbp, cbf);
|
||||||
|
|
||||||
chunkBufferOffset = currentChunkBuffer = 0;
|
chunkBufferOffset = currentChunkBuffer = 0;
|
||||||
}
|
}
|
||||||
@@ -352,7 +352,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
|||||||
s.ReadBytes(fileBuffer, 0, subchunkLength);
|
s.ReadBytes(fileBuffer, 0, subchunkLength);
|
||||||
Array.Clear(cbf, 0, cbf.Length);
|
Array.Clear(cbf, 0, cbf.Length);
|
||||||
Array.Clear(cbfBuffer, 0, cbfBuffer.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)
|
if ((videoFlags & 0x10) == 16)
|
||||||
{
|
{
|
||||||
var p = 0;
|
var p = 0;
|
||||||
@@ -406,7 +406,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
|||||||
|
|
||||||
// Frame data
|
// Frame data
|
||||||
case "VPTZ":
|
case "VPTZ":
|
||||||
LCWDecodeInto(s.ReadBytes(subchunkLength), origData);
|
LCWCompression.DecodeInto(s.ReadBytes(subchunkLength), origData);
|
||||||
|
|
||||||
// This is the last subchunk
|
// This is the last subchunk
|
||||||
return;
|
return;
|
||||||
@@ -414,9 +414,9 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
|||||||
Array.Clear(origData, 0, origData.Length);
|
Array.Clear(origData, 0, origData.Length);
|
||||||
s.ReadBytes(fileBuffer, 0, subchunkLength);
|
s.ReadBytes(fileBuffer, 0, subchunkLength);
|
||||||
if (fileBuffer[0] != 0)
|
if (fileBuffer[0] != 0)
|
||||||
vtprSize = LCWDecodeInto(fileBuffer, origData);
|
vtprSize = LCWCompression.DecodeInto(fileBuffer, origData);
|
||||||
else
|
else
|
||||||
LCWDecodeInto(fileBuffer, origData, 1, true);
|
LCWCompression.DecodeInto(fileBuffer, origData, 1, true);
|
||||||
return;
|
return;
|
||||||
case "VPTR":
|
case "VPTR":
|
||||||
Array.Clear(origData, 0, origData.Length);
|
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++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,10 +108,10 @@ namespace OpenRA.Mods.Cnc.Graphics
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
var v = l.VoxelMap[(byte)x, (byte)y];
|
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 null;
|
||||||
|
|
||||||
return l.VoxelMap[(byte)x, (byte)y][(byte)z];
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cull slices without any visible faces
|
// Cull slices without any visible faces
|
||||||
|
|||||||
@@ -120,8 +120,7 @@ namespace OpenRA.Mods.Cnc.SpriteLoaders
|
|||||||
for (var j = 0; j < size.Height; j++)
|
for (var j = 0; j < size.Height; j++)
|
||||||
{
|
{
|
||||||
var start = (j - frameBounds.Y) * frameBounds.Width + (size.Width - width) / 2 - frameBounds.X;
|
var start = (j - frameBounds.Y) * frameBounds.Width + (size.Width - width) / 2 - frameBounds.X;
|
||||||
for (var i = 0; i < width; i++)
|
s.ReadBytes(data, start, width);
|
||||||
data[start + i] = s.ReadUInt8();
|
|
||||||
|
|
||||||
width += (j < size.Height / 2 - 1 ? 1 : -1) * 4;
|
width += (j < size.Height / 2 - 1 ? 1 : -1) * 4;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.FileFormats
|
namespace OpenRA.Mods.Common.FileFormats
|
||||||
{
|
{
|
||||||
// Run length encoded sequences of zeros (aka Format2)
|
// Run length encoded sequences of zeros (aka Format2)
|
||||||
@@ -24,8 +26,8 @@ namespace OpenRA.Mods.Common.FileFormats
|
|||||||
if (cmd == 0)
|
if (cmd == 0)
|
||||||
{
|
{
|
||||||
var count = r.ReadByte();
|
var count = r.ReadByte();
|
||||||
while (count-- > 0)
|
Array.Clear(dest, destIndex, count);
|
||||||
dest[destIndex++] = 0;
|
destIndex += count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dest[destIndex++] = cmd;
|
dest[destIndex++] = cmd;
|
||||||
|
|||||||
Reference in New Issue
Block a user