Merge pull request #8103 from RoosterDragon/mapcache-better-threading

Fix graphical glitches & crashes related to map loading
This commit is contained in:
Matthias Mailänder
2015-05-20 13:11:44 +02:00

View File

@@ -11,7 +11,6 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@@ -176,34 +175,31 @@ namespace OpenRA
bitmap = Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true); bitmap = Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true);
} }
// Note: this is not generally thread-safe, but it works here because: Game.RunAfterTick(() =>
// (a) This worker is the only thread writing to this sheet
// (b) The main thread is the only thread reading this sheet
// (c) The sheet is marked dirty after the write is completed,
// which causes the main thread to copy this to the texture during
// the next render cycle.
// (d) Any partially written bytes from the next minimap is in an
// unallocated area, and will be committed in the next cycle.
try
{ {
p.SetMinimap(sheetBuilder.Add(bitmap)); try
} {
finally p.SetMinimap(sheetBuilder.Add(bitmap));
{ }
if (createdPreview) finally
bitmap.Dispose(); {
} if (createdPreview)
bitmap.Dispose();
}
});
// Yuck... But this helps the UI Jank when opening the map selector significantly. // Yuck... But this helps the UI Jank when opening the map selector significantly.
Thread.Sleep(Environment.ProcessorCount == 1 ? 25 : 5); Thread.Sleep(Environment.ProcessorCount == 1 ? 25 : 5);
} }
} }
sheetBuilder.Current.ReleaseBuffer();
// The buffer is not fully reclaimed until changes are written out to the texture. // The buffer is not fully reclaimed until changes are written out to the texture.
// We will access the texture in order to force changes to be written out, allowing the buffer to be freed. // We will access the texture in order to force changes to be written out, allowing the buffer to be freed.
Game.RunAfterTick(() => sheetBuilder.Current.GetTexture()); Game.RunAfterTick(() =>
{
sheetBuilder.Current.ReleaseBuffer();
sheetBuilder.Current.GetTexture();
});
Log.Write("debug", "MapCache.LoadAsyncInternal ended"); Log.Write("debug", "MapCache.LoadAsyncInternal ended");
} }
@@ -224,7 +220,6 @@ namespace OpenRA
if (previewLoaderThread != null) if (previewLoaderThread != null)
previewLoaderThread.Join(); previewLoaderThread.Join();
sheetBuilder.Current.CreateBuffer();
previewLoaderThread = new Thread(LoadAsyncInternal) previewLoaderThread = new Thread(LoadAsyncInternal)
{ {
Name = "Map Preview Loader", Name = "Map Preview Loader",