More progress.

Published February 16, 2010
Advertisement
Ok so I got the entire framework implemented at this point. Timing is done, creating the window is done, and displaying performance information is done.

Got some more code this time around too. I am not exactly sure if I am handling my resizing events properly here but all seems to work properly. The only issue I notice is the fact that the font seems to stretch with the screen resizing. Not to mention the font is not nearly as crisp as it seemed in DX9. If anyone knows why it is doing this feel free to chime in. Also yell at me if I am handling my resize events wrong or something. I come from a heavy C++ use background and my C# event handling is very rusty.

First the GameTimer class. This uses System.Diagnostics.Stopwatch in a way that mimics the C++ QueryPerformanceCounter.

using System;using System.Diagnostics;namespace InitDirect3D{	class GameTimer	{		private double m_SecondsPerCount;		private double m_DeltaTime;		private long m_BaseTime;		private long m_PausedTime;		private long m_StopTime;		private long m_PrevTime;		private long m_CurrTime;		private bool m_Stopped;				public GameTimer()		{			m_SecondsPerCount = 0.0;			m_DeltaTime = -1.0;			m_BaseTime = 0;			m_PausedTime = 0;			m_StopTime = 0;			m_PrevTime = 0;			m_CurrTime = 0;			m_Stopped = false;			long countsPerSecond = Stopwatch.Frequency;			m_SecondsPerCount = 1.0 / (double)countsPerSecond;		}		public float GetGameTime()		{			if (m_Stopped)			{				return (float)((m_StopTime - m_BaseTime) * m_SecondsPerCount);			}			else			{				return (float)(((m_CurrTime - m_PausedTime) - m_BaseTime) * m_SecondsPerCount);			}		}		public float GetDeltaTime()		{			return (float)m_DeltaTime;		}		public void Reset()		{			long currTime = Stopwatch.GetTimestamp();			m_BaseTime = currTime;			m_PrevTime = currTime;			m_StopTime = 0;			m_Stopped = false;		}		public void Start()		{			long startTime = Stopwatch.GetTimestamp();			if (m_Stopped)			{				m_PausedTime += (startTime - m_StopTime);				m_PrevTime = startTime;				m_StopTime = 0;				m_Stopped = false;			}		}		public void Stop()		{			if (!m_Stopped)			{				long currTime = Stopwatch.GetTimestamp();				m_StopTime = currTime;				m_Stopped = true;			}		}		public void Tick()		{			if (m_Stopped)			{				m_DeltaTime = 0.0;				return;			}			long currTime = Stopwatch.GetTimestamp();			m_CurrTime = currTime;			m_DeltaTime = (m_CurrTime - m_PrevTime) * m_SecondsPerCount;			m_PrevTime = m_CurrTime;			if (m_DeltaTime < 0.0)			{				m_DeltaTime = 0.0;			}		}	}}


Next is the D3DApp class revised with the new features. Font code added and resize code modified.

using System;using System.Drawing;using System.Windows.Forms;using SlimDX;using D3D10 = SlimDX.Direct3D10;using DXGI = SlimDX.DXGI;using SlimDX.Windows;using System.Text;namespace InitDirect3D{	class D3DApp	{		protected RenderForm m_Window;		protected D3D10.Device m_D3DDevice;		protected DXGI.SwapChain m_SwapChain;		protected D3D10.RenderTargetView m_RenderTargetView;		protected D3D10.DepthStencilView m_DepthStencilView;		protected D3D10.Texture2D m_DepthStencilBuffer;		protected D3D10.Font m_Font;		protected int m_VSync;		protected bool m_AppPaused;		protected string m_FrameStats;		protected GameTimer m_Timer;		private int frameCnt;		private float t_base;		public D3DApp()		{			m_Window = null;			m_D3DDevice = null;			m_SwapChain = null;			m_RenderTargetView = null;			m_DepthStencilView = null;			m_DepthStencilBuffer = null;			m_Font = null;			m_VSync = 0;			m_FrameStats = "";			m_AppPaused = false;			frameCnt = 0;			t_base = 0.0f;		}		~D3DApp()		{			m_RenderTargetView.Dispose();			m_DepthStencilView.Dispose();			m_DepthStencilBuffer.Dispose();			m_D3DDevice.Dispose();			m_SwapChain.Dispose();			m_Font.Dispose();		}		public void Initialize(string windowCaption)		{			m_Window = new RenderForm(windowCaption);			m_Timer = new GameTimer();			DXGI.ModeDescription modeDesc = new DXGI.ModeDescription()			{				Width = m_Window.ClientSize.Width,				Height = m_Window.ClientSize.Height,				RefreshRate = new Rational(60, 1),				Format = DXGI.Format.R8G8B8A8_UNorm,				ScanlineOrdering = DXGI.DisplayModeScanlineOrdering.Unspecified,				Scaling = DXGI.DisplayModeScaling.Unspecified			};			// Setup the SwapChain and Device			DXGI.SwapChainDescription swapDesc = new DXGI.SwapChainDescription()			{				BufferCount = 1,				ModeDescription = modeDesc,				IsWindowed = true,				OutputHandle = m_Window.Handle,				SampleDescription = new DXGI.SampleDescription(1, 0),				Usage = DXGI.Usage.RenderTargetOutput,				Flags = DXGI.SwapChainFlags.None,				SwapEffect = DXGI.SwapEffect.Discard			};			D3D10.Device.CreateWithSwapChain(null, D3D10.DriverType.Hardware, D3D10.DeviceCreationFlags.Debug, swapDesc,				out m_D3DDevice, out m_SwapChain);			OnResize();			// Disable Alt+Enter FullScreen			DXGI.Factory factory = m_SwapChain.GetParent();			factory.SetWindowAssociation(m_Window.Handle, DXGI.WindowAssociationFlags.IgnoreAll);			m_Font = new D3D10.Font(m_D3DDevice, 24, 0, D3D10.FontWeight.Normal, 1, false, D3D10.FontCharacterSet.Default, D3D10.FontPrecision.Default,				D3D10.FontQuality.Default, D3D10.FontPitchAndFamily.Default | D3D10.FontPitchAndFamily.DontCare, "Times New Roman");			m_Window.ResizeBegin += new EventHandler(m_Window_ResizeBegin);			m_Window.ResizeEnd += new EventHandler(m_Window_ResizeEnd);			m_Window.Resize += new EventHandler(m_Window_Resize);			m_Window.KeyDown += new KeyEventHandler(m_Window_KeyDown);		}		void m_Window_Resize(object sender, EventArgs e)		{			if (m_Window.WindowState == FormWindowState.Minimized)			{				m_AppPaused = true;				m_Timer.Stop();			}			else			{				m_AppPaused = false;				m_Timer.Start();				OnResize();			}		}		void m_Window_ResizeBegin(object sender, EventArgs e)		{			m_AppPaused = true;			m_Timer.Stop();		}		void m_Window_ResizeEnd(object sender, EventArgs e)		{			m_AppPaused = false;			m_Timer.Start();			OnResize();		}		void m_Window_KeyDown(object sender, KeyEventArgs e)		{			if (e.KeyCode == Keys.V)			{				if (m_VSync == 0)				{					m_VSync = 1;				}				else				{					m_VSync = 0;				}			}		}		public void Run()		{			m_Timer.Reset();			MessagePump.Run(m_Window, () =>				{					m_Timer.Tick();					if (!m_AppPaused)					{						UpdateScene(m_Timer.GetDeltaTime());					}					else					{						System.Threading.Thread.Sleep(50);					}					DrawScene();					m_SwapChain.Present(m_VSync, DXGI.PresentFlags.None);				});		}		private void OnResize()		{			if (m_RenderTargetView != null)			{				m_RenderTargetView.Dispose();			}			if (m_DepthStencilView != null)			{				m_DepthStencilView.Dispose();			}			if (m_DepthStencilBuffer != null)			{				m_DepthStencilBuffer.Dispose();			}			// Setup the RenderTargetView and DepthStencilBuffer/View			m_SwapChain.ResizeBuffers(1, m_Window.ClientSize.Width, m_Window.ClientSize.Height, DXGI.Format.R8G8B8A8_UNorm, DXGI.SwapChainFlags.None);			D3D10.Texture2D backbuffer = D3D10.Texture2D.FromSwapChain3D
10.Texture2D>(m_SwapChain, 0);
m_RenderTargetView = new D3D10.RenderTargetView(m_D3DDevice, backbuffer);
backbuffer.Dispose();

D3D10.Texture2DDescription depthStencilDesc = new D3D10.Texture2DDescription()
{
Width = m_Window.ClientSize.Width,
Height = m_Window.ClientSize.Height,
MipLevels = 1,
ArraySize = 1,
Format = DXGI.Format.D24_UNorm_S8_UInt,
SampleDescription = new DXGI.SampleDescription(1, 0),
Usage = D3D10.ResourceUsage.Default,
BindFlags = D3D10.BindFlags.DepthStencil,
CpuAccessFlags = D3D10.CpuAccessFlags.None,
OptionFlags = D3D10.ResourceOptionFlags.None
};

m_DepthStencilBuffer = new D3D10.Texture2D(m_D3DDevice, depthStencilDesc);
m_DepthStencilView = new D3D10.DepthStencilView(m_D3DDevice, m_DepthStencilBuffer);

// Bind views to pipeline
m_D3DDevice.OutputMerger.SetTargets(m_DepthStencilView, m_RenderTargetView);

// Set the viewport transform.
D3D10.Viewport vp = new D3D10.Viewport(0, 0, m_Window.ClientSize.Width, m_Window.ClientSize.Height, 0.0f, 1.0f);
m_D3DDevice.Rasterizer.SetViewports(vp);
}

public virtual void UpdateScene(float dt)
{
frameCnt++;

if ((m_Timer.GetGameTime() - t_base) >= 1.0f)
{
float fps = (float)frameCnt;
float mspf = 1000.0f / fps;

StringBuilder output = new StringBuilder();
if (m_VSync == 0)
{
output.Append("VSync: Off \n");
}
else
{
output.Append("VSync: On \n");
}

output.AppendFormat("FPS: {0} \n", fps);
output.AppendFormat("Milliseconds Per Frame: {0:0.000000}", mspf);

m_FrameStats = output.ToString();

frameCnt = 0;
t_base += 1.0f;
}
}

public virtual void DrawScene()
{
m_D3DDevice.ClearRenderTargetView(m_RenderTargetView, new Color4(1.0f, 0.0f, 0.0f, 1.0f));
m_D3DDevice.ClearDepthStencilView(m_DepthStencilView, D3D10.DepthStencilClearFlags.Depth | D3D10.DepthStencilClearFlags.Stencil, 1.0f, 0);

m_Font.Draw(null, m_FrameStats, new Rectangle(0,0,5,5), D3D10.FontDrawFlags.NoClip, 0xff000000);
}
}
}



EDIT: There is no longer a issue with the Font stretching. See comment below as to why it was happening.
0 likes 1 comments

Comments

blewisjr
Well I just fixed my issue rather quickly at that. The one where the font was stretching. When I was looking through my code for clues I noticed I was forgetting to call ResizeBuffers() on the SwapChain. Once I did that bam fixed. I Updated the above code with the fix.
February 16, 2010 03:30 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement