Hi,
Here is another issue I'm meeting with my game profiler.
As a quick reminder, my game profiler does inject two method calls to
each methods before and after the actual method body in a given
assembly to store profiled data in static fields that are also added
to the type during the build process.
everything works fine but I have a strange behavior.
Imagine the following solution:
Indiefreaks.Game.Framework Project (dll assembly)
--- Application class
------- Update virtual method
------- Draw virtual method
--- IUpdate interface
------- Update method
--- IDraw interface
------- Draw method
--- GameState class implements IUpdate & IDraw
------- IUpdate.Update method (explicit implementation)
------- Update virtual method (called by IUpdate.Update)
Commander game (exe assembly)
--- CommanderApplication class inherits from Application
------- Update method overrides Application.Update
------- Draw method overrides Application.Draw
My first problem is that when I inject my profiling code in both
assemblies, my CommanderApplication.Draw method does include the right
code (verified in Reflector):
protected override void Draw(GameTime gameTime)
{
__profilerAttribute132.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
base.Draw(gameTime);
__profilerAttribute132.ProfilingMethodEnd();
ProfilingManager.Update();
}
And here is the IL code:
.method family hidebysig virtual instance void Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime
gameTime) cil managed
{
.maxstack 8
L_0000: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
L_0005: ldarg.0
L_0006: call class [mscorlib]System.Reflection.MethodBase
[mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
L_000b: castclass [mscorlib]System.Reflection.MethodInfo
L_0010: callvirt instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodStart(object,
class [mscorlib]System.Reflection.MethodInfo)
L_0015: ldarg.0
L_0016: ldarg.1
L_0017: call instance void
[Indiefreaks.Game.Framework]Indiefreaks.Xna.Core.Application::Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_001c: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
L_0021: call instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodEnd()
L_0026: call void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilingManager::Update()
L_002b: ret
}
However, the __profilerAttribute132.ProfilingMethodEnd(); method never
gets called while ProfilingManager.Update(); does get called.
I don't understand why. Any clue?
Note that the Application.Draw class calls internally an
((IDraw)ActiveGameState).Draw(gameTime); method.
Here is the Application.Draw code (modified with my injected code):
protected override void Draw(GameTime gameTime)
{
__profilerAttribute464.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
base.GraphicsDevice.Clear(Color.Black);
if (((this._loadingGameState != null) &&
this._loadingGameState.IsLoadingComplete) && !
this._loadingGameState.ShouldRenderLoadedGameState)
{
((IDraw) this._loadingGameState).Draw(gameTime);
}
else if ((this.ActiveGameState != null) &&
this.ActiveGameState.IsLoadingComplete)
{
((IDraw) this.ActiveGameState).Draw(gameTime);
}
if ((this._transitionColor.A != 0f) || (this._transitionColor.A !=
1f))
{
this._transitionRenderer.Begin(SpriteSortMode.Immediate,
BlendState.AlphaBlend);
this._transitionRenderer.Draw(this._transitionTexture,
base.GraphicsDevice.Viewport.Bounds, this._transitionColor);
this._transitionRenderer.End();
}
base.Draw(gameTime);
__profilerAttribute464.ProfilingMethodEnd();
}
My second problem may be related to the 1st one but I'm not sure:
The CommanderApplication.Update normally calls the Application.Update
method (using base.Update()) which in turns calls the internal
((IUpdate)ActiveGameState.Update(gameTime); method.
Here is the code with the profiled injection code:
protected override void Update(GameTime gameTime)
{
__profilerAttribute463.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
if ((SunBurn.Editor != null) && SunBurn.Editor.EditorAttached)
{
Input.Enabled = false;
}
else
{
Input.Enabled = true;
}
base.Update(gameTime);
this.Threads.Update();
Interpolator.Update((float)
gameTime.ElapsedGameTime.TotalSeconds);
Timer.Update((float) gameTime.ElapsedGameTime.TotalSeconds);
if (((this.ActiveGameState != null) &&
this.ActiveGameState.IsLoadingComplete) && ((this._loadingGameState ==
null) || this._loadingGameState.ShouldRenderLoadedGameState))
{
((IUpdate) this.ActiveGameState).Update(gameTime);
}
if (((this._loadingGameState != null) &&
this._loadingGameState.IsLoadingComplete) && !
this._loadingGameState.ShouldRenderLoadedGameState)
{
((IUpdate) this._loadingGameState).Update(gameTime);
}
__profilerAttribute463.ProfilingMethodEnd();
}
What is strange is that the _profilerAttributeXXX.ProfilingEnd()
methods in CommanderApplication and Application Update methods get
called before the GameState.Update() one:
Commander.exe Information: 0 : Started Profiling
CommanderApplication.Update
Commander.exe Information: 0 : Started Profiling
Application.Update
Commander.exe Information: 0 : Ended Profiling Application.Update
Commander.exe Information: 0 : Ended Profiling
CommanderApplication.Update
Commander.exe Information: 0 : Started Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update
...
Commander.exe Information: 0 : Ended Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update
I was expecting to get the methods called this way instead (that's the
way they actually are run by the game):
Commander.exe Information: 0 : Started Profiling
CommanderApplication.Update
Commander.exe Information: 0 : Started Profiling
Application.Update
Commander.exe Information: 0 : Started Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update
...
Commander.exe Information: 0 : Ended Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update
Commander.exe Information: 0 : Ended Profiling Application.Update
Commander.exe Information: 0 : Ended Profiling
CommanderApplication.Update
I hope you can help me understand these behaviors and how I could
solve them.
Thanks
--
--
mono-cecil