Skip to content

Commit

Permalink
[WP8] fix memory leak when Resume game
Browse files Browse the repository at this point in the history
ContentManager & ContentReaders was creating new instances during
AssetReload. The problem was with SoundEffectReader, VertexBufferReader
and generally with Shared resources like VertexBuffer, IndexBuffer,
Effect.

The problem was previously reported here:
MonoGame#1771

http://community.monogame.net/t/sharpdx-crashing-the-app-after-having-resumed-a-few-times/813/10

Tested on WP8.
  • Loading branch information
nkast committed Sep 23, 2014
1 parent 05ec4b5 commit 560221b
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 6 deletions.
32 changes: 32 additions & 0 deletions MonoGame.Framework/Content/ContentReader.cs
Expand Up @@ -44,6 +44,7 @@ public sealed class ContentReader : BinaryReader
private ContentTypeReader[] typeReaders;
internal int version;
internal int sharedResourceCount;
Dictionary<int, object> sharedResources;

internal ContentTypeReader[] TypeReaders
{
Expand Down Expand Up @@ -105,6 +106,7 @@ internal void InitializeTypeReaders()
typeReaderManager = new ContentTypeReaderManager();
typeReaders = typeReaderManager.LoadAssetReaders(this);
sharedResourceCount = Read7BitEncodedInt();
sharedResources = new Dictionary<int, object>(sharedResourceCount);
sharedResourceFixups = new List<KeyValuePair<int, Action<object>>>();
}

Expand All @@ -120,9 +122,18 @@ internal void ReadSharedResources()
if (index > 0)
{
ContentTypeReader contentReader = typeReaders[index - 1];
int resourceId = i + 1;
if (!this.sharedResources.ContainsKey(resourceId))
{
sharedResources[i] = ReadObject<object>(contentReader);
}
else
{
object existingInstance = this.sharedResources[resourceId];
sharedResources[i] = contentReader.Read(this, existingInstance);
}
}
else
{
sharedResources[i] = null;
}
Expand Down Expand Up @@ -281,6 +292,27 @@ public void ReadSharedResource<T>(Action<T> fixup)
}
}

public void ReadSharedResource<T>(Action<T> fixup, T existingInstance)
{
int index = Read7BitEncodedInt();
if (index > 0)
{
sharedResourceFixups.Add(new KeyValuePair<int, Action<object>>(index - 1, delegate(object v)
{
if (!(v is T))
{
throw new ContentLoadException(String.Format("Error loading shared resource. Expected type {0}, received type {1}", typeof(T).Name, v.GetType().Name));
}
fixup((T)v);
}));
if (existingInstance != null)
{
if (!sharedResources.ContainsKey(index))
sharedResources.Add(index, existingInstance);
}
}
}

public Vector2 ReadVector2()
{
Vector2 result = new Vector2();
Expand Down
12 changes: 9 additions & 3 deletions MonoGame.Framework/Content/ContentReaders/EffectReader.cs
Expand Up @@ -31,11 +31,17 @@ private static bool Contains(string search, string[] arr)

protected internal override Effect Read(ContentReader input, Effect existingInstance)
{
int count = input.ReadInt32();
Effect effect = existingInstance;

var effect = new Effect(input.GraphicsDevice,input.ReadBytes(count));
effect.Name = input.AssetName;
var dataCount = (int)input.ReadUInt32();
var data = input.ReadBytes(dataCount);

if (effect == null)
{
effect = new Effect(input.GraphicsDevice, data);
}

effect.Name = input.AssetName;
return effect;
}
}
Expand Down
Expand Up @@ -109,6 +109,11 @@ protected internal override SoundEffect Read(ContentReader input, SoundEffect ex
else
throw new NotSupportedException("Unsupported wave format!");

if(existingInstance!=null)
{
return existingInstance;
}

return new SoundEffect(data, 0, count, sampleRate, (AudioChannels)channels, loopStart, loopLength)
{
_format = waveFormat,
Expand Down
12 changes: 9 additions & 3 deletions MonoGame.Framework/Content/ContentReaders/VertexBufferReader.cs
Expand Up @@ -34,13 +34,19 @@ class VertexBufferReader : ContentTypeReader<VertexBuffer>
{
protected internal override VertexBuffer Read(ContentReader input, VertexBuffer existingInstance)
{
VertexBuffer vertexBuffer = existingInstance;

var declaration = input.ReadRawObject<VertexDeclaration>();
var vertexCount = (int)input.ReadUInt32();
var data = input.ReadBytes(vertexCount * declaration.VertexStride);

var buffer = new VertexBuffer( input.GraphicsDevice, declaration, vertexCount, BufferUsage.None );
buffer.SetData( data );
return buffer;
if(vertexBuffer == null)
{
vertexBuffer = new VertexBuffer(input.GraphicsDevice, declaration, vertexCount, BufferUsage.None);
}

vertexBuffer.SetData( data );
return vertexBuffer;
}
}
}

0 comments on commit 560221b

Please sign in to comment.