Changeset 331


Ignore:
Timestamp:
Sep 6, 2018, 1:46:44 AM (6 years ago)
Author:
alloc
Message:

Major allocation and execution time improvements on the map rendering code

Location:
binary-improvements
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • binary-improvements/7dtd-server-fixes/src/FileCache/MapTileCache.cs

    r329 r331  
    4646
    4747                                                Profiler.BeginSample ("ReadPng");
    48                                                 cacheEntry.pngData = File.ReadAllBytes (filename);
     48                                                cacheEntry.pngData = ReadAllBytes (filename);
    4949                                                Profiler.EndSample ();
    5050                                        }
     
    6363                                lock (cache) {
    6464                                        CurrentZoomFile cacheEntry = cache [zoomlevel];
    65                                        
    66                                         if (string.IsNullOrEmpty (cacheEntry.filename)) {
     65
     66                                        string file = cacheEntry.filename;
     67                                        if (string.IsNullOrEmpty (file)) {
    6768                                                return;
    6869                                        }
     
    7172
    7273                                        Profiler.BeginSample ("WritePng");
    73                                         File.WriteAllBytes (cacheEntry.filename, contentPng);
     74                                        using (Stream stream = new FileStream (file, FileMode.Create, FileAccess.ReadWrite, FileShare.None,
     75                                                4096)) {
     76                                                stream.Write (contentPng, 0, contentPng.Length);
     77                                        }
    7478                                        Profiler.EndSample ();
    7579                                }
     
    9296                                        }
    9397
    94                                         return File.ReadAllBytes (filename);
     98                                        return ReadAllBytes (filename);
    9599                                }
    96100                        } catch (Exception e) {
     
    101105                }
    102106
     107                private static byte[] ReadAllBytes (string _path) {
     108                        using (FileStream fileStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096)) {
     109                                int bytesRead = 0;
     110                                int bytesLeft = (int) fileStream.Length;
     111                                byte[] result = new byte[bytesLeft];
     112                                while (bytesLeft > 0) {
     113                                        int readThisTime = fileStream.Read (result, bytesRead, bytesLeft);
     114                                        if (readThisTime == 0) {
     115                                                throw new IOException ("Unexpected end of stream");
     116                                        }
     117
     118                                        bytesRead += readThisTime;
     119                                        bytesLeft -= readThisTime;
     120                                }
     121
     122                                return result;
     123                        }
     124                }
     125
     126
    103127                private class CurrentZoomFile {
    104128                        public string filename;
  • binary-improvements/MapRendering/API.cs

    r326 r331  
    22using AllocsFixes.NetConnections.Servers.Web.Handlers;
    33
    4 namespace MapRendering {
     4namespace AllocsFixes {
    55        public class API : IModApi {
    66                public void InitMod () {
  • binary-improvements/MapRendering/MapRendering/Constants.cs

    r325 r331  
     1using UnityEngine;
     2
    13namespace AllocsFixes.MapRendering {
    24        public class Constants {
     5                public static TextureFormat DEFAULT_TEX_FORMAT = TextureFormat.ARGB32;
    36                public static int MAP_BLOCK_SIZE = 128;
    47                public static int MAP_CHUNK_SIZE = 16;
  • binary-improvements/MapRendering/MapRendering/MapRenderBlockBuffer.cs

    r329 r331  
    88namespace AllocsFixes.MapRendering {
    99        public class MapRenderBlockBuffer {
    10                 private readonly Texture2D blockMap = new Texture2D (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE, TextureFormat.ARGB32, false);
     10                private readonly Texture2D blockMap = new Texture2D (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE, Constants.DEFAULT_TEX_FORMAT, false);
    1111                private readonly MapTileCache cache;
    12                 private readonly Color nullColor = new Color (0, 0, 0, 0);
    13                 private readonly Texture2D zoomBuffer = new Texture2D (1, 1, TextureFormat.ARGB32, false);
     12                private readonly NativeArray<int> emptyImageData;
     13                private readonly Texture2D zoomBuffer = new Texture2D (Constants.MAP_BLOCK_SIZE / 2, Constants.MAP_BLOCK_SIZE / 2, Constants.DEFAULT_TEX_FORMAT, false);
    1414                private readonly int zoomLevel;
    1515                private readonly string folderBase;
     
    2323                        this.cache = cache;
    2424                        folderBase = Constants.MAP_DIRECTORY + "/" + zoomLevel + "/";
     25
     26                        {
     27                                // Initialize empty tile data
     28                                Color nullColor = new Color (0, 0, 0, 0);
     29                                for (int x = 0; x < Constants.MAP_BLOCK_SIZE; x++) {
     30                                        for (int y = 0; y < Constants.MAP_BLOCK_SIZE; y++) {
     31                                                blockMap.SetPixel (x, y, nullColor);
     32                                        }
     33                                }
     34
     35                                NativeArray<int> blockMapData = blockMap.GetRawTextureData<int> ();
     36                                emptyImageData = new NativeArray<int> (blockMapData.Length, Allocator.Persistent,
     37                                        NativeArrayOptions.UninitializedMemory);
     38                                blockMapData.CopyTo (emptyImageData);
     39                        }
    2540                }
    2641
    2742                public TextureFormat FormatSelf {
    2843                        get { return blockMap.format; }
    29                 }
    30 
    31                 public TextureFormat FormatScaled {
    32                         get { return zoomBuffer.format; }
    3344                }
    3445
     
    4051
    4152                public void SaveBlock () {
     53                        Profiler.BeginSample ("SaveBlock");
    4254                        try {
    43                                 if (currentBlockMapFilename.Length > 0) {
    44                                         saveTextureToFile (currentBlockMapFilename);
    45                                 }
     55                                saveTextureToFile ();
    4656                        } catch (Exception e) {
    4757                                Log.Warning ("Exception in MapRenderBlockBuffer.SaveBlock(): " + e);
    4858                        }
     59                        Profiler.EndSample ();
    4960                }
    5061
    5162                public bool LoadBlock (Vector2i block) {
    52                         bool res = false;
     63                        Profiler.BeginSample ("LoadBlock");
    5364                        lock (blockMap) {
    5465                                if (currentBlockMapPos != block) {
     
    5667                                        string folder;
    5768                                        if (currentBlockMapPos.x != block.x) {
    58                                                 folder = folderBase + block.x;
     69                                                folder = folderBase + block.x + '/';
    5970
    6071                                                Profiler.BeginSample ("LoadBlock.Directory");
     
    6576                                        }
    6677
    67                                         string fileName = folder + "/" + block.y + ".png";
     78                                        string fileName = folder + block.y + ".png";
    6879                                        Profiler.EndSample ();
    6980                                       
    70                                         if (!fileName.Equals (currentBlockMapFilename)) {
    71                                                 res = true;
    72                                                 SaveBlock ();
    73                                                 loadTextureFromFile (fileName);
    74                                         }
     81                                        SaveBlock ();
     82                                        loadTextureFromFile (fileName);
    7583
    7684                                        currentBlockMapFolder = folder;
    7785                                        currentBlockMapPos = block;
    7886                                        currentBlockMapFilename = fileName;
    79                                 }
    80                         }
    81 
    82                         return res;
     87
     88                                        Profiler.EndSample ();
     89                                        return true;
     90                                }
     91                        }
     92
     93                        Profiler.EndSample ();
     94                        return false;
    8395                }
    8496
     
    147159                public NativeArray<int> GetHalfScaledNative () {
    148160                        Profiler.BeginSample ("HalfScaledNative.ResizeBuffer");
    149                         zoomBuffer.Resize (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE);
    150                         Profiler.EndSample ();
    151 
    152                         Profiler.BeginSample ("HalfScaledNative.CopyPixels");
    153                         if (blockMap.format == zoomBuffer.format) {
    154                                 Profiler.BeginSample ("Native");
    155                                 NativeArray<byte> dataSrc = blockMap.GetRawTextureData<byte> ();
    156                                 NativeArray<byte> dataZoom = zoomBuffer.GetRawTextureData<byte> ();
    157                                 dataSrc.CopyTo (dataZoom);
    158                                 Profiler.EndSample ();
    159                         } else {
    160                                 Profiler.BeginSample ("GetSetPixels");
    161                                 zoomBuffer.SetPixels32 (blockMap.GetPixels32 ());
    162                                 Profiler.EndSample ();
     161                        if (zoomBuffer.format != blockMap.format || zoomBuffer.height != Constants.MAP_BLOCK_SIZE / 2 || zoomBuffer.width != Constants.MAP_BLOCK_SIZE / 2) {
     162                                zoomBuffer.Resize (Constants.MAP_BLOCK_SIZE / 2, Constants.MAP_BLOCK_SIZE / 2, blockMap.format, false);
    163163                        }
    164164                        Profiler.EndSample ();
    165165
    166166                        Profiler.BeginSample ("HalfScaledNative.Scale");
    167                         TextureScale.Point (zoomBuffer, Constants.MAP_BLOCK_SIZE / 2, Constants.MAP_BLOCK_SIZE / 2);
     167                        ScaleNative (blockMap, zoomBuffer);
    168168                        Profiler.EndSample ();
    169169
    170170                        return zoomBuffer.GetRawTextureData<int> ();
     171                }
     172               
     173                private static void ScaleNative (Texture2D _sourceTex, Texture2D _targetTex) {
     174                        NativeArray<int> srcData = _sourceTex.GetRawTextureData<int> ();
     175                        NativeArray<int> targetData = _targetTex.GetRawTextureData<int> ();
     176                       
     177                        int oldWidth = _sourceTex.width;
     178                        int oldHeight = _sourceTex.height;
     179                        int newWidth = _targetTex.width;
     180                        int newHeight = _targetTex.height;
     181                       
     182                        float ratioX = ((float) oldWidth) / newWidth;
     183                        float ratioY = ((float) oldHeight) / newHeight;
     184
     185                        for (var y = 0; y < newHeight; y++) {
     186                                var oldLineStart = (int) (ratioY * y) * oldWidth;
     187                                var newLineStart = y * newWidth;
     188                                for (var x = 0; x < newWidth; x++) {
     189                                        targetData [newLineStart + x] = srcData [(int) (oldLineStart + ratioX * x)];
     190                                }
     191                        }
    171192                }
    172193
     
    192213                        }
    193214
    194                         if (blockMap.height != Constants.MAP_BLOCK_SIZE || blockMap.width != Constants.MAP_BLOCK_SIZE) {
    195                                 blockMap.Resize (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE, TextureFormat.ARGB32, false);
    196                         }
    197 
    198                         for (int x = 0; x < Constants.MAP_BLOCK_SIZE; x++) {
    199                                 for (int y = 0; y < Constants.MAP_BLOCK_SIZE; y++) {
    200                                         blockMap.SetPixel (x, y, nullColor);
    201                                 }
    202                         }
    203                         Profiler.EndSample ();
    204                 }
    205 
    206                 private void saveTextureToFile (string _fileName) {
    207                         Profiler.BeginSample ("SaveTexture");
    208 
     215                        if (blockMap.format != Constants.DEFAULT_TEX_FORMAT || blockMap.height != Constants.MAP_BLOCK_SIZE ||
     216                            blockMap.width != Constants.MAP_BLOCK_SIZE) {
     217                                blockMap.Resize (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE, Constants.DEFAULT_TEX_FORMAT,
     218                                        false);
     219                        }
     220
     221                        blockMap.LoadRawTextureData (emptyImageData);
     222
     223                        Profiler.EndSample ();
     224                }
     225
     226                private void saveTextureToFile () {
    209227                        Profiler.BeginSample ("EncodePNG");
    210228                        byte[] array = blockMap.EncodeToPNG ();
     
    212230
    213231                        cache.SaveTile (zoomLevel, array);
    214                         Profiler.EndSample ();
    215232                }
    216233        }
  • binary-improvements/MapRendering/MapRendering/MapRendering.cs

    r329 r331  
    246246
    247247                        Profiler.BeginSample ("RenderDirtyChunks.Work");
     248                        // Write all chunks that are in the same image tile of the highest zoom level
    248249                        Vector2i v_block, v_blockOffset;
    249250                        foreach (Vector2i v in chunksToRender) {
     
    268269                        }
    269270
     271                        // Update lower zoom levels affected by the change of the highest one
    270272                        RenderZoomLevel (block);
    271273
     
    285287
    286288                                Profiler.BeginSample ("RenderZoomLevel.Transfer");
    287                                 if ((zoomLevelBuffers [level].FormatScaled == TextureFormat.ARGB32 ||
    288                                      zoomLevelBuffers [level].FormatScaled == TextureFormat.RGBA32) &&
    289                                     zoomLevelBuffers [level].FormatScaled == zoomLevelBuffers [level - 1].FormatSelf) {
     289                                if ((zoomLevelBuffers [level].FormatSelf == TextureFormat.ARGB32 ||
     290                                     zoomLevelBuffers [level].FormatSelf == TextureFormat.RGBA32) &&
     291                                    zoomLevelBuffers [level].FormatSelf == zoomLevelBuffers [level - 1].FormatSelf) {
    290292                                        zoomLevelBuffers [level - 1].SetPartNative (blockOffset, Constants.MAP_BLOCK_SIZE / 2, zoomLevelBuffers [level].GetHalfScaledNative ());
    291293                                } else {
  • binary-improvements/MapRendering/WebAndMapRendering.csproj

    r330 r331  
    7070    <Compile Include="Commands\EnableRendering.cs" />
    7171    <Compile Include="API.cs" />
    72     <Compile Include="MapRendering\TextureScale.cs" />
    7372    <Compile Include="Web\API\GetAnimalsLocation.cs" />
    7473    <Compile Include="Web\API\GetHostileLocation.cs" />
Note: See TracChangeset for help on using the changeset viewer.