Ignore:
Timestamp:
Sep 5, 2018, 11:16:04 PM (6 years ago)
Author:
alloc
Message:

Some small optimizations to the map rendering stuff and added profiling instrumentation

Location:
binary-improvements/MapRendering/MapRendering
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • binary-improvements/MapRendering/MapRendering/MapRenderBlockBuffer.cs

    r326 r329  
    22using System.IO;
    33using AllocsFixes.FileCache;
     4using Unity.Collections;
    45using UnityEngine;
     6using UnityEngine.Profiling;
    57
    68namespace AllocsFixes.MapRendering {
    79        public class MapRenderBlockBuffer {
    8                 private readonly Texture2D blockMap = new Texture2D (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE);
     10                private readonly Texture2D blockMap = new Texture2D (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE, TextureFormat.ARGB32, false);
    911                private readonly MapTileCache cache;
    1012                private readonly Color nullColor = new Color (0, 0, 0, 0);
    11                 private readonly Texture2D zoomBuffer = new Texture2D (1, 1);
     13                private readonly Texture2D zoomBuffer = new Texture2D (1, 1, TextureFormat.ARGB32, false);
    1214                private readonly int zoomLevel;
    13                 private string currentBlockMap = string.Empty;
     15                private readonly string folderBase;
     16               
     17                private Vector2i currentBlockMapPos = new Vector2i (Int32.MinValue, Int32.MinValue);
     18                private string currentBlockMapFolder = string.Empty;
     19                private string currentBlockMapFilename = string.Empty;
    1420
    1521                public MapRenderBlockBuffer (int level, MapTileCache cache) {
    1622                        zoomLevel = level;
    1723                        this.cache = cache;
     24                        folderBase = Constants.MAP_DIRECTORY + "/" + zoomLevel + "/";
     25                }
     26
     27                public TextureFormat FormatSelf {
     28                        get { return blockMap.format; }
     29                }
     30
     31                public TextureFormat FormatScaled {
     32                        get { return zoomBuffer.format; }
    1833                }
    1934
    2035                public void ResetBlock () {
    21                         currentBlockMap = string.Empty;
     36                        currentBlockMapFolder = string.Empty;
     37                        currentBlockMapFilename = string.Empty;
     38                        currentBlockMapPos = new Vector2i (Int32.MinValue, Int32.MinValue);
    2239                }
    2340
    2441                public void SaveBlock () {
    2542                        try {
    26                                 if (currentBlockMap.Length > 0) {
    27                                         saveTextureToFile (currentBlockMap);
     43                                if (currentBlockMapFilename.Length > 0) {
     44                                        saveTextureToFile (currentBlockMapFilename);
    2845                                }
    2946                        } catch (Exception e) {
    30                                 Log.Out ("Exception in MapRenderBlockBuffer.SaveBlock(): " + e);
     47                                Log.Warning ("Exception in MapRenderBlockBuffer.SaveBlock(): " + e);
    3148                        }
    3249                }
     
    3552                        bool res = false;
    3653                        lock (blockMap) {
    37                                 string folder = Constants.MAP_DIRECTORY + "/" + zoomLevel + "/" + block.x;
    38                                 string fileName = folder + "/" + block.y + ".png";
    39                                 Directory.CreateDirectory (folder);
    40                                 if (!fileName.Equals (currentBlockMap)) {
    41                                         res = true;
    42                                         SaveBlock ();
    43                                         loadTextureFromFile (fileName);
    44                                 }
    45 
    46                                 currentBlockMap = fileName;
     54                                if (currentBlockMapPos != block) {
     55                                        Profiler.BeginSample ("LoadBlock.Strings");
     56                                        string folder;
     57                                        if (currentBlockMapPos.x != block.x) {
     58                                                folder = folderBase + block.x;
     59
     60                                                Profiler.BeginSample ("LoadBlock.Directory");
     61                                                Directory.CreateDirectory (folder);
     62                                                Profiler.EndSample ();
     63                                        } else {
     64                                                folder = currentBlockMapFolder;
     65                                        }
     66
     67                                        string fileName = folder + "/" + block.y + ".png";
     68                                        Profiler.EndSample ();
     69                                       
     70                                        if (!fileName.Equals (currentBlockMapFilename)) {
     71                                                res = true;
     72                                                SaveBlock ();
     73                                                loadTextureFromFile (fileName);
     74                                        }
     75
     76                                        currentBlockMapFolder = folder;
     77                                        currentBlockMapPos = block;
     78                                        currentBlockMapFilename = fileName;
     79                                }
    4780                        }
    4881
     
    5184
    5285                public void SetPart (Vector2i offset, int partSize, Color32[] pixels) {
    53                         if (offset.x + partSize > blockMap.width || offset.y + partSize > blockMap.height) {
     86                        if (offset.x + partSize > Constants.MAP_BLOCK_SIZE || offset.y + partSize > Constants.MAP_BLOCK_SIZE) {
    5487                                Log.Error (string.Format ("MapBlockBuffer[{0}].SetPart ({1}, {2}, {3}) has blockMap.size ({4}/{5})",
    55                                         zoomLevel, offset, partSize, pixels.Length, blockMap.width, blockMap.height));
     88                                        zoomLevel, offset, partSize, pixels.Length, Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE));
    5689                                return;
    5790                        }
    5891
     92                        Profiler.BeginSample ("SetPart");
    5993                        blockMap.SetPixels32 (offset.x, offset.y, partSize, partSize, pixels);
     94                        Profiler.EndSample ();
    6095                }
    6196
    6297                public Color32[] GetHalfScaled () {
     98                        Profiler.BeginSample ("HalfScaled.ResizeBuffer");
    6399                        zoomBuffer.Resize (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE);
    64                         zoomBuffer.SetPixels32 (blockMap.GetPixels32 ());
    65 
     100                        Profiler.EndSample ();
     101
     102                        Profiler.BeginSample ("HalfScaled.CopyPixels");
     103                        if (blockMap.format == zoomBuffer.format) {
     104                                Profiler.BeginSample ("Native");
     105                                NativeArray<byte> dataSrc = blockMap.GetRawTextureData<byte> ();
     106                                NativeArray<byte> dataZoom = zoomBuffer.GetRawTextureData<byte> ();
     107                                dataSrc.CopyTo (dataZoom);
     108                                Profiler.EndSample ();
     109                        } else {
     110                                Profiler.BeginSample ("GetSetPixels");
     111                                zoomBuffer.SetPixels32 (blockMap.GetPixels32 ());
     112                                Profiler.EndSample ();
     113                        }
     114                        Profiler.EndSample ();
     115
     116                        Profiler.BeginSample ("HalfScaled.Scale");
    66117                        TextureScale.Point (zoomBuffer, Constants.MAP_BLOCK_SIZE / 2, Constants.MAP_BLOCK_SIZE / 2);
    67 
    68                         return zoomBuffer.GetPixels32 ();
     118                        Profiler.EndSample ();
     119
     120                        Profiler.BeginSample ("HalfScaled.Return");
     121                        Color32[] result = zoomBuffer.GetPixels32 ();
     122                        Profiler.EndSample ();
     123
     124                        return result;
     125                }
     126
     127                public void SetPartNative (Vector2i offset, int partSize, NativeArray<int> pixels) {
     128                        if (offset.x + partSize > Constants.MAP_BLOCK_SIZE || offset.y + partSize > Constants.MAP_BLOCK_SIZE) {
     129                                Log.Error (string.Format ("MapBlockBuffer[{0}].SetPart ({1}, {2}, {3}) has blockMap.size ({4}/{5})",
     130                                        zoomLevel, offset, partSize, pixels.Length, Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE));
     131                                return;
     132                        }
     133
     134                        Profiler.BeginSample ("SetPartNative");
     135                        NativeArray<int> destData = blockMap.GetRawTextureData<int> ();
     136                       
     137                        for (int y = 0; y < partSize; y++) {
     138                                int srcLineStartIdx = partSize * y;
     139                                int destLineStartIdx = blockMap.width * (offset.y + y) + offset.x;
     140                                for (int x = 0; x < partSize; x++) {
     141                                        destData [destLineStartIdx + x] = pixels [srcLineStartIdx + x];
     142                                }
     143                        }
     144                        Profiler.EndSample ();
     145                }
     146
     147                public NativeArray<int> GetHalfScaledNative () {
     148                        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 ();
     163                        }
     164                        Profiler.EndSample ();
     165
     166                        Profiler.BeginSample ("HalfScaledNative.Scale");
     167                        TextureScale.Point (zoomBuffer, Constants.MAP_BLOCK_SIZE / 2, Constants.MAP_BLOCK_SIZE / 2);
     168                        Profiler.EndSample ();
     169
     170                        return zoomBuffer.GetRawTextureData<int> ();
    69171                }
    70172
    71173                private void loadTextureFromFile (string _fileName) {
     174                        Profiler.BeginSample ("LoadTexture");
     175
     176                        Profiler.BeginSample ("LoadFile");
    72177                        byte[] array = cache.LoadTile (zoomLevel, _fileName);
     178                        Profiler.EndSample ();
     179
     180                        Profiler.BeginSample ("LoadImage");
    73181                        if (array != null && blockMap.LoadImage (array) && blockMap.height == Constants.MAP_BLOCK_SIZE &&
    74182                            blockMap.width == Constants.MAP_BLOCK_SIZE) {
     183                                Profiler.EndSample ();
     184
     185                                Profiler.EndSample ();
    75186                                return;
    76187                        }
     188                        Profiler.EndSample ();
    77189
    78190                        if (array != null) {
     
    81193
    82194                        if (blockMap.height != Constants.MAP_BLOCK_SIZE || blockMap.width != Constants.MAP_BLOCK_SIZE) {
    83                                 blockMap.Resize (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE);
     195                                blockMap.Resize (Constants.MAP_BLOCK_SIZE, Constants.MAP_BLOCK_SIZE, TextureFormat.ARGB32, false);
    84196                        }
    85197
     
    89201                                }
    90202                        }
     203                        Profiler.EndSample ();
    91204                }
    92205
    93206                private void saveTextureToFile (string _fileName) {
     207                        Profiler.BeginSample ("SaveTexture");
     208
     209                        Profiler.BeginSample ("EncodePNG");
    94210                        byte[] array = blockMap.EncodeToPNG ();
     211                        Profiler.EndSample ();
     212
    95213                        cache.SaveTile (zoomLevel, array);
     214                        Profiler.EndSample ();
    96215                }
    97216        }
  • binary-improvements/MapRendering/MapRendering/MapRendering.cs

    r326 r329  
    99using AllocsFixes.JSON;
    1010using UnityEngine;
     11using UnityEngine.Profiling;
    1112using Object = UnityEngine.Object;
    1213
     
    6768                public static void RenderSingleChunk (Chunk chunk) {
    6869                        if (renderingEnabled) {
     70                                // TODO: Replace with regular thread and a blocking queue / set
    6971                                ThreadPool.UnsafeQueueUserWorkItem (o => {
    7072                                        try {
     
    194196                        }
    195197                }
     198               
     199                private readonly WaitForSeconds coroutineDelay = new WaitForSeconds (0.2f);
    196200
    197201                private IEnumerator renderCoroutine () {
     
    203207
    204208                                        if (Time.time > renderTimeout || dirtyChunks.Count > 200) {
     209                                                Profiler.BeginSample ("RenderDirtyChunks");
    205210                                                RenderDirtyChunks ();
    206                                         }
    207                                 }
    208 
    209                                 yield return new WaitForSeconds (0.2f);
    210                         }
    211                 }
     211                                                Profiler.EndSample ();
     212                                        }
     213                                }
     214
     215                                yield return coroutineDelay;
     216                        }
     217                }
     218
     219                private readonly List<Vector2i> chunksToRender = new List<Vector2i> ();
     220                private readonly List<Vector2i> chunksRendered = new List<Vector2i> ();
    212221
    213222                private void RenderDirtyChunks () {
     
    218227                        }
    219228
    220                         List<Vector2i> keys = new List<Vector2i> (dirtyChunks.Keys);
    221                         List<Vector2i> chunksDone = new List<Vector2i> ();
    222 
    223                         Vector2i chunkPos = keys [0];
    224                         chunksDone.Add (chunkPos);
     229                        Profiler.BeginSample ("RenderDirtyChunks.Prepare");
     230                        chunksToRender.Clear ();
     231                        chunksRendered.Clear ();
     232
     233                        dirtyChunks.CopyKeysTo (chunksToRender);
     234
     235                        Vector2i chunkPos = chunksToRender [0];
     236                        chunksRendered.Add (chunkPos);
    225237
    226238                        //Log.Out ("Start Dirty: " + chunkPos);
     
    231243
    232244                        zoomLevelBuffers [Constants.ZOOMLEVELS - 1].LoadBlock (block);
    233 
     245                        Profiler.EndSample ();
     246
     247                        Profiler.BeginSample ("RenderDirtyChunks.Work");
    234248                        Vector2i v_block, v_blockOffset;
    235                         foreach (Vector2i v in keys) {
     249                        foreach (Vector2i v in chunksToRender) {
    236250                                getBlockNumber (v, out v_block, out v_blockOffset, Constants.MAP_BLOCK_TO_CHUNK_DIV,
    237251                                        Constants.MAP_CHUNK_SIZE);
    238252                                if (v_block.Equals (block)) {
    239253                                        //Log.Out ("Dirty: " + v + " render: true");
    240                                         chunksDone.Add (v);
     254                                        chunksRendered.Add (v);
    241255                                        if (dirtyChunks [v].Length != Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE) {
    242256                                                Log.Error (string.Format ("Rendering chunk has incorrect data size of {0} instead of {1}",
     
    248262                                }
    249263                        }
    250 
    251                         foreach (Vector2i v in chunksDone) {
     264                        Profiler.EndSample ();
     265
     266                        foreach (Vector2i v in chunksRendered) {
    252267                                dirtyChunks.Remove (v);
    253268                        }
     
    255270                        RenderZoomLevel (block);
    256271
     272                        Profiler.BeginSample ("RenderDirtyChunks.SaveAll");
    257273                        SaveAllBlockMaps ();
     274                        Profiler.EndSample ();
    258275                }
    259276
    260277                private void RenderZoomLevel (Vector2i innerBlock) {
     278                        Profiler.BeginSample ("RenderZoomLevel");
    261279                        int level = Constants.ZOOMLEVELS - 1;
    262280                        while (level > 0) {
     
    265283
    266284                                zoomLevelBuffers [level - 1].LoadBlock (block);
    267                                 zoomLevelBuffers [level - 1].SetPart (blockOffset, Constants.MAP_BLOCK_SIZE / 2, zoomLevelBuffers [level].GetHalfScaled ());
    268 
    269                                 level = level - 1;
     285
     286                                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) {
     290                                        zoomLevelBuffers [level - 1].SetPartNative (blockOffset, Constants.MAP_BLOCK_SIZE / 2, zoomLevelBuffers [level].GetHalfScaledNative ());
     291                                } else {
     292                                        zoomLevelBuffers [level - 1].SetPart (blockOffset, Constants.MAP_BLOCK_SIZE / 2, zoomLevelBuffers [level].GetHalfScaled ());
     293                                }
     294                                Profiler.EndSample ();
     295
     296                                level--;
    270297                                innerBlock = block;
    271298                        }
     299                        Profiler.EndSample ();
    272300                }
    273301
     
    374402                }
    375403
    376                 private static Color shortColorToColor (ushort col) {
    377                         return new Color (((col >> 10) & 31) / 31f, ((col >> 5) & 31) / 31f, (col & 31) / 31f, 255);
    378                 }
    379 
    380404                private static Color32 shortColorToColor32 (ushort col) {
    381405                        byte r = (byte) (256 * ((col >> 10) & 31) / 32);
Note: See TracChangeset for help on using the changeset viewer.