Show More
Commit Description:
Add timers for Simulation and various engines...
Commit Description:
Add timers for Simulation and various engines Starting to add additional timers for different stages of the process of updating in order to get more insight into what is slowing it down. The update takes 9ms, which is much longer than it used to. Engine-specific timers are coming later.
File last commit:
Show/Diff file:
Action:
FNA/src/GraphicsDeviceManager.cs
571 lines | 12.9 KiB | text/x-csharp | CSharpLexer
#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2020 Ethan Lee and the MonoGame Team
*
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
#endregion
namespace Microsoft.Xna.Framework
{
public class GraphicsDeviceManager : IGraphicsDeviceService, IDisposable, IGraphicsDeviceManager
{
#region Public Properties
public GraphicsProfile GraphicsProfile
{
get;
set;
}
public GraphicsDevice GraphicsDevice
{
get
{
return graphicsDevice;
}
}
private bool INTERNAL_isFullScreen;
public bool IsFullScreen
{
get
{
return INTERNAL_isFullScreen;
}
set
{
INTERNAL_isFullScreen = value;
prefsChanged = true;
}
}
private bool INTERNAL_preferMultiSampling;
public bool PreferMultiSampling
{
get
{
return INTERNAL_preferMultiSampling;
}
set
{
INTERNAL_preferMultiSampling = value;
prefsChanged = true;
}
}
private SurfaceFormat INTERNAL_preferredBackBufferFormat;
public SurfaceFormat PreferredBackBufferFormat
{
get
{
return INTERNAL_preferredBackBufferFormat;
}
set
{
INTERNAL_preferredBackBufferFormat = value;
prefsChanged = true;
}
}
private int INTERNAL_preferredBackBufferHeight;
public int PreferredBackBufferHeight
{
get
{
return INTERNAL_preferredBackBufferHeight;
}
set
{
INTERNAL_preferredBackBufferHeight = value;
prefsChanged = true;
}
}
private int INTERNAL_preferredBackBufferWidth;
public int PreferredBackBufferWidth
{
get
{
return INTERNAL_preferredBackBufferWidth;
}
set
{
INTERNAL_preferredBackBufferWidth = value;
prefsChanged = true;
}
}
private DepthFormat INTERNAL_preferredDepthStencilFormat;
public DepthFormat PreferredDepthStencilFormat
{
get
{
return INTERNAL_preferredDepthStencilFormat;
}
set
{
INTERNAL_preferredDepthStencilFormat = value;
prefsChanged = true;
}
}
private bool INTERNAL_synchronizeWithVerticalRetrace;
public bool SynchronizeWithVerticalRetrace
{
get
{
return INTERNAL_synchronizeWithVerticalRetrace;
}
set
{
INTERNAL_synchronizeWithVerticalRetrace = value;
prefsChanged = true;
}
}
private DisplayOrientation INTERNAL_supportedOrientations;
public DisplayOrientation SupportedOrientations
{
get
{
return INTERNAL_supportedOrientations;
}
set
{
INTERNAL_supportedOrientations = value;
prefsChanged = true;
}
}
#endregion
#region Private Variables
private Game game;
private GraphicsDevice graphicsDevice;
private bool drawBegun;
private bool disposed;
private bool prefsChanged;
private bool supportsOrientations;
private bool useResizedBackBuffer;
private int resizedBackBufferWidth;
private int resizedBackBufferHeight;
#endregion
#region Public Static Fields
public static readonly int DefaultBackBufferWidth = 800;
public static readonly int DefaultBackBufferHeight = 480;
#endregion
#region Public Events
public event EventHandler<EventArgs> Disposed;
#endregion
#region IGraphicsDeviceService Events
public event EventHandler<EventArgs> DeviceCreated;
public event EventHandler<EventArgs> DeviceDisposing;
public event EventHandler<EventArgs> DeviceReset;
public event EventHandler<EventArgs> DeviceResetting;
public event EventHandler<PreparingDeviceSettingsEventArgs> PreparingDeviceSettings;
#endregion
#region Public Constructor
public GraphicsDeviceManager(Game game)
{
if (game == null)
{
throw new ArgumentNullException("The game cannot be null!");
}
this.game = game;
INTERNAL_supportedOrientations = DisplayOrientation.Default;
INTERNAL_preferredBackBufferHeight = DefaultBackBufferHeight;
INTERNAL_preferredBackBufferWidth = DefaultBackBufferWidth;
INTERNAL_preferredBackBufferFormat = SurfaceFormat.Color;
INTERNAL_preferredDepthStencilFormat = DepthFormat.Depth24;
INTERNAL_synchronizeWithVerticalRetrace = true;
INTERNAL_preferMultiSampling = false;
if (game.Services.GetService(typeof(IGraphicsDeviceManager)) != null)
{
throw new ArgumentException("Graphics Device Manager Already Present");
}
game.Services.AddService(typeof(IGraphicsDeviceManager), this);
game.Services.AddService(typeof(IGraphicsDeviceService), this);
prefsChanged = true;
useResizedBackBuffer = false;
supportsOrientations = FNAPlatform.SupportsOrientationChanges();
game.Window.ClientSizeChanged += INTERNAL_OnClientSizeChanged;
}
#endregion
#region Deconstructor
~GraphicsDeviceManager()
{
Dispose(false);
}
#endregion
#region Dispose Methods
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (graphicsDevice != null)
{
graphicsDevice.Dispose();
graphicsDevice = null;
}
}
if (Disposed != null)
{
Disposed(this, EventArgs.Empty);
}
disposed = true;
}
}
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region Public Methods
public void ApplyChanges()
{
/* Calling ApplyChanges() before CreateDevice() forces CreateDevice.
* We can then return early since CreateDevice basically does all of
* this work for us anyway.
*
* Note that if you hit this block, it's probably because you called
* ApplyChanges in the constructor. The device created here gets
* destroyed and recreated by the game, so maybe don't do that!
*
* -flibit
*/
if (graphicsDevice == null)
{
(this as IGraphicsDeviceManager).CreateDevice();
return;
}
// ApplyChanges() calls with no actual changes should be ignored.
if (!prefsChanged && !useResizedBackBuffer)
{
return;
}
// Recreate device information before resetting
GraphicsDeviceInformation gdi = new GraphicsDeviceInformation();
gdi.Adapter = graphicsDevice.Adapter;
gdi.PresentationParameters = graphicsDevice.PresentationParameters.Clone();
INTERNAL_CreateGraphicsDeviceInformation(gdi);
// Prepare the window...
if (supportsOrientations)
{
game.Window.SetSupportedOrientations(
INTERNAL_supportedOrientations
);
}
game.Window.BeginScreenDeviceChange(
gdi.PresentationParameters.IsFullScreen
);
game.Window.EndScreenDeviceChange(
gdi.Adapter.DeviceName,
gdi.PresentationParameters.BackBufferWidth,
gdi.PresentationParameters.BackBufferHeight
);
// FIXME: Everything below should be before EndScreenDeviceChange! -flibit
// Reset!
graphicsDevice.Reset(
gdi.PresentationParameters,
gdi.Adapter
);
prefsChanged = false;
}
public void ToggleFullScreen()
{
IsFullScreen = !IsFullScreen;
ApplyChanges();
}
#endregion
#region Protected Methods
protected virtual void OnDeviceCreated(object sender, EventArgs args)
{
if (DeviceCreated != null)
{
DeviceCreated(sender, args);
}
}
protected virtual void OnDeviceDisposing(object sender, EventArgs args)
{
if (DeviceDisposing != null)
{
DeviceDisposing(sender, args);
}
}
protected virtual void OnDeviceReset(object sender, EventArgs args)
{
if (DeviceReset != null)
{
DeviceReset(sender, args);
}
}
protected virtual void OnDeviceResetting(object sender, EventArgs args)
{
if (DeviceResetting != null)
{
DeviceResetting(sender, args);
}
}
protected virtual void OnPreparingDeviceSettings(
object sender,
PreparingDeviceSettingsEventArgs args
) {
if (PreparingDeviceSettings != null)
{
PreparingDeviceSettings(sender, args);
}
}
protected virtual bool CanResetDevice(
GraphicsDeviceInformation newDeviceInfo
) {
throw new NotImplementedException();
}
protected virtual GraphicsDeviceInformation FindBestDevice(
bool anySuitableDevice
) {
throw new NotImplementedException();
}
protected virtual void RankDevices(
List<GraphicsDeviceInformation> foundDevices
) {
throw new NotImplementedException();
}
#endregion
#region Private Methods
private void INTERNAL_OnClientSizeChanged(object sender, EventArgs e)
{
Rectangle size = (sender as GameWindow).ClientBounds;
resizedBackBufferWidth = size.Width;
resizedBackBufferHeight = size.Height;
if (Environment.GetEnvironmentVariable("FNA_GRAPHICS_ENABLE_HIGHDPI") == "1")
{
resizedBackBufferWidth *= 2;
resizedBackBufferHeight *= 2;
}
useResizedBackBuffer = true;
ApplyChanges();
}
private void INTERNAL_CreateGraphicsDeviceInformation(
GraphicsDeviceInformation gdi
) {
/* Apply the GraphicsDevice changes to the new Parameters.
* Note that PreparingDeviceSettings can override any of these!
* -flibit
*/
if (useResizedBackBuffer)
{
gdi.PresentationParameters.BackBufferWidth =
resizedBackBufferWidth;
gdi.PresentationParameters.BackBufferHeight =
resizedBackBufferHeight;
useResizedBackBuffer = false;
}
else
{
if (!supportsOrientations)
{
gdi.PresentationParameters.BackBufferWidth =
PreferredBackBufferWidth;
gdi.PresentationParameters.BackBufferHeight =
PreferredBackBufferHeight;
}
else
{
/* Flip the backbuffer dimensions to scale
* appropriately to the current orientation.
*/
int min = Math.Min(PreferredBackBufferWidth, PreferredBackBufferHeight);
int max = Math.Max(PreferredBackBufferWidth, PreferredBackBufferHeight);
if (gdi.PresentationParameters.DisplayOrientation == DisplayOrientation.Portrait)
{
gdi.PresentationParameters.BackBufferWidth = min;
gdi.PresentationParameters.BackBufferHeight = max;
}
else
{
gdi.PresentationParameters.BackBufferWidth = max;
gdi.PresentationParameters.BackBufferHeight = min;
}
}
}
gdi.PresentationParameters.BackBufferFormat =
PreferredBackBufferFormat;
gdi.PresentationParameters.DepthStencilFormat =
PreferredDepthStencilFormat;
gdi.PresentationParameters.IsFullScreen =
IsFullScreen;
gdi.PresentationParameters.PresentationInterval =
SynchronizeWithVerticalRetrace ?
PresentInterval.One :
PresentInterval.Immediate;
if (!PreferMultiSampling)
{
gdi.PresentationParameters.MultiSampleCount = 0;
}
else if (gdi.PresentationParameters.MultiSampleCount == 0)
{
/* XNA4 seems to have an upper limit of 8, but I'm willing to
* limit this only in GraphicsDeviceManager's default setting.
* If you want even higher values, Reset() with a custom value.
* -flibit
*/
int maxMultiSampleCount = 0;
if (graphicsDevice != null)
{
maxMultiSampleCount = graphicsDevice.GLDevice.MaxMultiSampleCount;
}
gdi.PresentationParameters.MultiSampleCount = Math.Min(
maxMultiSampleCount,
8
);
}
gdi.GraphicsProfile = GraphicsProfile;
// Give the user a chance to override the above settings.
OnPreparingDeviceSettings(
this,
new PreparingDeviceSettingsEventArgs(gdi)
);
}
#endregion
#region IGraphicsDeviceManager Methods
void IGraphicsDeviceManager.CreateDevice()
{
// This function can recreate the device from scratch!
if (graphicsDevice != null)
{
graphicsDevice.Dispose();
graphicsDevice = null;
}
// Set the default device information
GraphicsDeviceInformation gdi = new GraphicsDeviceInformation();
gdi.Adapter = GraphicsAdapter.DefaultAdapter;
gdi.PresentationParameters = new PresentationParameters();
gdi.PresentationParameters.DeviceWindowHandle = game.Window.Handle;
INTERNAL_CreateGraphicsDeviceInformation(gdi);
// Prepare the window...
if (supportsOrientations)
{
game.Window.SetSupportedOrientations(
INTERNAL_supportedOrientations
);
}
game.Window.BeginScreenDeviceChange(
gdi.PresentationParameters.IsFullScreen
);
game.Window.EndScreenDeviceChange(
gdi.Adapter.DeviceName,
gdi.PresentationParameters.BackBufferWidth,
gdi.PresentationParameters.BackBufferHeight
);
// FIXME: Everything below should be before EndScreenDeviceChange! -flibit
// Create the GraphicsDevice, hook the callbacks
graphicsDevice = new GraphicsDevice(
gdi.Adapter,
gdi.GraphicsProfile,
gdi.PresentationParameters
);
graphicsDevice.Disposing += OnDeviceDisposing;
graphicsDevice.DeviceResetting += OnDeviceResetting;
graphicsDevice.DeviceReset += OnDeviceReset;
// Call the DeviceCreated Event
OnDeviceCreated(this, EventArgs.Empty);
}
bool IGraphicsDeviceManager.BeginDraw()
{
if (graphicsDevice == null)
{
return false;
}
graphicsDevice.GLDevice.BeginFrame();
drawBegun = true;
return true;
}
void IGraphicsDeviceManager.EndDraw()
{
if (graphicsDevice != null && drawBegun)
{
drawBegun = false;
graphicsDevice.Present();
}
}
#endregion
}
}