text: //--------------------------------------------------------------------------------------
  // File: DXUT.cpp
  //
  // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  // PARTICULAR PURPOSE.
  //
  // Copyright (c) Microsoft Corporation. All rights reserved.
  //
  // http://go.microsoft.com/fwlink/?LinkId=320437
  //--------------------------------------------------------------------------------------
  #include "DXUT.h"
  
  #ifndef NDEBUG
  #include <dxgidebug.h>
  #endif
  
  #define DXUT_MIN_WINDOW_SIZE_X 200
  #define DXUT_MIN_WINDOW_SIZE_Y 200
  #define DXUT_COUNTER_STAT_LENGTH 2048
  
  
  //--------------------------------------------------------------------------------------
  // Thread safety
  //--------------------------------------------------------------------------------------
  CRITICAL_SECTION    g_cs;
  bool                g_bThreadSafe = true;
  
  
  //--------------------------------------------------------------------------------------
  // Automatically enters & leaves the CS upon object creation/deletion
  //--------------------------------------------------------------------------------------
  class DXUTLock
  {
  public:
  #pragma prefast( suppress:26166, "g_bThreadSafe controls behavior" )
  	inline _Acquires_lock_(g_cs) DXUTLock() { if (g_bThreadSafe) EnterCriticalSection(&g_cs); }
  #pragma prefast( suppress:26165, "g_bThreadSafe controls behavior" )
  	inline _Releases_lock_(g_cs) ~DXUTLock() { if (g_bThreadSafe) LeaveCriticalSection(&g_cs); }
  };
  
  //--------------------------------------------------------------------------------------
  // Helper macros to build member functions that access member variables with thread safety
  //--------------------------------------------------------------------------------------
  #define SET_ACCESSOR( x, y )       inline void Set##y( x t )   { DXUTLock l; m_state.m_##y = t; };
  #define GET_ACCESSOR( x, y )       inline x Get##y()           { DXUTLock l; return m_state.m_##y; };
  #define GET_SET_ACCESSOR( x, y )   SET_ACCESSOR( x, y ) GET_ACCESSOR( x, y )
  
  #define SETP_ACCESSOR( x, y )      inline void Set##y( x* t )  { DXUTLock l; m_state.m_##y = *t; };
  #define GETP_ACCESSOR( x, y )      inline x* Get##y()          { DXUTLock l; return &m_state.m_##y; };
  #define GETP_SETP_ACCESSOR( x, y ) SETP_ACCESSOR( x, y ) GETP_ACCESSOR( x, y )
  
  
  //--------------------------------------------------------------------------------------
  // Stores timer callback info
  //--------------------------------------------------------------------------------------
  struct DXUT_TIMER
  {
  	LPDXUTCALLBACKTIMER pCallbackTimer;
  	void* pCallbackUserContext;
  	float fTimeoutInSecs;
  	float fCountdown;
  	bool bEnabled;
  	UINT nID;
  };
  
  
  //--------------------------------------------------------------------------------------
  // Stores DXUT state and data access is done with thread safety (if g_bThreadSafe==true)
  //--------------------------------------------------------------------------------------
  class DXUTState
  {
  protected:
  	struct STATE
  	{
  		DXUTDeviceSettings*     m_CurrentDeviceSettings;   // current device settings
  		IDXGIFactory1*          m_DXGIFactory;             // DXGI Factory object
  		IDXGIAdapter1*          m_DXGIAdapter;            // The DXGI adapter object for the D3D11 device
  		IDXGIOutput**           m_DXGIOutputArray;        // The array of output obj for the D3D11 adapter obj
  		UINT                    m_DXGIOutputArraySize;    // Number of elements in m_D3D11OutputArray
  		IDXGISwapChain*         m_DXGISwapChain;          // the D3D11 swapchain
  		DXGI_SURFACE_DESC       m_BackBufferSurfaceDescDXGI; // D3D11 back buffer surface description
  		bool                    m_RenderingOccluded;       // Rendering is occluded by another window
  		bool                    m_DoNotStoreBufferSize;    // Do not store the buffer size on WM_SIZE messages
  
  		// D3D11 specific
  		ID3D11Device*           m_D3D11Device;             // the D3D11 rendering device
  		ID3D11DeviceContext*	m_D3D11DeviceContext;	   // the D3D11 immediate device context
  		D3D_FEATURE_LEVEL       m_D3D11FeatureLevel;	   // the D3D11 feature level that this device supports
  		ID3D11Texture2D*        m_D3D11DepthStencil;       // the D3D11 depth stencil texture (optional)
  		ID3D11DepthStencilView* m_D3D11DepthStencilView;   // the D3D11 depth stencil view (optional)
  		ID3D11RenderTargetView* m_D3D11RenderTargetView;   // the D3D11 render target view
  		ID3D11RasterizerState*  m_D3D11RasterizerState;    // the D3D11 Rasterizer state
  
  		// D3D11.1 specific
  		ID3D11Device1*          m_D3D11Device1;            // the D3D11.1 rendering device
  		ID3D11DeviceContext1*	m_D3D11DeviceContext1;	   // the D3D11.1 immediate device context
  
  #ifdef USE_DIRECT3D11_2
  		// D3D11.2 specific
  		ID3D11Device2*          m_D3D11Device2;            // the D3D11.2 rendering device
  		ID3D11DeviceContext2*	m_D3D11DeviceContext2;	   // the D3D11.2 immediate device context
  #endif
  
  #ifdef USE_DIRECT3D11_3
  														   // D3D11.3 specific
  		ID3D11Device3*          m_D3D11Device3;            // the D3D11.3 rendering device
  		ID3D11DeviceContext3*	m_D3D11DeviceContext3;	   // the D3D11.3 immediate device context
  #endif
  
  		// General
  		HWND  m_HWNDFocus;                  // the main app focus window
  		HWND  m_HWNDDeviceFullScreen;       // the main app device window in fullscreen mode
  		HWND  m_HWNDDeviceWindowed;         // the main app device window in windowed mode
  		HMONITOR m_AdapterMonitor;          // the monitor of the adapter 
  		HMENU m_Menu;                       // handle to menu
  
  		UINT m_FullScreenBackBufferWidthAtModeChange;  // back buffer size of fullscreen mode right before switching to windowed mode.  Used to restore to same resolution when toggling back to fullscreen
  		UINT m_FullScreenBackBufferHeightAtModeChange; // back buffer size of fullscreen mode right before switching to windowed mode.  Used to restore to same resolution when toggling back to fullscreen
  		UINT m_WindowBackBufferWidthAtModeChange;  // back buffer size of windowed mode right before switching to fullscreen mode.  Used to restore to same resolution when toggling back to windowed mode
  		UINT m_WindowBackBufferHeightAtModeChange; // back buffer size of windowed mode right before switching to fullscreen mode.  Used to restore to same resolution when toggling back to windowed mode
  		DWORD m_WindowedStyleAtModeChange;  // window style
  		WINDOWPLACEMENT m_WindowedPlacement;// record of windowed HWND position/show state/etc
  		bool  m_TopmostWhileWindowed;       // if true, the windowed HWND is topmost 
  		bool  m_Minimized;                  // if true, the HWND is minimized
  		bool  m_Maximized;                  // if true, the HWND is maximized
  		bool  m_MinimizedWhileFullscreen;   // if true, the HWND is minimized due to a focus switch away when fullscreen mode
  		bool  m_IgnoreSizeChange;           // if true, DXUT won't reset the device upon HWND size change
  		bool  m_HeadlessMode;				// if true, DXUT won't create any window or swap chain
  		bool  m_NoSwapChainPresent;			// if true, DXUT won't call swap chain present
  
  		double m_Time;                      // current time in seconds
  		double m_AbsoluteTime;              // absolute time in seconds
  		float m_ElapsedTime;                // time elapsed since last frame
  
  		HINSTANCE m_HInstance;              // handle to the app instance
  		double m_LastStatsUpdateTime;       // last time the stats were updated
  		DWORD m_LastStatsUpdateFrames;      // frames count since last time the stats were updated
  		float m_FPS;                        // frames per second
  		int   m_CurrentFrameNumber;         // the current frame number
  		HHOOK m_KeyboardHook;               // handle to keyboard hook
  		bool  m_AllowShortcutKeysWhenFullscreen; // if true, when fullscreen enable shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) 
  		bool  m_AllowShortcutKeysWhenWindowed;   // if true, when windowed enable shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) 
  		bool  m_AllowShortcutKeys;          // if true, then shortcut keys are currently disabled (Windows key, etc)
  		bool  m_CallDefWindowProc;          // if true, DXUTStaticWndProc will call DefWindowProc for unhandled messages. Applications rendering to a dialog may need to set this to false.
  		STICKYKEYS m_StartupStickyKeys;     // StickyKey settings upon startup so they can be restored later
  		TOGGLEKEYS m_StartupToggleKeys;     // ToggleKey settings upon startup so they can be restored later
  		FILTERKEYS m_StartupFilterKeys;     // FilterKey settings upon startup so they can be restored later
  
  		bool  m_HandleEscape;               // if true, then DXUT will handle escape to quit
  		bool  m_HandleAltEnter;             // if true, then DXUT will handle alt-enter to toggle fullscreen
  		bool  m_HandlePause;                // if true, then DXUT will handle pause to toggle time pausing
  		bool  m_ShowMsgBoxOnError;          // if true, then msgboxes are displayed upon errors
  		bool  m_NoStats;                    // if true, then DXUTGetFrameStats() and DXUTGetDeviceStats() will return blank strings
  		bool  m_ClipCursorWhenFullScreen;   // if true, then DXUT will keep the cursor from going outside the window when full screen
  		bool  m_ShowCursorWhenFullScreen;   // if true, then DXUT will show a cursor when full screen
  		bool  m_ConstantFrameTime;          // if true, then elapsed frame time will always be 0.05f seconds which is good for debugging or automated capture
  		float m_TimePerFrame;               // the constant time per frame in seconds, only valid if m_ConstantFrameTime==true
  		bool  m_WireframeMode;              // if true, then D3DRS_FILLMODE==D3DFILL_WIREFRAME else D3DRS_FILLMODE==D3DFILL_SOLID 
  		bool  m_AutoChangeAdapter;          // if true, then the adapter will automatically change if the window is different monitor
  		bool  m_WindowCreatedWithDefaultPositions; // if true, then CW_USEDEFAULT was used and the window should be moved to the right adapter
  		int   m_ExitCode;                   // the exit code to be returned to the command line
  
  		bool  m_DXUTInited;                 // if true, then DXUTInit() has succeeded
  		bool  m_WindowCreated;              // if true, then DXUTCreateWindow() or DXUTSetWindow() has succeeded
  		bool  m_DeviceCreated;              // if true, then DXUTCreateDevice() has succeeded
  
  		bool  m_DXUTInitCalled;             // if true, then DXUTInit() was called
  		bool  m_WindowCreateCalled;         // if true, then DXUTCreateWindow() or DXUTSetWindow() was called
  		bool  m_DeviceCreateCalled;         // if true, then DXUTCreateDevice() was called
  
  		bool  m_DeviceObjectsCreated;       // if true, then DeviceCreated callback has been called (if non-NULL)
  		bool  m_DeviceObjectsReset;         // if true, then DeviceReset callback has been called (if non-NULL)
  		bool  m_InsideDeviceCallback;       // if true, then the framework is inside an app device callback
  		bool  m_InsideMainloop;             // if true, then the framework is inside the main loop
  		bool  m_Active;                     // if true, then the app is the active top level window
  		bool  m_TimePaused;                 // if true, then time is paused
  		bool  m_RenderingPaused;            // if true, then rendering is paused
  		int   m_PauseRenderingCount;        // pause rendering ref count
  		int   m_PauseTimeCount;             // pause time ref count
  		bool  m_DeviceLost;                 // if true, then the device is lost and needs to be reset
  		bool  m_NotifyOnMouseMove;          // if true, include WM_MOUSEMOVE in mousecallback
  		bool  m_Automation;                 // if true, automation is enabled
  		bool  m_InSizeMove;                 // if true, app is inside a WM_ENTERSIZEMOVE
  		UINT  m_TimerLastID;                // last ID of the DXUT timer
  		bool  m_MessageWhenD3D11NotAvailable;
  
  		D3D_FEATURE_LEVEL  m_OverrideForceFeatureLevel; // if != -1, then overrid to use a featurelevel
  		WCHAR m_ScreenShotName[256];        // command line screen shot name
  		bool m_SaveScreenShot;              // command line save screen shot
  		bool m_ExitAfterScreenShot;         // command line exit after screen shot
  
  		int   m_OverrideAdapterOrdinal;         // if != -1, then override to use this adapter ordinal
  		bool  m_OverrideWindowed;               // if true, then force to start windowed
  		int   m_OverrideOutput;                 // if != -1, then override to use the particular output on the adapter
  		bool  m_OverrideFullScreen;             // if true, then force to start full screen
  		int   m_OverrideStartX;                 // if != -1, then override to this X position of the window
  		int   m_OverrideStartY;                 // if != -1, then override to this Y position of the window
  		int   m_OverrideWidth;                  // if != 0, then override to this width
  		int   m_OverrideHeight;                 // if != 0, then override to this height
  		bool  m_OverrideForceHAL;               // if true, then force to HAL device (failing if one doesn't exist)
  		bool  m_OverrideForceREF;               // if true, then force to REF device (failing if one doesn't exist)
  		bool  m_OverrideForceWARP;              // if true, then force to WARP device (failing if one doesn't exist)
  		bool  m_OverrideConstantFrameTime;      // if true, then force to constant frame time
  		float m_OverrideConstantTimePerFrame;   // the constant time per frame in seconds if m_OverrideConstantFrameTime==true
  		int   m_OverrideQuitAfterFrame;         // if != 0, then it will force the app to quit after that frame
  		int   m_OverrideForceVsync;             // if == 0, then it will force the app to use D3DPRESENT_INTERVAL_IMMEDIATE, if == 1 force use of D3DPRESENT_INTERVAL_DEFAULT
  		bool  m_AppCalledWasKeyPressed;         // true if the app ever calls DXUTWasKeyPressed().  Allows for optimzation
  		bool  m_ReleasingSwapChain;             // if true, the app is releasing its swapchain
  		bool  m_IsInGammaCorrectMode;           // Tell DXUTRes and DXUTMisc that we are in gamma correct mode
  
  		LPDXUTCALLBACKMODIFYDEVICESETTINGS      m_ModifyDeviceSettingsFunc;     // modify Direct3D device settings callback
  		LPDXUTCALLBACKDEVICEREMOVED             m_DeviceRemovedFunc;            // Direct3D device removed callback
  		LPDXUTCALLBACKFRAMEMOVE                 m_FrameMoveFunc;                // frame move callback
  		LPDXUTCALLBACKKEYBOARD                  m_KeyboardFunc;                 // keyboard callback
  		LPDXUTCALLBACKMOUSE                     m_MouseFunc;                    // mouse callback
  		LPDXUTCALLBACKMSGPROC                   m_WindowMsgFunc;                // window messages callback
  
  		LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE   m_IsD3D11DeviceAcceptableFunc;  // D3D11 is device acceptable callback
  		LPDXUTCALLBACKD3D11DEVICECREATED        m_D3D11DeviceCreatedFunc;       // D3D11 device created callback
  		LPDXUTCALLBACKD3D11SWAPCHAINRESIZED     m_D3D11SwapChainResizedFunc;    // D3D11 SwapChain reset callback
  		LPDXUTCALLBACKD3D11SWAPCHAINRELEASING   m_D3D11SwapChainReleasingFunc;  // D3D11 SwapChain lost callback
  		LPDXUTCALLBACKD3D11DEVICEDESTROYED      m_D3D11DeviceDestroyedFunc;     // D3D11 device destroyed callback
  		LPDXUTCALLBACKD3D11FRAMERENDER          m_D3D11FrameRenderFunc;         // D3D11 frame render callback
  
  		void* m_ModifyDeviceSettingsFuncUserContext;     // user context for modify Direct3D device settings callback
  		void* m_DeviceRemovedFuncUserContext;            // user context for Direct3D device removed callback
  		void* m_FrameMoveFuncUserContext;                // user context for frame move callback
  		void* m_KeyboardFuncUserContext;                 // user context for keyboard callback
  		void* m_MouseFuncUserContext;                    // user context for mouse callback
  		void* m_WindowMsgFuncUserContext;                // user context for window messages callback
  
  		void* m_IsD3D11DeviceAcceptableFuncUserContext;  // user context for is D3D11 device acceptable callback
  		void* m_D3D11DeviceCreatedFuncUserContext;       // user context for D3D11 device created callback
  		void* m_D3D11SwapChainResizedFuncUserContext;    // user context for D3D11 SwapChain resized callback
  		void* m_D3D11SwapChainReleasingFuncUserContext;  // user context for D3D11 SwapChain releasing callback
  		void* m_D3D11DeviceDestroyedFuncUserContext;     // user context for D3D11 device destroyed callback
  		void* m_D3D11FrameRenderFuncUserContext;         // user context for D3D11 frame render callback
  
  		bool m_Keys[256];                                // array of key state
  		bool m_LastKeys[256];                            // array of last key state
  		bool m_MouseButtons[5];                          // array of mouse states
  
  		std::vector<DXUT_TIMER>*  m_TimerList;           // list of DXUT_TIMER structs
  		WCHAR m_StaticFrameStats[256];                   // static part of frames stats 
  		WCHAR m_FPSStats[64];                            // fps stats
  		WCHAR m_FrameStats[256];                         // frame stats (fps, width, etc)
  		WCHAR m_DeviceStats[256];                        // device stats (description, device type, etc)
  		WCHAR m_WindowTitle[256];                        // window title
  	};
  
  	STATE m_state;
  
  public:
  	DXUTState() { Create(); }
  	~DXUTState() { Destroy(); }
  
  	void Create()
  	{
  		g_bThreadSafe = true;
  		(void)InitializeCriticalSectionAndSpinCount(&g_cs, 1000);
  
  		ZeroMemory(&m_state, sizeof(STATE));
  		m_state.m_OverrideStartX = -1;
  		m_state.m_OverrideStartY = -1;
  		m_state.m_OverrideForceFeatureLevel = (D3D_FEATURE_LEVEL)0;
  		m_state.m_ScreenShotName[0] = 0;
  		m_state.m_SaveScreenShot = false;
  		m_state.m_ExitAfterScreenShot = false;
  		m_state.m_OverrideAdapterOrdinal = -1;
  		m_state.m_OverrideOutput = -1;
  		m_state.m_OverrideForceVsync = -1;
  		m_state.m_AutoChangeAdapter = true;
  		m_state.m_ShowMsgBoxOnError = true;
  		m_state.m_AllowShortcutKeysWhenWindowed = true;
  		m_state.m_Active = true;
  		m_state.m_CallDefWindowProc = true;
  		m_state.m_HandleEscape = true;
  		m_state.m_HandleAltEnter = true;
  		m_state.m_HandlePause = true;
  		m_state.m_IsInGammaCorrectMode = true;
  		m_state.m_FPS = 1.0f;
  		m_state.m_MessageWhenD3D11NotAvailable = true;
  		m_state.m_HeadlessMode = false;
  		m_state.m_NoSwapChainPresent = false;
  	}
  
  	void Destroy()
  	{
  		SAFE_DELETE(m_state.m_TimerList);
  		DXUTShutdown();
  		DeleteCriticalSection(&g_cs);
  	}
  
  	// Macros to define access functions for thread safe access into m_state 
  	GET_SET_ACCESSOR(DXUTDeviceSettings*, CurrentDeviceSettings);
  
  	// D3D11 specific
  	GET_SET_ACCESSOR(IDXGIFactory1*, DXGIFactory);
  	GET_SET_ACCESSOR(IDXGIAdapter1*, DXGIAdapter);
  	GET_SET_ACCESSOR(IDXGIOutput**, DXGIOutputArray);
  	GET_SET_ACCESSOR(UINT, DXGIOutputArraySize);
  	GET_SET_ACCESSOR(IDXGISwapChain*, DXGISwapChain);
  	GETP_SETP_ACCESSOR(DXGI_SURFACE_DESC, BackBufferSurfaceDescDXGI);
  	GET_SET_ACCESSOR(bool, RenderingOccluded);
  	GET_SET_ACCESSOR(bool, DoNotStoreBufferSize);
  
  	GET_SET_ACCESSOR(ID3D11Device*, D3D11Device);
  	GET_SET_ACCESSOR(ID3D11DeviceContext*, D3D11DeviceContext);
  	GET_SET_ACCESSOR(D3D_FEATURE_LEVEL, D3D11FeatureLevel);
  	GET_SET_ACCESSOR(ID3D11Texture2D*, D3D11DepthStencil);
  	GET_SET_ACCESSOR(ID3D11DepthStencilView*, D3D11DepthStencilView);
  	GET_SET_ACCESSOR(ID3D11RenderTargetView*, D3D11RenderTargetView);
  	GET_SET_ACCESSOR(ID3D11RasterizerState*, D3D11RasterizerState);
  
  	GET_SET_ACCESSOR(ID3D11Device1*, D3D11Device1);
  	GET_SET_ACCESSOR(ID3D11DeviceContext1*, D3D11DeviceContext1);
  
  #ifdef USE_DIRECT3D11_2
  	GET_SET_ACCESSOR(ID3D11Device2*, D3D11Device2);
  	GET_SET_ACCESSOR(ID3D11DeviceContext2*, D3D11DeviceContext2);
  #endif
  
  #ifdef USE_DIRECT3D11_3
  	GET_SET_ACCESSOR(ID3D11Device3*, D3D11Device3);
  	GET_SET_ACCESSOR(ID3D11DeviceContext3*, D3D11DeviceContext3);
  #endif
  
  	GET_SET_ACCESSOR(HWND, HWNDFocus);
  	GET_SET_ACCESSOR(HWND, HWNDDeviceFullScreen);
  	GET_SET_ACCESSOR(HWND, HWNDDeviceWindowed);
  	GET_SET_ACCESSOR(HMONITOR, AdapterMonitor);
  	GET_SET_ACCESSOR(HMENU, Menu);
  
  	GET_SET_ACCESSOR(UINT, FullScreenBackBufferWidthAtModeChange);
  	GET_SET_ACCESSOR(UINT, FullScreenBackBufferHeightAtModeChange);
  	GET_SET_ACCESSOR(UINT, WindowBackBufferWidthAtModeChange);
  	GET_SET_ACCESSOR(UINT, WindowBackBufferHeightAtModeChange);
  	GETP_SETP_ACCESSOR(WINDOWPLACEMENT, WindowedPlacement);
  	GET_SET_ACCESSOR(DWORD, WindowedStyleAtModeChange);
  	GET_SET_ACCESSOR(bool, TopmostWhileWindowed);
  	GET_SET_ACCESSOR(bool, Minimized);
  	GET_SET_ACCESSOR(bool, Maximized);
  	GET_SET_ACCESSOR(bool, MinimizedWhileFullscreen);
  	GET_SET_ACCESSOR(bool, IgnoreSizeChange);
  	GET_SET_ACCESSOR(bool, HeadlessMode);
  	GET_SET_ACCESSOR(bool, NoSwapChainPresent);
  
  	GET_SET_ACCESSOR(double, Time);
  	GET_SET_ACCESSOR(double, AbsoluteTime);
  	GET_SET_ACCESSOR(float, ElapsedTime);
  
  	GET_SET_ACCESSOR(HINSTANCE, HInstance);
  	GET_SET_ACCESSOR(double, LastStatsUpdateTime);
  	GET_SET_ACCESSOR(DWORD, LastStatsUpdateFrames);
  	GET_SET_ACCESSOR(float, FPS);
  	GET_SET_ACCESSOR(int, CurrentFrameNumber);
  	GET_SET_ACCESSOR(HHOOK, KeyboardHook);
  	GET_SET_ACCESSOR(bool, AllowShortcutKeysWhenFullscreen);
  	GET_SET_ACCESSOR(bool, AllowShortcutKeysWhenWindowed);
  	GET_SET_ACCESSOR(bool, AllowShortcutKeys);
  	GET_SET_ACCESSOR(bool, CallDefWindowProc);
  	GET_SET_ACCESSOR(STICKYKEYS, StartupStickyKeys);
  	GET_SET_ACCESSOR(TOGGLEKEYS, StartupToggleKeys);
  	GET_SET_ACCESSOR(FILTERKEYS, StartupFilterKeys);
  
  	GET_SET_ACCESSOR(bool, HandleEscape);
  	GET_SET_ACCESSOR(bool, HandleAltEnter);
  	GET_SET_ACCESSOR(bool, HandlePause);
  	GET_SET_ACCESSOR(bool, ShowMsgBoxOnError);
  	GET_SET_ACCESSOR(bool, NoStats);
  	GET_SET_ACCESSOR(bool, ClipCursorWhenFullScreen);
  	GET_SET_ACCESSOR(bool, ShowCursorWhenFullScreen);
  	GET_SET_ACCESSOR(bool, ConstantFrameTime);
  	GET_SET_ACCESSOR(float, TimePerFrame);
  	GET_SET_ACCESSOR(bool, WireframeMode);
  	GET_SET_ACCESSOR(bool, AutoChangeAdapter);
  	GET_SET_ACCESSOR(bool, WindowCreatedWithDefaultPositions);
  	GET_SET_ACCESSOR(int, ExitCode);
  
  	GET_SET_ACCESSOR(bool, DXUTInited);
  	GET_SET_ACCESSOR(bool, WindowCreated);
  	GET_SET_ACCESSOR(bool, DeviceCreated);
  	GET_SET_ACCESSOR(bool, DXUTInitCalled);
  	GET_SET_ACCESSOR(bool, WindowCreateCalled);
  	GET_SET_ACCESSOR(bool, DeviceCreateCalled);
  	GET_SET_ACCESSOR(bool, InsideDeviceCallback);
  	GET_SET_ACCESSOR(bool, InsideMainloop);
  	GET_SET_ACCESSOR(bool, DeviceObjectsCreated);
  	GET_SET_ACCESSOR(bool, DeviceObjectsReset);
  	GET_SET_ACCESSOR(bool, Active);
  	GET_SET_ACCESSOR(bool, RenderingPaused);
  	GET_SET_ACCESSOR(bool, TimePaused);
  	GET_SET_ACCESSOR(int, PauseRenderingCount);
  	GET_SET_ACCESSOR(int, PauseTimeCount);
  	GET_SET_ACCESSOR(bool, DeviceLost);
  	GET_SET_ACCESSOR(bool, NotifyOnMouseMove);
  	GET_SET_ACCESSOR(bool, Automation);
  	GET_SET_ACCESSOR(bool, InSizeMove);
  	GET_SET_ACCESSOR(UINT, TimerLastID);
  	GET_SET_ACCESSOR(bool, MessageWhenD3D11NotAvailable);
  	GET_SET_ACCESSOR(bool, AppCalledWasKeyPressed);
  
  	GET_SET_ACCESSOR(D3D_FEATURE_LEVEL, OverrideForceFeatureLevel);
  	GET_ACCESSOR(WCHAR*, ScreenShotName);
  	GET_SET_ACCESSOR(bool, SaveScreenShot);
  	GET_SET_ACCESSOR(bool, ExitAfterScreenShot);
  
  	GET_SET_ACCESSOR(int, OverrideAdapterOrdinal);
  	GET_SET_ACCESSOR(bool, OverrideWindowed);
  	GET_SET_ACCESSOR(int, OverrideOutput);
  	GET_SET_ACCESSOR(bool, OverrideFullScreen);
  	GET_SET_ACCESSOR(int, OverrideStartX);
  	GET_SET_ACCESSOR(int, OverrideStartY);
  	GET_SET_ACCESSOR(int, OverrideWidth);
  	GET_SET_ACCESSOR(int, OverrideHeight);
  	GET_SET_ACCESSOR(bool, OverrideForceHAL);
  	GET_SET_ACCESSOR(bool, OverrideForceREF);
  	GET_SET_ACCESSOR(bool, OverrideForceWARP);
  	GET_SET_ACCESSOR(bool, OverrideConstantFrameTime);
  	GET_SET_ACCESSOR(float, OverrideConstantTimePerFrame);
  	GET_SET_ACCESSOR(int, OverrideQuitAfterFrame);
  	GET_SET_ACCESSOR(int, OverrideForceVsync);
  	GET_SET_ACCESSOR(bool, ReleasingSwapChain);
  	GET_SET_ACCESSOR(bool, IsInGammaCorrectMode);
  
  	GET_SET_ACCESSOR(LPDXUTCALLBACKMODIFYDEVICESETTINGS, ModifyDeviceSettingsFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKDEVICEREMOVED, DeviceRemovedFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKFRAMEMOVE, FrameMoveFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKKEYBOARD, KeyboardFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKMOUSE, MouseFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKMSGPROC, WindowMsgFunc);
  
  	GET_SET_ACCESSOR(LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE, IsD3D11DeviceAcceptableFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKD3D11DEVICECREATED, D3D11DeviceCreatedFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKD3D11SWAPCHAINRESIZED, D3D11SwapChainResizedFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKD3D11SWAPCHAINRELEASING, D3D11SwapChainReleasingFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKD3D11DEVICEDESTROYED, D3D11DeviceDestroyedFunc);
  	GET_SET_ACCESSOR(LPDXUTCALLBACKD3D11FRAMERENDER, D3D11FrameRenderFunc);
  
  	GET_SET_ACCESSOR(void*, ModifyDeviceSettingsFuncUserContext);
  	GET_SET_ACCESSOR(void*, DeviceRemovedFuncUserContext);
  	GET_SET_ACCESSOR(void*, FrameMoveFuncUserContext);
  	GET_SET_ACCESSOR(void*, KeyboardFuncUserContext);
  	GET_SET_ACCESSOR(void*, MouseFuncUserContext);
  	GET_SET_ACCESSOR(void*, WindowMsgFuncUserContext);
  
  	GET_SET_ACCESSOR(void*, IsD3D11DeviceAcceptableFuncUserContext);
  	GET_SET_ACCESSOR(void*, D3D11DeviceCreatedFuncUserContext);
  	GET_SET_ACCESSOR(void*, D3D11DeviceDestroyedFuncUserContext);
  	GET_SET_ACCESSOR(void*, D3D11SwapChainResizedFuncUserContext);
  	GET_SET_ACCESSOR(void*, D3D11SwapChainReleasingFuncUserContext);
  	GET_SET_ACCESSOR(void*, D3D11FrameRenderFuncUserContext);
  
  	GET_SET_ACCESSOR(std::vector<DXUT_TIMER>*, TimerList);
  	GET_ACCESSOR(bool*, Keys);
  	GET_ACCESSOR(bool*, LastKeys);
  	GET_ACCESSOR(bool*, MouseButtons);
  	GET_ACCESSOR(WCHAR*, StaticFrameStats);
  	GET_ACCESSOR(WCHAR*, FPSStats);
  	GET_ACCESSOR(WCHAR*, FrameStats);
  	GET_ACCESSOR(WCHAR*, DeviceStats);
  	GET_ACCESSOR(WCHAR*, WindowTitle);
  };
  
  
  //--------------------------------------------------------------------------------------
  // Global state 
  //--------------------------------------------------------------------------------------
  DXUTState*          g_pDXUTState = nullptr;
  
  HRESULT WINAPI DXUTCreateState()
  {
  	if (!g_pDXUTState)
  	{
  		g_pDXUTState = new (std::nothrow) DXUTState;
  		if (!g_pDXUTState)
  			return E_OUTOFMEMORY;
  	}
  	return S_OK;
  }
  
  void WINAPI DXUTDestroyState()
  {
  	SAFE_DELETE(g_pDXUTState);
  }
  
  class DXUTMemoryHelper
  {
  public:
  	DXUTMemoryHelper() { DXUTCreateState(); }
  	~DXUTMemoryHelper() { DXUTDestroyState(); }
  };
  
  DXUTState& GetDXUTState()
  {
  	// This class will auto create the memory when its first accessed and delete it after the program exits WinMain.
  	// However the application can also call DXUTCreateState() & DXUTDestroyState() independantly if its wants 
  	static DXUTMemoryHelper memory;
  	assert(g_pDXUTState);
  	_Analysis_assume_(g_pDXUTState);
  	return *g_pDXUTState;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Internal functions forward declarations
  //--------------------------------------------------------------------------------------
  void DXUTParseCommandLine(_In_z_ WCHAR* strCommandLine,
  	_In_ bool bIgnoreFirstCommand = true);
  bool DXUTIsNextArg(_Inout_ WCHAR*& strCmdLine, _In_ const WCHAR* strArg);
  bool DXUTGetCmdParam(_Inout_ WCHAR*& strCmdLine, _Out_cap_(cchDest) WCHAR* strFlag, _In_ int cchDest);
  void DXUTAllowShortcutKeys(_In_ bool bAllowKeys);
  void DXUTUpdateStaticFrameStats();
  void DXUTUpdateFrameStats();
  
  LRESULT CALLBACK DXUTStaticWndProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
  void DXUTHandleTimers();
  void DXUTDisplayErrorMessage(_In_ HRESULT hr);
  int DXUTMapButtonToArrayIndex(_In_ BYTE vButton);
  
  HRESULT DXUTChangeDevice(_In_ DXUTDeviceSettings* pNewDeviceSettings,
  	_In_ bool bClipWindowToSingleAdapter);
  
  bool DXUTCanDeviceBeReset(_In_ DXUTDeviceSettings* pOldDeviceSettings,
  	_In_ DXUTDeviceSettings* pNewDeviceSettings,
  	_In_ ID3D11Device* pd3d11DeviceFromApp);
  
  
  HRESULT DXUTDelayLoadDXGI();
  HRESULT DXUTSnapDeviceSettingsToEnumDevice(_In_ DXUTDeviceSettings* pDeviceSettings, _In_ bool forceEnum, _In_ D3D_FEATURE_LEVEL forceFL = D3D_FEATURE_LEVEL(0));
  void DXUTUpdateDeviceSettingsWithOverrides(_Inout_ DXUTDeviceSettings* pDeviceSettings);
  void DXUTCheckForDXGIFullScreenSwitch();
  void DXUTResizeDXGIBuffers(_In_ UINT Width, _In_ UINT Height, _In_ BOOL bFullscreen);
  void DXUTCheckForDXGIBufferChange();
  void DXUTCheckForWindowSizeChange();
  void DXUTCheckForWindowChangingMonitors();
  void DXUTCleanup3DEnvironment(_In_ bool bReleaseSettings);
  HMONITOR DXUTGetMonitorFromAdapter(_In_ DXUTDeviceSettings* pDeviceSettings);
  HRESULT DXUTGetAdapterOrdinalFromMonitor(_In_ HMONITOR hMonitor, _Out_ UINT* pAdapterOrdinal);
  HRESULT DXUTGetOutputOrdinalFromMonitor(_In_ HMONITOR hMonitor, _Out_ UINT* pOutputOrdinal);
  HRESULT DXUTHandleDeviceRemoved();
  void DXUTUpdateBackBufferDesc();
  void DXUTSetupCursor();
  
  // Direct3D 11
  HRESULT DXUTCreateD3D11Views(_In_ ID3D11Device* pd3dDevice, _In_ ID3D11DeviceContext* pd3dDeviceContext, _In_ DXUTDeviceSettings* pDeviceSettings);
  HRESULT DXUTCreate3DEnvironment11();
  HRESULT DXUTReset3DEnvironment11();
  void DXUTUpdateD3D11DeviceStats(_In_ D3D_DRIVER_TYPE DeviceType, _In_ D3D_FEATURE_LEVEL featureLevel, _In_ DXGI_ADAPTER_DESC* pAdapterDesc);
  
  
  //--------------------------------------------------------------------------------------
  // Internal helper functions 
  //--------------------------------------------------------------------------------------
  UINT DXUTGetBackBufferWidthFromDS(_In_ DXUTDeviceSettings* pNewDeviceSettings)
  {
  	return pNewDeviceSettings->d3d11.sd.BufferDesc.Width;
  }
  UINT DXUTGetBackBufferHeightFromDS(_In_ DXUTDeviceSettings* pNewDeviceSettings)
  {
  	return pNewDeviceSettings->d3d11.sd.BufferDesc.Height;
  }
  bool DXUTGetIsWindowedFromDS(_In_ DXUTDeviceSettings* pNewDeviceSettings)
  {
  	if (!pNewDeviceSettings)
  		return true;
  
  	return pNewDeviceSettings->d3d11.sd.Windowed ? true : false;
  }
  
  
  //--------------------------------------------------------------------------------------
  // External state access functions
  //--------------------------------------------------------------------------------------
  bool WINAPI DXUTGetMSAASwapChainCreated()
  {
  	DXUTDeviceSettings *psettings = GetDXUTState().GetCurrentDeviceSettings();
  	if (!psettings)
  		return false;
  	return (psettings->d3d11.sd.SampleDesc.Count > 1);
  }
  D3D_FEATURE_LEVEL WINAPI DXUTGetD3D11DeviceFeatureLevel() { return GetDXUTState().GetD3D11FeatureLevel(); }
  IDXGISwapChain* WINAPI DXUTGetDXGISwapChain() { return GetDXUTState().GetDXGISwapChain(); }
  ID3D11RenderTargetView* WINAPI DXUTGetD3D11RenderTargetView() { return GetDXUTState().GetD3D11RenderTargetView(); }
  ID3D11DepthStencilView* WINAPI DXUTGetD3D11DepthStencilView() { return GetDXUTState().GetD3D11DepthStencilView(); }
  const DXGI_SURFACE_DESC* WINAPI DXUTGetDXGIBackBufferSurfaceDesc() { return GetDXUTState().GetBackBufferSurfaceDescDXGI(); }
  HINSTANCE WINAPI DXUTGetHINSTANCE() { return GetDXUTState().GetHInstance(); }
  HWND WINAPI DXUTGetHWND() { return DXUTIsWindowed() ? GetDXUTState().GetHWNDDeviceWindowed() : GetDXUTState().GetHWNDDeviceFullScreen(); }
  HWND WINAPI DXUTGetHWNDFocus() { return GetDXUTState().GetHWNDFocus(); }
  HWND WINAPI DXUTGetHWNDDeviceFullScreen() { return GetDXUTState().GetHWNDDeviceFullScreen(); }
  HWND WINAPI DXUTGetHWNDDeviceWindowed() { return GetDXUTState().GetHWNDDeviceWindowed(); }
  RECT WINAPI DXUTGetWindowClientRect() { RECT rc; GetClientRect(DXUTGetHWND(), &rc); return rc; }
  LONG WINAPI DXUTGetWindowWidth() { RECT rc = DXUTGetWindowClientRect(); return ((LONG)rc.right - rc.left); }
  LONG WINAPI DXUTGetWindowHeight() { RECT rc = DXUTGetWindowClientRect(); return ((LONG)rc.bottom - rc.top); }
  RECT WINAPI DXUTGetWindowClientRectAtModeChange() { RECT rc = { 0, 0, static_cast<LONG>(GetDXUTState().GetWindowBackBufferWidthAtModeChange()), static_cast<LONG>(GetDXUTState().GetWindowBackBufferHeightAtModeChange()) }; return rc; }
  RECT WINAPI DXUTGetFullsceenClientRectAtModeChange() { RECT rc = { 0, 0, static_cast<LONG>(GetDXUTState().GetFullScreenBackBufferWidthAtModeChange()), static_cast<LONG>(GetDXUTState().GetFullScreenBackBufferHeightAtModeChange()) }; return rc; }
  double WINAPI DXUTGetTime() { return GetDXUTState().GetTime(); }
  float WINAPI DXUTGetElapsedTime() { return GetDXUTState().GetElapsedTime(); }
  float WINAPI DXUTGetFPS() { return GetDXUTState().GetFPS(); }
  LPCWSTR WINAPI DXUTGetWindowTitle() { return GetDXUTState().GetWindowTitle(); }
  LPCWSTR WINAPI DXUTGetDeviceStats() { return GetDXUTState().GetDeviceStats(); }
  bool WINAPI DXUTIsRenderingPaused() { return GetDXUTState().GetPauseRenderingCount() > 0; }
  bool WINAPI DXUTIsTimePaused() { return GetDXUTState().GetPauseTimeCount() > 0; }
  bool WINAPI DXUTIsActive() { return GetDXUTState().GetActive(); }
  int WINAPI DXUTGetExitCode() { return GetDXUTState().GetExitCode(); }
  bool WINAPI DXUTGetShowMsgBoxOnError() { return GetDXUTState().GetShowMsgBoxOnError(); }
  bool WINAPI DXUTGetAutomation() { return GetDXUTState().GetAutomation(); }
  bool WINAPI DXUTIsWindowed() { return DXUTGetIsWindowedFromDS(GetDXUTState().GetCurrentDeviceSettings()); }
  bool WINAPI DXUTIsInGammaCorrectMode() { return GetDXUTState().GetIsInGammaCorrectMode(); }
  bool WINAPI DXUTIsHeadlessMode() { return GetDXUTState().GetHeadlessMode(); }
  bool WINAPI DXUTNoSwapChainPresent() { return GetDXUTState().GetNoSwapChainPresent(); }
  IDXGIFactory1* WINAPI DXUTGetDXGIFactory() { DXUTDelayLoadDXGI(); return GetDXUTState().GetDXGIFactory(); }
  
  ID3D11Device* WINAPI DXUTGetD3D11Device() { return GetDXUTState().GetD3D11Device(); }
  ID3D11DeviceContext* WINAPI DXUTGetD3D11DeviceContext() { return GetDXUTState().GetD3D11DeviceContext(); }
  ID3D11Device1* WINAPI DXUTGetD3D11Device1() { return GetDXUTState().GetD3D11Device1(); }
  ID3D11DeviceContext1* WINAPI DXUTGetD3D11DeviceContext1() { return GetDXUTState().GetD3D11DeviceContext1(); }
  
  #ifdef USE_DIRECT3D11_2
  ID3D11Device2* WINAPI DXUTGetD3D11Device2() { return GetDXUTState().GetD3D11Device2(); }
  ID3D11DeviceContext2* WINAPI DXUTGetD3D11DeviceContext2() { return GetDXUTState().GetD3D11DeviceContext2(); }
  #endif
  
  #ifdef USE_DIRECT3D11_3
  ID3D11Device3* WINAPI DXUTGetD3D11Device3() { return GetDXUTState().GetD3D11Device3(); }
  ID3D11DeviceContext3* WINAPI DXUTGetD3D11DeviceContext3() { return GetDXUTState().GetD3D11DeviceContext3(); }
  #endif
  
  //--------------------------------------------------------------------------------------
  // External callback setup functions
  //--------------------------------------------------------------------------------------
  
  // General callbacks
  void WINAPI DXUTSetCallbackDeviceChanging(_In_ LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetModifyDeviceSettingsFunc(pCallback); GetDXUTState().SetModifyDeviceSettingsFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackDeviceRemoved(_In_ LPDXUTCALLBACKDEVICEREMOVED pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetDeviceRemovedFunc(pCallback); GetDXUTState().SetDeviceRemovedFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackFrameMove(_In_ LPDXUTCALLBACKFRAMEMOVE pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetFrameMoveFunc(pCallback);  GetDXUTState().SetFrameMoveFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackKeyboard(_In_ LPDXUTCALLBACKKEYBOARD pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetKeyboardFunc(pCallback);  GetDXUTState().SetKeyboardFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackMouse(_In_ LPDXUTCALLBACKMOUSE pCallback, bool bIncludeMouseMove, _In_opt_ void* pUserContext) { GetDXUTState().SetMouseFunc(pCallback); GetDXUTState().SetNotifyOnMouseMove(bIncludeMouseMove);  GetDXUTState().SetMouseFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackMsgProc(_In_ LPDXUTCALLBACKMSGPROC pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetWindowMsgFunc(pCallback);  GetDXUTState().SetWindowMsgFuncUserContext(pUserContext); }
  
  // Direct3D 11 callbacks
  void WINAPI DXUTSetCallbackD3D11DeviceAcceptable(_In_ LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetIsD3D11DeviceAcceptableFunc(pCallback); GetDXUTState().SetIsD3D11DeviceAcceptableFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackD3D11DeviceCreated(_In_ LPDXUTCALLBACKD3D11DEVICECREATED pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetD3D11DeviceCreatedFunc(pCallback); GetDXUTState().SetD3D11DeviceCreatedFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackD3D11SwapChainResized(_In_ LPDXUTCALLBACKD3D11SWAPCHAINRESIZED pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetD3D11SwapChainResizedFunc(pCallback);  GetDXUTState().SetD3D11SwapChainResizedFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackD3D11FrameRender(_In_ LPDXUTCALLBACKD3D11FRAMERENDER pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetD3D11FrameRenderFunc(pCallback);  GetDXUTState().SetD3D11FrameRenderFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackD3D11SwapChainReleasing(_In_ LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetD3D11SwapChainReleasingFunc(pCallback);  GetDXUTState().SetD3D11SwapChainReleasingFuncUserContext(pUserContext); }
  void WINAPI DXUTSetCallbackD3D11DeviceDestroyed(_In_ LPDXUTCALLBACKD3D11DEVICEDESTROYED pCallback, _In_opt_ void* pUserContext) { GetDXUTState().SetD3D11DeviceDestroyedFunc(pCallback);  GetDXUTState().SetD3D11DeviceDestroyedFuncUserContext(pUserContext); }
  void DXUTGetCallbackD3D11DeviceAcceptable(_In_ LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE* ppCallback, _Outptr_ void** ppUserContext) { *ppCallback = GetDXUTState().GetIsD3D11DeviceAcceptableFunc(); *ppUserContext = GetDXUTState().GetIsD3D11DeviceAcceptableFuncUserContext(); }
  
  
  //--------------------------------------------------------------------------------------
  // Optionally parses the command line and sets if default hotkeys are handled
  //
  //       Possible command line parameters are:
  //          -forcefeaturelevel:fl     forces app to use a specified direct3D11 feature level    
  //          -screenshotexit:filename save a screenshot to the filename.bmp and exit.
  //          -adapter:#              forces app to use this adapter # (fails if the adapter doesn't exist)
  //          -output:#               forces app to use a particular output on the adapter (fails if the output doesn't exist) 
  //          -windowed               forces app to start windowed
  //          -fullscreen             forces app to start full screen
  //          -forcehal               forces app to use HAL (fails if HAL doesn't exist)
  //          -forceref               forces app to use REF (fails if REF doesn't exist)
  //          -forcewarp              forces app to use WARP (fails if WARP doesn't exist)
  //          -forcevsync:#           if # is 0, then vsync is disabled 
  //          -width:#                forces app to use # for width. for full screen, it will pick the closest possible supported mode
  //          -height:#               forces app to use # for height. for full screen, it will pick the closest possible supported mode
  //          -startx:#               forces app to use # for the x coord of the window position for windowed mode
  //          -starty:#               forces app to use # for the y coord of the window position for windowed mode
  //          -constantframetime:#    forces app to use constant frame time, where # is the time/frame in seconds
  //          -quitafterframe:x       forces app to quit after # frames
  //          -noerrormsgboxes        prevents the display of message boxes generated by the framework so the application can be run without user interaction
  //          -nostats                prevents the display of the stats
  //          -automation             a hint to other components that automation is active 
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT WINAPI DXUTInit(bool bParseCommandLine,
  	bool bShowMsgBoxOnError,
  	WCHAR* strExtraCommandLineParams,
  	bool bThreadSafeDXUT)
  {
  	g_bThreadSafe = bThreadSafeDXUT;
  
  	HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
  	if (FAILED(hr))
  		return hr;
  
  	GetDXUTState().SetDXUTInitCalled(true);
  
  	// Not always needed, but lets the app create GDI dialogs
  	InitCommonControls();
  
  	// Save the current sticky/toggle/filter key settings so DXUT can restore them later
  	STICKYKEYS sk = { sizeof(STICKYKEYS), 0 };
  	if (!SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &sk, 0))
  		memset(&sk, 0, sizeof(sk));
  	GetDXUTState().SetStartupStickyKeys(sk);
  
  	TOGGLEKEYS tk = { sizeof(TOGGLEKEYS), 0 };
  	if (!SystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tk, 0))
  		memset(&tk, 0, sizeof(tk));
  	GetDXUTState().SetStartupToggleKeys(tk);
  
  	FILTERKEYS fk = { sizeof(FILTERKEYS), 0 };
  	if (!SystemParametersInfo(SPI_GETFILTERKEYS, sizeof(FILTERKEYS), &fk, 0))
  		memset(&fk, 0, sizeof(fk));
  	GetDXUTState().SetStartupFilterKeys(fk);
  
  	GetDXUTState().SetShowMsgBoxOnError(bShowMsgBoxOnError);
  
  	if (bParseCommandLine)
  		DXUTParseCommandLine(GetCommandLine());
  	if (strExtraCommandLineParams)
  		DXUTParseCommandLine(strExtraCommandLineParams, false);
  
  	// Reset the timer
  	DXUTGetGlobalTimer()->Reset();
  
  	GetDXUTState().SetDXUTInited(true);
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Parses the command line for parameters.  See DXUTInit() for list 
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  void DXUTParseCommandLine(WCHAR* strCommandLine,
  	bool bIgnoreFirstCommand)
  {
  	WCHAR* strCmdLine;
  	WCHAR strFlag[MAX_PATH];
  
  	int nNumArgs;
  	auto pstrArgList = CommandLineToArgvW(strCommandLine, &nNumArgs);
  	int iArgStart = 0;
  	if (bIgnoreFirstCommand)
  		iArgStart = 1;
  	for (int iArg = iArgStart; iArg < nNumArgs; iArg++)
  	{
  		strCmdLine = pstrArgList[iArg];
  
  		// Handle flag args
  		if (*strCmdLine == L'/' || *strCmdLine == L'-')
  		{
  			strCmdLine++;
  
  			if (DXUTIsNextArg(strCmdLine, L"forcefeaturelevel"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  #ifdef USE_DIRECT3D11_3
  					if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_12_1", MAX_PATH) == 0) {
  						GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_12_1);
  					}
  					else if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_12_0", MAX_PATH) == 0) {
  						GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_12_0);
  					}
  					else
  #endif
  						if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_11_1", MAX_PATH) == 0) {
  							GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_11_1);
  						}
  						else if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_11_0", MAX_PATH) == 0) {
  							GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_11_0);
  						}
  						else if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_10_1", MAX_PATH) == 0) {
  							GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_10_1);
  						}
  						else if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_10_0", MAX_PATH) == 0) {
  							GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_10_0);
  						}
  						else if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_9_3", MAX_PATH) == 0) {
  							GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_9_3);
  						}
  						else if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_9_2", MAX_PATH) == 0) {
  							GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_9_2);
  						}
  						else if (_wcsnicmp(strFlag, L"D3D_FEATURE_LEVEL_9_1", MAX_PATH) == 0) {
  							GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_9_1);
  						}
  						continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"adapter"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int nAdapter = _wtoi(strFlag);
  					GetDXUTState().SetOverrideAdapterOrdinal(nAdapter);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"windowed"))
  			{
  				GetDXUTState().SetOverrideWindowed(true);
  				continue;
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"output"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int Output = _wtoi(strFlag);
  					GetDXUTState().SetOverrideOutput(Output);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"fullscreen"))
  			{
  				GetDXUTState().SetOverrideFullScreen(true);
  				continue;
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"forcehal"))
  			{
  				GetDXUTState().SetOverrideForceHAL(true);
  				continue;
  			}
  			if (DXUTIsNextArg(strCmdLine, L"screenshotexit")) {
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					GetDXUTState().SetExitAfterScreenShot(true);
  					GetDXUTState().SetSaveScreenShot(true);
  					swprintf_s(GetDXUTState().GetScreenShotName(), 256, L"%ls.bmp", strFlag);
  					continue;
  				}
  			}
  			if (DXUTIsNextArg(strCmdLine, L"forceref"))
  			{
  				GetDXUTState().SetOverrideForceREF(true);
  				continue;
  			}
  			if (DXUTIsNextArg(strCmdLine, L"forcewarp"))
  			{
  				GetDXUTState().SetOverrideForceWARP(true);
  				continue;
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"forcevsync"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int nOn = _wtoi(strFlag);
  					GetDXUTState().SetOverrideForceVsync(nOn);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"width"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int nWidth = _wtoi(strFlag);
  					GetDXUTState().SetOverrideWidth(nWidth);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"height"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int nHeight = _wtoi(strFlag);
  					GetDXUTState().SetOverrideHeight(nHeight);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"startx"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int nX = _wtoi(strFlag);
  					GetDXUTState().SetOverrideStartX(nX);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"starty"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int nY = _wtoi(strFlag);
  					GetDXUTState().SetOverrideStartY(nY);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"constantframetime"))
  			{
  				float fTimePerFrame;
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  					fTimePerFrame = (float)wcstod(strFlag, nullptr);
  				else
  					fTimePerFrame = 0.0333f;
  				GetDXUTState().SetOverrideConstantFrameTime(true);
  				GetDXUTState().SetOverrideConstantTimePerFrame(fTimePerFrame);
  				DXUTSetConstantFrameTime(true, fTimePerFrame);
  				continue;
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"quitafterframe"))
  			{
  				if (DXUTGetCmdParam(strCmdLine, strFlag, MAX_PATH))
  				{
  					int nFrame = _wtoi(strFlag);
  					GetDXUTState().SetOverrideQuitAfterFrame(nFrame);
  					continue;
  				}
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"noerrormsgboxes"))
  			{
  				GetDXUTState().SetShowMsgBoxOnError(false);
  				continue;
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"nostats"))
  			{
  				GetDXUTState().SetNoStats(true);
  				continue;
  			}
  
  			if (DXUTIsNextArg(strCmdLine, L"automation"))
  			{
  				GetDXUTState().SetAutomation(true);
  				continue;
  			}
  		}
  
  		// Unrecognized flag
  		wcscpy_s(strFlag, MAX_PATH, strCmdLine);
  		WCHAR* strSpace = strFlag;
  		while (*strSpace && (*strSpace > L' '))
  			strSpace++;
  		*strSpace = 0;
  
  		DXUTOutputDebugString(L"Unrecognized flag: %ls", strFlag);
  		strCmdLine += wcslen(strFlag);
  	}
  
  	LocalFree(pstrArgList);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Helper function for DXUTParseCommandLine
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  bool DXUTIsNextArg(WCHAR*& strCmdLine, const WCHAR* strArg)
  {
  	size_t nArgLen = wcslen(strArg);
  	size_t nCmdLen = wcslen(strCmdLine);
  
  	if (nCmdLen >= nArgLen &&
  		_wcsnicmp(strCmdLine, strArg, nArgLen) == 0 &&
  		(strCmdLine[nArgLen] == 0 || strCmdLine[nArgLen] == L':'))
  	{
  		strCmdLine += nArgLen;
  		return true;
  	}
  
  	return false;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Helper function for DXUTParseCommandLine.  Updates strCmdLine and strFlag 
  //      Example: if strCmdLine=="-width:1024 -forceref"
  // then after: strCmdLine==" -forceref" and strFlag=="1024"
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  bool DXUTGetCmdParam(WCHAR*& strCmdLine, WCHAR* strFlag, int cchDest)
  {
  	if (*strCmdLine == L':')
  	{
  		strCmdLine++; // Skip ':'
  
  		// Place nul terminator in strFlag after current token
  		wcscpy_s(strFlag, cchDest, strCmdLine);
  
  		WCHAR* strSpace = strFlag;
  		int count = 0;
  		while (*strSpace && (*strSpace > L' ') && (count < cchDest))
  		{
  			++strSpace;
  			++count;
  		}
  		*strSpace = 0;
  
  		// Update strCmdLine
  		strCmdLine += wcslen(strFlag);
  		return true;
  	}
  	else
  	{
  		strFlag[0] = 0;
  		return false;
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Creates a window with the specified window title, icon, menu, and 
  // starting position.  If DXUTInit() has not already been called, it will
  // call it with the default parameters.  Instead of calling this, you can 
  // call DXUTSetWindow() to use an existing window.  
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT WINAPI DXUTCreateWindow(const WCHAR* strWindowTitle, HINSTANCE hInstance,
  	HICON hIcon, HMENU hMenu, int x, int y)
  {
  	HRESULT hr;
  
  	// Not allowed to call this from inside the device callbacks
  	if (GetDXUTState().GetInsideDeviceCallback())
  		return DXUT_ERR_MSGBOX(L"DXUTCreateWindow", E_FAIL);
  
  	GetDXUTState().SetWindowCreateCalled(true);
  
  	if (!GetDXUTState().GetDXUTInited())
  	{
  		// If DXUTInit() was already called and failed, then fail.
  		// DXUTInit() must first succeed for this function to succeed
  		if (GetDXUTState().GetDXUTInitCalled())
  			return E_FAIL;
  
  		// If DXUTInit() hasn't been called, then automatically call it
  		// with default params
  		hr = DXUTInit();
  		if (FAILED(hr))
  			return hr;
  	}
  
  	if (!DXUTGetHWNDFocus())
  	{
  		if (!hInstance)
  			hInstance = (HINSTANCE)GetModuleHandle(nullptr);
  		GetDXUTState().SetHInstance(hInstance);
  
  		WCHAR szExePath[MAX_PATH];
  		GetModuleFileName(nullptr, szExePath, MAX_PATH);
  		if (!hIcon) // If the icon is NULL, then use the first one found in the exe
  			hIcon = ExtractIcon(hInstance, szExePath, 0);
  
  		// Register the windows class
  		WNDCLASS wndClass;
  		wndClass.style = CS_DBLCLKS;
  		wndClass.lpfnWndProc = DXUTStaticWndProc;
  		wndClass.cbClsExtra = 0;
  		wndClass.cbWndExtra = 0;
  		wndClass.hInstance = hInstance;
  		wndClass.hIcon = hIcon;
  		wndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
  		wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  		wndClass.lpszMenuName = nullptr;
  		wndClass.lpszClassName = L"Direct3DWindowClass";
  
  		if (!RegisterClass(&wndClass))
  		{
  			DWORD dwError = GetLastError();
  			if (dwError != ERROR_CLASS_ALREADY_EXISTS)
  				return DXUT_ERR_MSGBOX(L"RegisterClass", HRESULT_FROM_WIN32(dwError));
  		}
  
  		// Override the window's initial & size position if there were cmd line args
  		if (GetDXUTState().GetOverrideStartX() != -1)
  			x = GetDXUTState().GetOverrideStartX();
  		if (GetDXUTState().GetOverrideStartY() != -1)
  			y = GetDXUTState().GetOverrideStartY();
  
  		GetDXUTState().SetWindowCreatedWithDefaultPositions(false);
  		if (x == CW_USEDEFAULT && y == CW_USEDEFAULT)
  			GetDXUTState().SetWindowCreatedWithDefaultPositions(true);
  
  		// Find the window's initial size, but it might be changed later
  		int nDefaultWidth = 800;
  		int nDefaultHeight = 600;
  		if (GetDXUTState().GetOverrideWidth() != 0)
  			nDefaultWidth = GetDXUTState().GetOverrideWidth();
  		if (GetDXUTState().GetOverrideHeight() != 0)
  			nDefaultHeight = GetDXUTState().GetOverrideHeight();
  
  		RECT rc;
  		SetRect(&rc, 0, 0, nDefaultWidth, nDefaultHeight);
  		AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, (hMenu) ? true : false);
  
  		WCHAR* strCachedWindowTitle = GetDXUTState().GetWindowTitle();
  		wcscpy_s(strCachedWindowTitle, 256, strWindowTitle);
  
  		// Create the render window
  		HWND hWnd = CreateWindow(L"Direct3DWindowClass", strWindowTitle, WS_OVERLAPPEDWINDOW,
  			x, y, (rc.right - rc.left), (rc.bottom - rc.top), 0,
  			hMenu, hInstance, 0);
  		if (!hWnd)
  		{
  			DWORD dwError = GetLastError();
  			return DXUT_ERR_MSGBOX(L"CreateWindow", HRESULT_FROM_WIN32(dwError));
  		}
  
  		GetDXUTState().SetWindowCreated(true);
  		GetDXUTState().SetHWNDFocus(hWnd);
  		GetDXUTState().SetHWNDDeviceFullScreen(hWnd);
  		GetDXUTState().SetHWNDDeviceWindowed(hWnd);
  	}
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Sets a previously created window for the framework to use.  If DXUTInit() 
  // has not already been called, it will call it with the default parameters.  
  // Instead of calling this, you can call DXUTCreateWindow() to create a new window.  
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT WINAPI DXUTSetWindow(HWND hWndFocus, HWND hWndDeviceFullScreen, HWND hWndDeviceWindowed, bool bHandleMessages)
  {
  	HRESULT hr;
  
  	// Not allowed to call this from inside the device callbacks
  	if (GetDXUTState().GetInsideDeviceCallback())
  		return DXUT_ERR_MSGBOX(L"DXUTCreateWindow", E_FAIL);
  
  	GetDXUTState().SetWindowCreateCalled(true);
  
  	// To avoid confusion, we do not allow any HWND to be nullptr here.  The
  	// caller must pass in valid HWND for all three parameters.  The same
  	// HWND may be used for more than one parameter.
  	if (!hWndFocus || !hWndDeviceFullScreen || !hWndDeviceWindowed)
  		return DXUT_ERR_MSGBOX(L"DXUTSetWindow", E_INVALIDARG);
  
  	// If subclassing the window, set the pointer to the local window procedure
  	if (bHandleMessages)
  	{
  		// Switch window procedures
  		LONG_PTR nResult = SetWindowLongPtr(hWndFocus, GWLP_WNDPROC, (LONG_PTR)DXUTStaticWndProc);
  
  		DWORD dwError = GetLastError();
  		if (nResult == 0)
  			return DXUT_ERR_MSGBOX(L"SetWindowLongPtr", HRESULT_FROM_WIN32(dwError));
  	}
  
  	if (!GetDXUTState().GetDXUTInited())
  	{
  		// If DXUTInit() was already called and failed, then fail.
  		// DXUTInit() must first succeed for this function to succeed
  		if (GetDXUTState().GetDXUTInitCalled())
  			return E_FAIL;
  
  		// If DXUTInit() hasn't been called, then automatically call it
  		// with default params
  		hr = DXUTInit();
  		if (FAILED(hr))
  			return hr;
  	}
  
  	WCHAR* strCachedWindowTitle = GetDXUTState().GetWindowTitle();
  	GetWindowText(hWndFocus, strCachedWindowTitle, 255);
  	strCachedWindowTitle[255] = 0;
  
  	HINSTANCE hInstance = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWndFocus, GWLP_HINSTANCE);
  	GetDXUTState().SetHInstance(hInstance);
  	GetDXUTState().SetWindowCreatedWithDefaultPositions(false);
  	GetDXUTState().SetWindowCreated(true);
  	GetDXUTState().SetHWNDFocus(hWndFocus);
  	GetDXUTState().SetHWNDDeviceFullScreen(hWndDeviceFullScreen);
  	GetDXUTState().SetHWNDDeviceWindowed(hWndDeviceWindowed);
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Handles window messages 
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  LRESULT CALLBACK DXUTStaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
  
  	// Consolidate the keyboard messages and pass them to the app's keyboard callback
  	if (uMsg == WM_KEYDOWN ||
  		uMsg == WM_SYSKEYDOWN ||
  		uMsg == WM_KEYUP ||
  		uMsg == WM_SYSKEYUP)
  	{
  		bool bKeyDown = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN);
  		DWORD dwMask = (1 << 29);
  		bool bAltDown = ((lParam & dwMask) != 0);
  
  		bool* bKeys = GetDXUTState().GetKeys();
  		bKeys[(BYTE)(wParam & 0xFF)] = bKeyDown;
  
  		LPDXUTCALLBACKKEYBOARD pCallbackKeyboard = GetDXUTState().GetKeyboardFunc();
  		if (pCallbackKeyboard)
  			pCallbackKeyboard((UINT)wParam, bKeyDown, bAltDown, GetDXUTState().GetKeyboardFuncUserContext());
  	}
  
  	// Consolidate the mouse button messages and pass them to the app's mouse callback
  	if (uMsg == WM_LBUTTONDOWN ||
  		uMsg == WM_LBUTTONUP ||
  		uMsg == WM_LBUTTONDBLCLK ||
  		uMsg == WM_MBUTTONDOWN ||
  		uMsg == WM_MBUTTONUP ||
  		uMsg == WM_MBUTTONDBLCLK ||
  		uMsg == WM_RBUTTONDOWN ||
  		uMsg == WM_RBUTTONUP ||
  		uMsg == WM_RBUTTONDBLCLK ||
  		uMsg == WM_XBUTTONDOWN ||
  		uMsg == WM_XBUTTONUP ||
  		uMsg == WM_XBUTTONDBLCLK ||
  		uMsg == WM_MOUSEWHEEL ||
  		(GetDXUTState().GetNotifyOnMouseMove() && uMsg == WM_MOUSEMOVE))
  	{
  		int xPos = (short)LOWORD(lParam);
  		int yPos = (short)HIWORD(lParam);
  
  		if (uMsg == WM_MOUSEWHEEL)
  		{
  			// WM_MOUSEWHEEL passes screen mouse coords
  			// so convert them to client coords
  			POINT pt;
  			pt.x = xPos; pt.y = yPos;
  			ScreenToClient(hWnd, &pt);
  			xPos = pt.x; yPos = pt.y;
  		}
  
  		int nMouseWheelDelta = 0;
  		if (uMsg == WM_MOUSEWHEEL)
  			nMouseWheelDelta = (short)HIWORD(wParam);
  
  		int nMouseButtonState = LOWORD(wParam);
  		bool bLeftButton = ((nMouseButtonState & MK_LBUTTON) != 0);
  		bool bRightButton = ((nMouseButtonState & MK_RBUTTON) != 0);
  		bool bMiddleButton = ((nMouseButtonState & MK_MBUTTON) != 0);
  		bool bSideButton1 = ((nMouseButtonState & MK_XBUTTON1) != 0);
  		bool bSideButton2 = ((nMouseButtonState & MK_XBUTTON2) != 0);
  
  		bool* bMouseButtons = GetDXUTState().GetMouseButtons();
  		bMouseButtons[0] = bLeftButton;
  		bMouseButtons[1] = bMiddleButton;
  		bMouseButtons[2] = bRightButton;
  		bMouseButtons[3] = bSideButton1;
  		bMouseButtons[4] = bSideButton2;
  
  		LPDXUTCALLBACKMOUSE pCallbackMouse = GetDXUTState().GetMouseFunc();
  		if (pCallbackMouse)
  			pCallbackMouse(bLeftButton, bRightButton, bMiddleButton, bSideButton1, bSideButton2, nMouseWheelDelta,
  				xPos, yPos, GetDXUTState().GetMouseFuncUserContext());
  	}
  
  	// TODO - WM_POINTER for touch when on Windows 8.0
  
  	// Pass all messages to the app's MsgProc callback, and don't 
  	// process further messages if the apps says not to.
  	LPDXUTCALLBACKMSGPROC pCallbackMsgProc = GetDXUTState().GetWindowMsgFunc();
  	if (pCallbackMsgProc)
  	{
  		bool bNoFurtherProcessing = false;
  		LRESULT nResult = pCallbackMsgProc(hWnd, uMsg, wParam, lParam, &bNoFurtherProcessing,
  			GetDXUTState().GetWindowMsgFuncUserContext());
  		if (bNoFurtherProcessing)
  			return nResult;
  	}
  
  	switch (uMsg)
  	{
  	case WM_PAINT:
  	{
  		// Handle paint messages when the app is paused
  		if (DXUTIsRenderingPaused() &&
  			GetDXUTState().GetDeviceObjectsCreated() && GetDXUTState().GetDeviceObjectsReset())
  		{
  			HRESULT hr;
  			double fTime = DXUTGetTime();
  			float fElapsedTime = DXUTGetElapsedTime();
  
  			{
  				auto pd3dDevice = DXUTGetD3D11Device();
  				auto pDeferred = DXUTGetD3D11DeviceContext();
  				if (pd3dDevice)
  				{
  					LPDXUTCALLBACKD3D11FRAMERENDER pCallbackFrameRender = GetDXUTState().GetD3D11FrameRenderFunc();
  					if (pCallbackFrameRender &&
  						!GetDXUTState().GetRenderingOccluded())
  					{
  						pCallbackFrameRender(pd3dDevice, pDeferred, fTime, fElapsedTime,
  							GetDXUTState().GetD3D11FrameRenderFuncUserContext());
  					}
  
  					DWORD dwFlags = 0;
  					if (GetDXUTState().GetRenderingOccluded())
  						dwFlags = DXGI_PRESENT_TEST;
  					else
  						dwFlags = GetDXUTState().GetCurrentDeviceSettings()->d3d11.PresentFlags;
  
  					auto pSwapChain = DXUTGetDXGISwapChain();
  					hr = pSwapChain->Present(0, dwFlags);
  					if (DXGI_STATUS_OCCLUDED == hr)
  					{
  						// There is a window covering our entire rendering area.
  						// Don't render until we're visible again.
  						GetDXUTState().SetRenderingOccluded(true);
  					}
  					else if (SUCCEEDED(hr))
  					{
  						if (GetDXUTState().GetRenderingOccluded())
  						{
  							// Now that we're no longer occluded
  							// allow us to render again
  							GetDXUTState().SetRenderingOccluded(false);
  						}
  					}
  				}
  			}
  		}
  		break;
  	}
  
  	case WM_SIZE:
  
  		if (SIZE_MINIMIZED == wParam)
  		{
  			DXUTPause(true, true); // Pause while we're minimized
  
  			GetDXUTState().SetMinimized(true);
  			GetDXUTState().SetMaximized(false);
  		}
  		else
  		{
  			RECT rcCurrentClient;
  			GetClientRect(DXUTGetHWND(), &rcCurrentClient);
  			if (rcCurrentClient.top == 0 && rcCurrentClient.bottom == 0)
  			{
  				// Rapidly clicking the task bar to minimize and restore a window
  				// can cause a WM_SIZE message with SIZE_RESTORED when 
  				// the window has actually become minimized due to rapid change
  				// so just ignore this message
  			}
  			else if (SIZE_MAXIMIZED == wParam)
  			{
  				if (GetDXUTState().GetMinimized())
  					DXUTPause(false, false); // Unpause since we're no longer minimized
  				GetDXUTState().SetMinimized(false);
  				GetDXUTState().SetMaximized(true);
  				DXUTCheckForWindowSizeChange();
  				DXUTCheckForWindowChangingMonitors();
  			}
  			else if (SIZE_RESTORED == wParam)
  			{
  				//DXUTCheckForDXGIFullScreenSwitch();
  				if (GetDXUTState().GetMaximized())
  				{
  					GetDXUTState().SetMaximized(false);
  					DXUTCheckForWindowSizeChange();
  					DXUTCheckForWindowChangingMonitors();
  				}
  				else if (GetDXUTState().GetMinimized())
  				{
  					DXUTPause(false, false); // Unpause since we're no longer minimized
  					GetDXUTState().SetMinimized(false);
  					DXUTCheckForWindowSizeChange();
  					DXUTCheckForWindowChangingMonitors();
  				}
  				else if (GetDXUTState().GetInSizeMove())
  				{
  					// If we're neither maximized nor minimized, the window size 
  					// is changing by the user dragging the window edges.  In this 
  					// case, we don't reset the device yet -- we wait until the 
  					// user stops dragging, and a WM_EXITSIZEMOVE message comes.
  				}
  				else
  				{
  					// This WM_SIZE come from resizing the window via an API like SetWindowPos() so 
  					// resize and reset the device now.
  					DXUTCheckForWindowSizeChange();
  					DXUTCheckForWindowChangingMonitors();
  				}
  			}
  		}
  		break;
  
  	case WM_GETMINMAXINFO:
  		((MINMAXINFO*)lParam)->ptMinTrackSize.x = DXUT_MIN_WINDOW_SIZE_X;
  		((MINMAXINFO*)lParam)->ptMinTrackSize.y = DXUT_MIN_WINDOW_SIZE_Y;
  		break;
  
  	case WM_ENTERSIZEMOVE:
  		// Halt frame movement while the app is sizing or moving
  		DXUTPause(true, true);
  		GetDXUTState().SetInSizeMove(true);
  		break;
  
  	case WM_EXITSIZEMOVE:
  		DXUTPause(false, false);
  		DXUTCheckForWindowSizeChange();
  		DXUTCheckForWindowChangingMonitors();
  		GetDXUTState().SetInSizeMove(false);
  		break;
  
  	case WM_SETCURSOR:
  		if (DXUTIsActive() && !DXUTIsWindowed())
  		{
  			if (!GetDXUTState().GetShowCursorWhenFullScreen())
  				SetCursor(nullptr);
  
  			return true; // prevent Windows from setting cursor to window class cursor
  		}
  		break;
  
  	case WM_ACTIVATEAPP:
  		if (wParam == TRUE && !DXUTIsActive()) // Handle only if previously not active 
  		{
  			GetDXUTState().SetActive(true);
  
  			// Enable controller rumble & input when activating app
  			DXUTEnableXInput(true);
  
  			// The GetMinimizedWhileFullscreen() varible is used instead of !DXUTIsWindowed()
  			// to handle the rare case toggling to windowed mode while the fullscreen application 
  			// is minimized and thus making the pause count wrong
  			if (GetDXUTState().GetMinimizedWhileFullscreen())
  			{
  				GetDXUTState().SetMinimizedWhileFullscreen(false);
  
  				DXUTToggleFullScreen();
  			}
  
  			// Upon returning to this app, potentially disable shortcut keys 
  			// (Windows key, accessibility shortcuts) 
  			DXUTAllowShortcutKeys((DXUTIsWindowed()) ? GetDXUTState().GetAllowShortcutKeysWhenWindowed() :
  				GetDXUTState().GetAllowShortcutKeysWhenFullscreen());
  
  		}
  		else if (wParam == FALSE && DXUTIsActive()) // Handle only if previously active 
  		{
  			GetDXUTState().SetActive(false);
  
  			// Disable any controller rumble & input when de-activating app
  			DXUTEnableXInput(false);
  
  			if (!DXUTIsWindowed())
  			{
  				// Going from full screen to a minimized state 
  				ClipCursor(nullptr);      // don't limit the cursor anymore
  				GetDXUTState().SetMinimizedWhileFullscreen(true);
  			}
  
  			// Restore shortcut keys (Windows key, accessibility shortcuts) to original state
  			//
  			// This is important to call here if the shortcuts are disabled, 
  			// because if this is not done then the Windows key will continue to 
  			// be disabled while this app is running which is very bad.
  			// If the app crashes, the Windows key will return to normal.
  			DXUTAllowShortcutKeys(true);
  		}
  		break;
  
  	case WM_ENTERMENULOOP:
  		// Pause the app when menus are displayed
  		DXUTPause(true, true);
  		break;
  
  	case WM_EXITMENULOOP:
  		DXUTPause(false, false);
  		break;
  
  	case WM_MENUCHAR:
  		// A menu is active and the user presses a key that does not correspond to any mnemonic or accelerator key
  		// So just ignore and don't beep
  		return MAKELRESULT(0, MNC_CLOSE);
  		break;
  
  	case WM_NCHITTEST:
  		// Prevent the user from selecting the menu in full screen mode
  		if (!DXUTIsWindowed())
  			return HTCLIENT;
  		break;
  
  	case WM_POWERBROADCAST:
  		switch (wParam)
  		{
  		case PBT_APMQUERYSUSPEND:
  			// At this point, the app should save any data for open
  			// network connections, files, etc., and prepare to go into
  			// a suspended mode.  The app can use the MsgProc callback
  			// to handle this if desired.
  			return true;
  
  		case PBT_APMRESUMESUSPEND:
  			// At this point, the app should recover any data, network
  			// connections, files, etc., and resume running from when
  			// the app was suspended. The app can use the MsgProc callback
  			// to handle this if desired.
  
  			// QPC may lose consistency when suspending, so reset the timer
  			// upon resume.
  			DXUTGetGlobalTimer()->Reset();
  			GetDXUTState().SetLastStatsUpdateTime(0);
  			return true;
  		}
  		break;
  
  	case WM_SYSCOMMAND:
  		// Prevent moving/sizing in full screen mode
  		switch ((wParam & 0xFFF0))
  		{
  		case SC_MOVE:
  		case SC_SIZE:
  		case SC_MAXIMIZE:
  		case SC_KEYMENU:
  			if (!DXUTIsWindowed())
  				return 0;
  			break;
  		}
  		break;
  
  	case WM_KEYDOWN:
  	{
  		switch (wParam)
  		{
  		case VK_ESCAPE:
  		{
  			if (GetDXUTState().GetHandleEscape())
  				SendMessage(hWnd, WM_CLOSE, 0, 0);
  			break;
  		}
  
  		case VK_PAUSE:
  		{
  			if (GetDXUTState().GetHandlePause())
  			{
  				bool bTimePaused = DXUTIsTimePaused();
  				bTimePaused = !bTimePaused;
  				if (bTimePaused)
  					DXUTPause(true, false);
  				else
  					DXUTPause(false, false);
  			}
  			break;
  		}
  		}
  		break;
  	}
  
  	case WM_CLOSE:
  	{
  		HMENU hMenu;
  		hMenu = GetMenu(hWnd);
  		if (hMenu)
  			DestroyMenu(hMenu);
  		DestroyWindow(hWnd);
  		UnregisterClass(L"Direct3DWindowClass", nullptr);
  		GetDXUTState().SetHWNDFocus(nullptr);
  		GetDXUTState().SetHWNDDeviceFullScreen(nullptr);
  		GetDXUTState().SetHWNDDeviceWindowed(nullptr);
  		return 0;
  	}
  
  	case WM_DESTROY:
  		PostQuitMessage(0);
  		break;
  	}
  
  	// Don't allow the F10 key to act as a shortcut to the menu bar
  	// by not passing these messages to the DefWindowProc only when
  	// there's no menu present
  	if (!GetDXUTState().GetCallDefWindowProc() || !GetDXUTState().GetMenu() &&
  		(uMsg == WM_SYSKEYDOWN || uMsg == WM_SYSKEYUP) && wParam == VK_F10)
  		return 0;
  	else
  		return DefWindowProc(hWnd, uMsg, wParam, lParam);
  }
  
  //--------------------------------------------------------------------------------------
  // Sets the render target view to the texture instead of swap chain's frame buffer.
  // Used in headless mode.
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  void WINAPI DXUTSetD3D11RenderTargetView(_In_ ID3D11RenderTargetView* pRenderTargetView)
  {
  	GetDXUTState().SetD3D11RenderTargetView(pRenderTargetView);
  }
  
  //--------------------------------------------------------------------------------------
  // Sets the custom depth stencil view.
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  void WINAPI DXUTSetD3D11DepthStencilView(_In_ ID3D11DepthStencilView* pDepthStencilView)
  {
  	GetDXUTState().SetD3D11DepthStencilView(pDepthStencilView);
  }
  
  //--------------------------------------------------------------------------------------
  // Handles app's message loop and rendering when idle.  If DXUTCreateDevice()
  // has not already been called, it will call DXUTCreateWindow() with the default parameters.  
  //--------------------------------------------------------------------------------------
  HRESULT WINAPI DXUTMainLoop(_In_opt_ HACCEL hAccel)
  {
  	HRESULT hr;
  
  	// Not allowed to call this from inside the device callbacks or reenter
  	if (GetDXUTState().GetInsideDeviceCallback() || GetDXUTState().GetInsideMainloop())
  	{
  		if ((GetDXUTState().GetExitCode() == 0) || (GetDXUTState().GetExitCode() == 10))
  			GetDXUTState().SetExitCode(1);
  		return DXUT_ERR_MSGBOX(L"DXUTMainLoop", E_FAIL);
  	}
  
  	GetDXUTState().SetInsideMainloop(true);
  
  	// If DXUTCreateDevice() has not already been called, 
  	// then call DXUTCreateDevice() with the default parameters.         
  	if (!GetDXUTState().GetDeviceCreated())
  	{
  		if (GetDXUTState().GetDeviceCreateCalled())
  		{
  			if ((GetDXUTState().GetExitCode() == 0) || (GetDXUTState().GetExitCode() == 10))
  				GetDXUTState().SetExitCode(1);
  			return E_FAIL; // DXUTCreateDevice() must first succeed for this function to succeed
  		}
  
  		hr = DXUTCreateDevice(D3D_FEATURE_LEVEL_10_0, true, 800, 600);
  		if (FAILED(hr))
  		{
  			if ((GetDXUTState().GetExitCode() == 0) || (GetDXUTState().GetExitCode() == 10))
  				GetDXUTState().SetExitCode(1);
  			return hr;
  		}
  	}
  
  	HWND hWnd = DXUTGetHWND();
  
  	// DXUTInit() must have been called and succeeded for this function to proceed
  	// DXUTCreateWindow() or DXUTSetWindow() must have been called and succeeded for this function to proceed
  	// DXUTCreateDevice() or DXUTCreateDeviceFromSettings() must have been called and succeeded for this function to proceed
  	if (!GetDXUTState().GetDXUTInited() || !GetDXUTState().GetWindowCreated() || !GetDXUTState().GetDeviceCreated())
  	{
  		if ((GetDXUTState().GetExitCode() == 0) || (GetDXUTState().GetExitCode() == 10))
  			GetDXUTState().SetExitCode(1);
  		return DXUT_ERR_MSGBOX(L"DXUTMainLoop", E_FAIL);
  	}
  
  	// Now we're ready to receive and process Windows messages.
  	bool bGotMsg;
  	MSG msg;
  	msg.message = WM_NULL;
  	PeekMessage(&msg, nullptr, 0U, 0U, PM_NOREMOVE);
  
  	while (WM_QUIT != msg.message)
  	{
  		// Use PeekMessage() so we can use idle time to render the scene. 
  		bGotMsg = (PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE) != 0);
  
  		if (bGotMsg)
  		{
  			// Translate and dispatch the message
  			if (!hAccel || !hWnd ||
  				0 == TranslateAccelerator(hWnd, hAccel, &msg))
  			{
  				TranslateMessage(&msg);
  				DispatchMessage(&msg);
  			}
  		}
  		else
  		{
  			// Render a frame during idle time (no messages are waiting)
  			DXUTRender3DEnvironment();
  		}
  	}
  
  	// Cleanup the accelerator table
  	if (hAccel)
  		DestroyAcceleratorTable(hAccel);
  
  	GetDXUTState().SetInsideMainloop(false);
  
  	return S_OK;
  }
  
  
  //======================================================================================
  //======================================================================================
  // Direct3D section
  //======================================================================================
  //======================================================================================
  _Use_decl_annotations_
  HRESULT WINAPI DXUTCreateDevice(D3D_FEATURE_LEVEL reqFL, bool bWindowed, int nSuggestedWidth, int nSuggestedHeight)
  {
  	HRESULT hr = S_OK;
  
  	// Not allowed to call this from inside the device callbacks
  	if (GetDXUTState().GetInsideDeviceCallback())
  		return DXUT_ERR_MSGBOX(L"DXUTCreateDevice", E_FAIL);
  
  	GetDXUTState().SetDeviceCreateCalled(true);
  
  	// If DXUTCreateWindow() or DXUTSetWindow() has not already been called and
  	// we're not in headless mode, call DXUTCreateWindow() with the default parameters.         
  	if (!GetDXUTState().GetWindowCreated() && !GetDXUTState().GetHeadlessMode())
  	{
  		// If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail.
  		// DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed
  		if (GetDXUTState().GetWindowCreateCalled())
  			return E_FAIL;
  
  		// If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then 
  		// automatically call DXUTCreateWindow() with default params
  		hr = DXUTCreateWindow();
  		if (FAILED(hr))
  			return hr;
  	}
  
  	DXUTDeviceSettings deviceSettings;
  	DXUTApplyDefaultDeviceSettings(&deviceSettings);
  	deviceSettings.MinimumFeatureLevel = reqFL;
  	deviceSettings.d3d11.sd.BufferDesc.Width = nSuggestedWidth;
  	deviceSettings.d3d11.sd.BufferDesc.Height = nSuggestedHeight;
  	deviceSettings.d3d11.sd.Windowed = bWindowed;
  
  	DXUTUpdateDeviceSettingsWithOverrides(&deviceSettings);
  
  	GetDXUTState().SetWindowBackBufferWidthAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Width);
  	GetDXUTState().SetWindowBackBufferHeightAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Height);
  	GetDXUTState().SetFullScreenBackBufferWidthAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Width);
  	GetDXUTState().SetFullScreenBackBufferHeightAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Height);
  
  	// Change to a Direct3D device created from the new device settings.  
  	// If there is an existing device, then either reset or recreated the scene
  	hr = DXUTChangeDevice(&deviceSettings, true);
  
  	if (hr == DXUTERR_NODIRECT3D && GetDXUTState().GetMessageWhenD3D11NotAvailable())
  	{
  		OSVERSIONINFOEX osv;
  		memset(&osv, 0, sizeof(osv));
  		osv.dwOSVersionInfoSize = sizeof(osv);
  #pragma warning( suppress : 4996 28159 )
  		GetVersionEx((LPOSVERSIONINFO)&osv);
  
  		if ((osv.dwMajorVersion > 6)
  			|| (osv.dwMajorVersion == 6 && osv.dwMinorVersion >= 1)
  			|| (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 && osv.dwBuildNumber > 6002))
  		{
  			MessageBox(0, L"Direct3D 11 components were not found.", L"Error", MB_ICONEXCLAMATION);
  			// This should not happen, but is here for completeness as the system could be
  			// corrupted or some future OS version could pull D3D11.DLL for some reason
  		}
  		else if (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 && osv.dwBuildNumber == 6002)
  		{
  			MessageBox(0, L"Direct3D 11 components were not found, but are available for"\
  				L" this version of Windows.\n"\
  				L"For details see Microsoft Knowledge Base Article #971644\n"\
  				L"http://go.microsoft.com/fwlink/?LinkId=160189", L"Error", MB_ICONEXCLAMATION);
  		}
  		else if (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0)
  		{
  			MessageBox(0, L"Direct3D 11 components were not found. Please install the latest Service Pack.\n"\
  				L"For details see Microsoft Knowledge Base Article #935791\n"\
  				L"http://support.microsoft.com/kb/935791/", L"Error", MB_ICONEXCLAMATION);
  		}
  		else
  		{
  			MessageBox(0, L"Direct3D 11 is not supported on this OS.", L"Error", MB_ICONEXCLAMATION);
  		}
  	}
  
  	if (FAILED(hr))
  		return hr;
  
  	return hr;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Tells the framework to change to a device created from the passed in device settings
  // If DXUTCreateWindow() has not already been called, it will call it with the 
  // default parameters.  Instead of calling this, you can call DXUTCreateDevice() 
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT WINAPI DXUTCreateDeviceFromSettings(DXUTDeviceSettings* pDeviceSettings, bool bClipWindowToSingleAdapter)
  {
  	if (!pDeviceSettings)
  		return E_INVALIDARG;
  
  	HRESULT hr;
  
  	GetDXUTState().SetDeviceCreateCalled(true);
  
  	// If DXUTCreateWindow() or DXUTSetWindow() has not already been called, 
  	// then call DXUTCreateWindow() with the default parameters.         
  	if (!GetDXUTState().GetWindowCreated())
  	{
  		// If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail.
  		// DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed
  		if (GetDXUTState().GetWindowCreateCalled())
  			return E_FAIL;
  
  		// If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then 
  		// automatically call DXUTCreateWindow() with default params
  		hr = DXUTCreateWindow();
  		if (FAILED(hr))
  			return hr;
  	}
  
  	DXUTUpdateDeviceSettingsWithOverrides(pDeviceSettings);
  
  	GetDXUTState().SetWindowBackBufferWidthAtModeChange(pDeviceSettings->d3d11.sd.BufferDesc.Width);
  	GetDXUTState().SetWindowBackBufferHeightAtModeChange(pDeviceSettings->d3d11.sd.BufferDesc.Height);
  	GetDXUTState().SetFullScreenBackBufferWidthAtModeChange(pDeviceSettings->d3d11.sd.BufferDesc.Width);
  	GetDXUTState().SetFullScreenBackBufferHeightAtModeChange(pDeviceSettings->d3d11.sd.BufferDesc.Height);
  
  	// Change to a Direct3D device created from the new device settings.  
  	// If there is an existing device, then either reset or recreate the scene
  	hr = DXUTChangeDevice(pDeviceSettings, bClipWindowToSingleAdapter);
  	if (FAILED(hr))
  		return hr;
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // All device changes are sent to this function.  It looks at the current 
  // device (if any) and the new device and determines the best course of action.  It 
  // also remembers and restores the window state if toggling between windowed and fullscreen
  // as well as sets the proper window and system state for switching to the new device.
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT DXUTChangeDevice(DXUTDeviceSettings* pNewDeviceSettings,
  	bool bClipWindowToSingleAdapter)
  {
  	if (GetDXUTState().GetReleasingSwapChain())
  		return S_FALSE;
  
  	HRESULT hr = S_OK;
  	DXUTDeviceSettings* pOldDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  
  	if (!pNewDeviceSettings)
  		return S_FALSE;
  
  	hr = DXUTDelayLoadDXGI();
  
  	if (FAILED(hr))
  		return hr;
  
  	// Make a copy of the pNewDeviceSettings on the heap
  	DXUTDeviceSettings* pNewDeviceSettingsOnHeap = new (std::nothrow) DXUTDeviceSettings;
  	if (!pNewDeviceSettingsOnHeap)
  		return E_OUTOFMEMORY;
  	memcpy(pNewDeviceSettingsOnHeap, pNewDeviceSettings, sizeof(DXUTDeviceSettings));
  	pNewDeviceSettings = pNewDeviceSettingsOnHeap;
  
  	GetDXUTState().SetCurrentDeviceSettings(pNewDeviceSettingsOnHeap);
  	hr = DXUTSnapDeviceSettingsToEnumDevice(pNewDeviceSettingsOnHeap, false);
  
  	if (FAILED(hr)) // the call will fail if no valid devices were found
  	{
  		DXUTDisplayErrorMessage(hr);
  		return DXUT_ERR(L"DXUTFindValidDeviceSettings", hr);
  	}
  
  	// If the ModifyDeviceSettings callback is non-NULL, then call it to let the app 
  	// change the settings or reject the device change by returning false.
  	LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings = GetDXUTState().GetModifyDeviceSettingsFunc();
  	if (pCallbackModifyDeviceSettings)
  	{
  		bool bContinue = pCallbackModifyDeviceSettings(pNewDeviceSettings,
  			GetDXUTState().GetModifyDeviceSettingsFuncUserContext());
  		if (!bContinue)
  		{
  			// The app rejected the device change by returning false, so just use the current device if there is one.
  			if (!pOldDeviceSettings)
  				DXUTDisplayErrorMessage(DXUTERR_NOCOMPATIBLEDEVICES);
  			SAFE_DELETE(pNewDeviceSettings);
  			return E_ABORT;
  		}
  		if (!GetDXUTState().GetDXGIFactory()) // if DXUTShutdown() was called in the modify callback, just return
  		{
  			SAFE_DELETE(pNewDeviceSettings);
  			return S_FALSE;
  		}
  		DXUTSnapDeviceSettingsToEnumDevice(pNewDeviceSettingsOnHeap, false); // modify the app specified settings to the closed enumerated settigns
  
  		if (FAILED(hr)) // the call will fail if no valid devices were found
  		{
  			DXUTDisplayErrorMessage(hr);
  			return DXUT_ERR(L"DXUTFindValidDeviceSettings", hr);
  		}
  
  	}
  
  	GetDXUTState().SetCurrentDeviceSettings(pNewDeviceSettingsOnHeap);
  
  	DXUTPause(true, true);
  
  	// Take note if the backbuffer width & height are 0 now as they will change after pd3dDevice->Reset()
  	bool bKeepCurrentWindowSize = false;
  	if (DXUTGetBackBufferWidthFromDS(pNewDeviceSettings) == 0 &&
  		DXUTGetBackBufferHeightFromDS(pNewDeviceSettings) == 0)
  		bKeepCurrentWindowSize = true;
  
  	//////////////////////////
  	// Before reset
  	/////////////////////////
  
  	if (DXUTGetIsWindowedFromDS(pNewDeviceSettings))
  	{
  		// Going to windowed mode
  		if (pOldDeviceSettings && !DXUTGetIsWindowedFromDS(pOldDeviceSettings))
  		{
  			// Going from fullscreen -> windowed
  			GetDXUTState().SetFullScreenBackBufferWidthAtModeChange(DXUTGetBackBufferWidthFromDS(
  				pOldDeviceSettings));
  			GetDXUTState().SetFullScreenBackBufferHeightAtModeChange(DXUTGetBackBufferHeightFromDS(
  				pOldDeviceSettings));
  		}
  	}
  	else
  	{
  		// Going to fullscreen mode
  		if (!pOldDeviceSettings || (pOldDeviceSettings && DXUTGetIsWindowedFromDS(pOldDeviceSettings)))
  		{
  			// Transistioning to full screen mode from a standard window so 
  			if (pOldDeviceSettings)
  			{
  				GetDXUTState().SetWindowBackBufferWidthAtModeChange(DXUTGetBackBufferWidthFromDS(
  					pOldDeviceSettings));
  				GetDXUTState().SetWindowBackBufferHeightAtModeChange(DXUTGetBackBufferHeightFromDS(
  					pOldDeviceSettings));
  			}
  		}
  	}
  
  	if (pOldDeviceSettings)
  		DXUTCleanup3DEnvironment(false);
  
  	// Create the D3D device and call the app's device callbacks
  	hr = DXUTCreate3DEnvironment11();
  	if (FAILED(hr))
  	{
  		SAFE_DELETE(pOldDeviceSettings);
  		DXUTCleanup3DEnvironment(true);
  		DXUTDisplayErrorMessage(hr);
  		DXUTPause(false, false);
  		GetDXUTState().SetIgnoreSizeChange(false);
  		return hr;
  	}
  
  	// Enable/disable StickKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut, and Windows key 
  	// to prevent accidental task switching
  	DXUTAllowShortcutKeys((DXUTGetIsWindowedFromDS(pNewDeviceSettings)) ?
  		GetDXUTState().GetAllowShortcutKeysWhenWindowed() :
  		GetDXUTState().GetAllowShortcutKeysWhenFullscreen());
  
  	HMONITOR hAdapterMonitor = DXUTGetMonitorFromAdapter(pNewDeviceSettings);
  	GetDXUTState().SetAdapterMonitor(hAdapterMonitor);
  
  	// Update the device stats text
  	DXUTUpdateStaticFrameStats();
  
  	if (!GetDXUTState().GetHeadlessMode())
  	{
  		if (pOldDeviceSettings && !DXUTGetIsWindowedFromDS(pOldDeviceSettings) &&
  			DXUTGetIsWindowedFromDS(pNewDeviceSettings))
  		{
  			// Going from fullscreen -> windowed
  
  			// Restore the show state, and positions/size of the window to what it was
  			// It is important to adjust the window size 
  			// after resetting the device rather than beforehand to ensure 
  			// that the monitor resolution is correct and does not limit the size of the new window.
  			auto pwp = GetDXUTState().GetWindowedPlacement();
  			SetWindowPlacement(DXUTGetHWNDDeviceWindowed(), pwp);
  
  			// Also restore the z-order of window to previous state
  			HWND hWndInsertAfter = GetDXUTState().GetTopmostWhileWindowed() ? HWND_TOPMOST : HWND_NOTOPMOST;
  			SetWindowPos(DXUTGetHWNDDeviceWindowed(), hWndInsertAfter, 0, 0, 0, 0,
  				SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
  		}
  
  		// Check to see if the window needs to be resized.  
  		// Handle cases where the window is minimized and maxmimized as well.
  
  		bool bNeedToResize = false;
  		if (DXUTGetIsWindowedFromDS(pNewDeviceSettings) && // only resize if in windowed mode
  			!bKeepCurrentWindowSize)                      // only resize if pp.BackbufferWidth/Height were not 0
  		{
  			UINT nClientWidth;
  			UINT nClientHeight;
  			if (IsIconic(DXUTGetHWNDDeviceWindowed()))
  			{
  				// Window is currently minimized. To tell if it needs to resize, 
  				// get the client rect of window when its restored the 
  				// hard way using GetWindowPlacement()
  				WINDOWPLACEMENT wp;
  				ZeroMemory(&wp, sizeof(WINDOWPLACEMENT));
  				wp.length = sizeof(WINDOWPLACEMENT);
  				GetWindowPlacement(DXUTGetHWNDDeviceWindowed(), &wp);
  
  				if ((wp.flags & WPF_RESTORETOMAXIMIZED) != 0 && wp.showCmd == SW_SHOWMINIMIZED)
  				{
  					// WPF_RESTORETOMAXIMIZED means that when the window is restored it will
  					// be maximized.  So maximize the window temporarily to get the client rect 
  					// when the window is maximized.  GetSystemMetrics( SM_CXMAXIMIZED ) will give this 
  					// information if the window is on the primary but this will work on multimon.
  					ShowWindow(DXUTGetHWNDDeviceWindowed(), SW_RESTORE);
  					RECT rcClient;
  					GetClientRect(DXUTGetHWNDDeviceWindowed(), &rcClient);
  					nClientWidth = (UINT)(rcClient.right - rcClient.left);
  					nClientHeight = (UINT)(rcClient.bottom - rcClient.top);
  					ShowWindow(DXUTGetHWNDDeviceWindowed(), SW_MINIMIZE);
  				}
  				else
  				{
  					// Use wp.rcNormalPosition to get the client rect, but wp.rcNormalPosition 
  					// includes the window frame so subtract it
  					RECT rcFrame = { 0 };
  					AdjustWindowRect(&rcFrame, GetDXUTState().GetWindowedStyleAtModeChange(), GetDXUTState().GetMenu() != 0);
  					LONG nFrameWidth = rcFrame.right - rcFrame.left;
  					LONG nFrameHeight = rcFrame.bottom - rcFrame.top;
  					nClientWidth = (UINT)(wp.rcNormalPosition.right - wp.rcNormalPosition.left - nFrameWidth);
  					nClientHeight = (UINT)(wp.rcNormalPosition.bottom - wp.rcNormalPosition.top - nFrameHeight);
  				}
  			}
  			else
  			{
  				// Window is restored or maximized so just get its client rect
  				RECT rcClient;
  				GetClientRect(DXUTGetHWNDDeviceWindowed(), &rcClient);
  				nClientWidth = (UINT)(rcClient.right - rcClient.left);
  				nClientHeight = (UINT)(rcClient.bottom - rcClient.top);
  			}
  
  			// Now that we know the client rect, compare it against the back buffer size
  			// to see if the client rect is already the right size
  			if (nClientWidth != DXUTGetBackBufferWidthFromDS(pNewDeviceSettings) ||
  				nClientHeight != DXUTGetBackBufferHeightFromDS(pNewDeviceSettings))
  			{
  				bNeedToResize = true;
  			}
  
  			if (bClipWindowToSingleAdapter && !IsIconic(DXUTGetHWNDDeviceWindowed()))
  			{
  				// Get the rect of the monitor attached to the adapter
  				MONITORINFO miAdapter;
  				miAdapter.cbSize = sizeof(MONITORINFO);
  				hAdapterMonitor = DXUTGetMonitorFromAdapter(pNewDeviceSettings);
  				DXUTGetMonitorInfo(hAdapterMonitor, &miAdapter);
  				HMONITOR hWindowMonitor = DXUTMonitorFromWindow(DXUTGetHWND(), MONITOR_DEFAULTTOPRIMARY);
  
  				// Get the rect of the window
  				RECT rcWindow;
  				GetWindowRect(DXUTGetHWNDDeviceWindowed(), &rcWindow);
  
  				// Check if the window rect is fully inside the adapter's vitural screen rect
  				if ((rcWindow.left < miAdapter.rcWork.left ||
  					rcWindow.right > miAdapter.rcWork.right ||
  					rcWindow.top < miAdapter.rcWork.top ||
  					rcWindow.bottom > miAdapter.rcWork.bottom))
  				{
  					if (hWindowMonitor == hAdapterMonitor && IsZoomed(DXUTGetHWNDDeviceWindowed()))
  					{
  						// If the window is maximized and on the same monitor as the adapter, then 
  						// no need to clip to single adapter as the window is already clipped 
  						// even though the rcWindow rect is outside of the miAdapter.rcWork
  					}
  					else
  					{
  						bNeedToResize = true;
  					}
  				}
  			}
  		}
  
  		// Only resize window if needed 
  
  		if (bNeedToResize)
  		{
  			// Need to resize, so if window is maximized or minimized then restore the window
  			if (IsIconic(DXUTGetHWNDDeviceWindowed()))
  				ShowWindow(DXUTGetHWNDDeviceWindowed(), SW_RESTORE);
  			if (IsZoomed(DXUTGetHWNDDeviceWindowed())) // doing the IsIconic() check first also handles the WPF_RESTORETOMAXIMIZED case
  				ShowWindow(DXUTGetHWNDDeviceWindowed(), SW_RESTORE);
  
  			if (bClipWindowToSingleAdapter)
  			{
  				// Get the rect of the monitor attached to the adapter
  				MONITORINFO miAdapter;
  				miAdapter.cbSize = sizeof(MONITORINFO);
  				hAdapterMonitor = DXUTGetMonitorFromAdapter(pNewDeviceSettings);
  				DXUTGetMonitorInfo(hAdapterMonitor, &miAdapter);
  
  				// Get the rect of the monitor attached to the window
  				MONITORINFO miWindow;
  				miWindow.cbSize = sizeof(MONITORINFO);
  				DXUTGetMonitorInfo(DXUTMonitorFromWindow(DXUTGetHWND(), MONITOR_DEFAULTTOPRIMARY), &miWindow);
  
  				// Do something reasonable if the BackBuffer size is greater than the monitor size
  				int nAdapterMonitorWidth = miAdapter.rcWork.right - miAdapter.rcWork.left;
  				int nAdapterMonitorHeight = miAdapter.rcWork.bottom - miAdapter.rcWork.top;
  
  				int nClientWidth = DXUTGetBackBufferWidthFromDS(pNewDeviceSettings);
  				int nClientHeight = DXUTGetBackBufferHeightFromDS(pNewDeviceSettings);
  
  				// Get the rect of the window
  				RECT rcWindow;
  				GetWindowRect(DXUTGetHWNDDeviceWindowed(), &rcWindow);
  
  				// Make a window rect with a client rect that is the same size as the backbuffer
  				RECT rcResizedWindow;
  				rcResizedWindow.left = 0;
  				rcResizedWindow.right = nClientWidth;
  				rcResizedWindow.top = 0;
  				rcResizedWindow.bottom = nClientHeight;
  				AdjustWindowRect(&rcResizedWindow, GetWindowLong(DXUTGetHWNDDeviceWindowed(), GWL_STYLE),
  					GetDXUTState().GetMenu() != 0);
  
  				int nWindowWidth = rcResizedWindow.right - rcResizedWindow.left;
  				int nWindowHeight = rcResizedWindow.bottom - rcResizedWindow.top;
  
  				if (nWindowWidth > nAdapterMonitorWidth)
  					nWindowWidth = nAdapterMonitorWidth;
  				if (nWindowHeight > nAdapterMonitorHeight)
  					nWindowHeight = nAdapterMonitorHeight;
  
  				if (rcResizedWindow.left < miAdapter.rcWork.left ||
  					rcResizedWindow.top < miAdapter.rcWork.top ||
  					rcResizedWindow.right > miAdapter.rcWork.right ||
  					rcResizedWindow.bottom > miAdapter.rcWork.bottom)
  				{
  					int nWindowOffsetX = (nAdapterMonitorWidth - nWindowWidth) / 2;
  					int nWindowOffsetY = (nAdapterMonitorHeight - nWindowHeight) / 2;
  
  					rcResizedWindow.left = miAdapter.rcWork.left + nWindowOffsetX;
  					rcResizedWindow.top = miAdapter.rcWork.top + nWindowOffsetY;
  					rcResizedWindow.right = miAdapter.rcWork.left + nWindowOffsetX + nWindowWidth;
  					rcResizedWindow.bottom = miAdapter.rcWork.top + nWindowOffsetY + nWindowHeight;
  				}
  
  				// Resize the window.  It is important to adjust the window size 
  				// after resetting the device rather than beforehand to ensure 
  				// that the monitor resolution is correct and does not limit the size of the new window.
  				SetWindowPos(DXUTGetHWNDDeviceWindowed(), 0, rcResizedWindow.left, rcResizedWindow.top, nWindowWidth,
  					nWindowHeight, SWP_NOZORDER);
  			}
  			else
  			{
  				// Make a window rect with a client rect that is the same size as the backbuffer
  				RECT rcWindow = { 0 };
  				rcWindow.right = (long)(DXUTGetBackBufferWidthFromDS(pNewDeviceSettings));
  				rcWindow.bottom = (long)(DXUTGetBackBufferHeightFromDS(pNewDeviceSettings));
  				AdjustWindowRect(&rcWindow, GetWindowLong(DXUTGetHWNDDeviceWindowed(), GWL_STYLE), GetDXUTState().GetMenu() != 0);
  
  				// Resize the window.  It is important to adjust the window size 
  				// after resetting the device rather than beforehand to ensure 
  				// that the monitor resolution is correct and does not limit the size of the new window.
  				int cx = (int)(rcWindow.right - rcWindow.left);
  				int cy = (int)(rcWindow.bottom - rcWindow.top);
  				SetWindowPos(DXUTGetHWNDDeviceWindowed(), 0, 0, 0, cx, cy, SWP_NOZORDER | SWP_NOMOVE);
  			}
  
  			// Its possible that the new window size is not what we asked for.  
  			// No window can be sized larger than the desktop, so see if the Windows OS resized the 
  			// window to something smaller to fit on the desktop.  Also if WM_GETMINMAXINFO
  			// will put a limit on the smallest/largest window size.
  			RECT rcClient;
  			GetClientRect(DXUTGetHWNDDeviceWindowed(), &rcClient);
  			UINT nClientWidth = (UINT)(rcClient.right - rcClient.left);
  			UINT nClientHeight = (UINT)(rcClient.bottom - rcClient.top);
  			if (nClientWidth != DXUTGetBackBufferWidthFromDS(pNewDeviceSettings) ||
  				nClientHeight != DXUTGetBackBufferHeightFromDS(pNewDeviceSettings))
  			{
  				// If its different, then resize the backbuffer again.  This time create a backbuffer that matches the 
  				// client rect of the current window w/o resizing the window.
  				auto deviceSettings = DXUTGetDeviceSettings();
  				deviceSettings.d3d11.sd.BufferDesc.Width = 0;
  				deviceSettings.d3d11.sd.BufferDesc.Height = 0;
  
  				hr = DXUTChangeDevice(&deviceSettings, bClipWindowToSingleAdapter);
  				if (FAILED(hr))
  				{
  					SAFE_DELETE(pOldDeviceSettings);
  					DXUTCleanup3DEnvironment(true);
  					DXUTPause(false, false);
  					GetDXUTState().SetIgnoreSizeChange(false);
  					return hr;
  				}
  			}
  		}
  
  		//if (DXUTGetIsWindowedFromDS( pNewDeviceSettings )) {
  		//    RECT rcFrame = {0};
  		//    AdjustWindowRect( &rcFrame, GetDXUTState().GetWindowedStyleAtModeChange(), GetDXUTState().GetMenu() );
  	   // }
  
  		// Make the window visible
  		if (!IsWindowVisible(DXUTGetHWND()))
  			ShowWindow(DXUTGetHWND(), SW_SHOW);
  	}
  
  	// Ensure that the display doesn't power down when fullscreen but does when windowed
  	if (!DXUTIsWindowed())
  		SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
  	else
  		SetThreadExecutionState(ES_CONTINUOUS);
  
  	SAFE_DELETE(pOldDeviceSettings);
  	GetDXUTState().SetIgnoreSizeChange(false);
  	DXUTPause(false, false);
  	GetDXUTState().SetDeviceCreated(true);
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Creates a DXGI factory object if one has not already been created  
  //--------------------------------------------------------------------------------------
  HRESULT DXUTDelayLoadDXGI()
  {
  	auto pDXGIFactory = GetDXUTState().GetDXGIFactory();
  	if (!pDXGIFactory)
  	{
  		HRESULT hr = DXUT_Dynamic_CreateDXGIFactory1(IID_PPV_ARGS(&pDXGIFactory));
  		if (FAILED(hr))
  			return hr;
  
  		GetDXUTState().SetDXGIFactory(pDXGIFactory);
  		if (!pDXGIFactory)
  		{
  			return DXUTERR_NODIRECT3D;
  		}
  
  		// DXGI 1.1 implies Direct3D 11
  	}
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Updates the device settings with default values..  
  //--------------------------------------------------------------------------------------
  void DXUTUpdateDeviceSettingsWithOverrides(_Inout_ DXUTDeviceSettings* pDeviceSettings)
  {
  	// Override with settings from the command line
  	if (GetDXUTState().GetOverrideWidth() != 0)
  	{
  		pDeviceSettings->d3d11.sd.BufferDesc.Width = GetDXUTState().GetOverrideWidth();
  	}
  	if (GetDXUTState().GetOverrideHeight() != 0)
  	{
  		pDeviceSettings->d3d11.sd.BufferDesc.Height = GetDXUTState().GetOverrideHeight();
  	}
  
  	if (GetDXUTState().GetOverrideAdapterOrdinal() != -1)
  	{
  		pDeviceSettings->d3d11.AdapterOrdinal = GetDXUTState().GetOverrideAdapterOrdinal();
  	}
  
  	if (GetDXUTState().GetOverrideFullScreen())
  	{
  		pDeviceSettings->d3d11.sd.Windowed = FALSE;
  	}
  
  	if (GetDXUTState().GetOverrideWindowed())
  	{
  		pDeviceSettings->d3d11.sd.Windowed = TRUE;
  	}
  
  	if (GetDXUTState().GetOverrideForceHAL())
  	{
  		pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE;
  	}
  
  	if (GetDXUTState().GetOverrideForceREF())
  	{
  		pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_REFERENCE;
  	}
  
  	if (GetDXUTState().GetOverrideForceWARP())
  	{
  		pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_WARP;
  		pDeviceSettings->d3d11.sd.Windowed = TRUE;
  	}
  
  	if (GetDXUTState().GetOverrideForceVsync() == 0)
  	{
  		pDeviceSettings->d3d11.SyncInterval = 0;
  	}
  	else if (GetDXUTState().GetOverrideForceVsync() == 1)
  	{
  		pDeviceSettings->d3d11.SyncInterval = 1;
  	}
  
  	if (GetDXUTState().GetOverrideForceFeatureLevel() != 0)
  	{
  		pDeviceSettings->d3d11.DeviceFeatureLevel = GetDXUTState().GetOverrideForceFeatureLevel();
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Sets the viewport, render target view, and depth stencil view.
  //--------------------------------------------------------------------------------------
  HRESULT WINAPI DXUTSetupD3D11Views(_In_ ID3D11DeviceContext* pd3dDeviceContext)
  {
  	HRESULT hr = S_OK;
  
  	// Setup the viewport to match the backbuffer
  	D3D11_VIEWPORT vp;
  	vp.Width = (FLOAT)DXUTGetDXGIBackBufferSurfaceDesc()->Width;
  	vp.Height = (FLOAT)DXUTGetDXGIBackBufferSurfaceDesc()->Height;
  	vp.MinDepth = 0;
  	vp.MaxDepth = 1;
  	vp.TopLeftX = 0;
  	vp.TopLeftY = 0;
  	pd3dDeviceContext->RSSetViewports(1, &vp);
  
  	// Set the render targets
  	auto pRTV = GetDXUTState().GetD3D11RenderTargetView();
  	auto pDSV = GetDXUTState().GetD3D11DepthStencilView();
  	pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, pDSV);
  
  	return hr;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Creates a render target view, and depth stencil texture and view.
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT DXUTCreateD3D11Views(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext,
  	DXUTDeviceSettings* pDeviceSettings)
  {
  	HRESULT hr = S_OK;
  	auto pSwapChain = DXUTGetDXGISwapChain();
  	ID3D11DepthStencilView* pDSV = nullptr;
  	ID3D11RenderTargetView* pRTV = nullptr;
  	UINT backBufferWidth = 0;
  	UINT backBufferHeight = 0;
  
  	if (!GetDXUTState().GetHeadlessMode())
  	{
  		// Get the back buffer and desc
  		ID3D11Texture2D* pBackBuffer;
  		hr = pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
  		if (FAILED(hr))
  			return hr;
  		D3D11_TEXTURE2D_DESC backBufferSurfaceDesc;
  		pBackBuffer->GetDesc(&backBufferSurfaceDesc);
  		backBufferWidth = backBufferSurfaceDesc.Width;
  		backBufferHeight = backBufferSurfaceDesc.Height;
  
  		// Create the render target view
  		hr = pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &pRTV);
  		SAFE_RELEASE(pBackBuffer);
  		if (FAILED(hr))
  			return hr;
  		DXUT_SetDebugName(pRTV, "DXUT");
  		GetDXUTState().SetD3D11RenderTargetView(pRTV);
  	}
  	else
  	{
  		auto pdeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  		auto desc = pdeviceSettings->d3d11.sd;
  		backBufferWidth = (UINT)desc.BufferDesc.Width;
  		backBufferHeight = (UINT)desc.BufferDesc.Height;
  	}
  
  	if (pDeviceSettings->d3d11.AutoCreateDepthStencil)
  	{
  		// Create depth stencil texture
  		ID3D11Texture2D* pDepthStencil = nullptr;
  		D3D11_TEXTURE2D_DESC descDepth;
  		descDepth.Width = backBufferWidth;
  		descDepth.Height = backBufferHeight;
  		descDepth.MipLevels = 1;
  		descDepth.ArraySize = 1;
  		descDepth.Format = pDeviceSettings->d3d11.AutoDepthStencilFormat;
  		descDepth.SampleDesc.Count = pDeviceSettings->d3d11.sd.SampleDesc.Count;
  		descDepth.SampleDesc.Quality = pDeviceSettings->d3d11.sd.SampleDesc.Quality;
  		descDepth.Usage = D3D11_USAGE_DEFAULT;
  		descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
  		descDepth.CPUAccessFlags = 0;
  		descDepth.MiscFlags = 0;
  		hr = pd3dDevice->CreateTexture2D(&descDepth, nullptr, &pDepthStencil);
  		if (FAILED(hr))
  			return hr;
  		DXUT_SetDebugName(pDepthStencil, "DXUT");
  		GetDXUTState().SetD3D11DepthStencil(pDepthStencil);
  
  		// Create the depth stencil view
  		D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
  		descDSV.Format = descDepth.Format;
  		descDSV.Flags = 0;
  		if (descDepth.SampleDesc.Count > 1)
  			descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
  		else
  			descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
  		descDSV.Texture2D.MipSlice = 0;
  		hr = pd3dDevice->CreateDepthStencilView(pDepthStencil, &descDSV, &pDSV);
  		if (FAILED(hr))
  			return hr;
  		DXUT_SetDebugName(pDSV, "DXUT");
  		GetDXUTState().SetD3D11DepthStencilView(pDSV);
  	}
  
  	hr = DXUTSetupD3D11Views(pd3dImmediateContext);
  	if (FAILED(hr))
  		return hr;
  
  	return hr;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Creates the 3D environment
  //--------------------------------------------------------------------------------------
  HRESULT DXUTCreate3DEnvironment11()
  {
  	HRESULT hr = S_OK;
  
  	ID3D11Device* pd3d11Device = nullptr;
  	ID3D11DeviceContext* pd3dImmediateContext = nullptr;
  	D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_1;
  
  	IDXGISwapChain* pSwapChain = nullptr;
  	auto pNewDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  	assert(pNewDeviceSettings);
  	_Analysis_assume_(pNewDeviceSettings);
  
  	auto pDXGIFactory = DXUTGetDXGIFactory();
  	assert(pDXGIFactory);
  	_Analysis_assume_(pDXGIFactory);
  	hr = pDXGIFactory->MakeWindowAssociation(DXUTGetHWND(), 0);
  
  	// Try to create the device with the chosen settings
  	IDXGIAdapter1* pAdapter = nullptr;
  
  	hr = S_OK;
  	D3D_DRIVER_TYPE ddt = pNewDeviceSettings->d3d11.DriverType;
  	if (pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE)
  	{
  		hr = pDXGIFactory->EnumAdapters1(pNewDeviceSettings->d3d11.AdapterOrdinal, &pAdapter);
  		if (FAILED(hr))
  		{
  			return E_FAIL;
  		}
  		ddt = D3D_DRIVER_TYPE_UNKNOWN;
  	}
  	else if (pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_WARP)
  	{
  		ddt = D3D_DRIVER_TYPE_WARP;
  		pAdapter = nullptr;
  	}
  	else if (pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE)
  	{
  		ddt = D3D_DRIVER_TYPE_REFERENCE;
  		pAdapter = nullptr;
  	}
  
  	if (SUCCEEDED(hr))
  	{
  		hr = DXUT_Dynamic_D3D11CreateDevice(pAdapter,
  			ddt,
  			(HMODULE)0,
  			pNewDeviceSettings->d3d11.CreateFlags,
  			&pNewDeviceSettings->d3d11.DeviceFeatureLevel,
  			1,
  			D3D11_SDK_VERSION,
  			&pd3d11Device,
  			&FeatureLevel,
  			&pd3dImmediateContext
  		);
  
  		if (FAILED(hr))
  		{
  			pAdapter = nullptr;
  			// Remote desktop does not allow you to enumerate the adapter.  In this case, we let D3D11 do the enumeration.
  			if (ddt == D3D_DRIVER_TYPE_UNKNOWN)
  			{
  				hr = DXUT_Dynamic_D3D11CreateDevice(pAdapter,
  					D3D_DRIVER_TYPE_HARDWARE,
  					(HMODULE)0,
  					pNewDeviceSettings->d3d11.CreateFlags,
  					&pNewDeviceSettings->d3d11.DeviceFeatureLevel,
  					1,
  					D3D11_SDK_VERSION,
  					&pd3d11Device,
  					&FeatureLevel,
  					&pd3dImmediateContext
  				);
  			}
  			if (FAILED(hr))
  			{
  				DXUT_ERR(L"D3D11CreateDevice", hr);
  				return DXUTERR_CREATINGDEVICE;
  			}
  		}
  	}
  
  #ifndef NDEBUG
  	if (SUCCEEDED(hr))
  	{
  		ID3D11Debug * d3dDebug = nullptr;
  		if (SUCCEEDED(pd3d11Device->QueryInterface(IID_PPV_ARGS(&d3dDebug))))
  		{
  			ID3D11InfoQueue* infoQueue = nullptr;
  			if (SUCCEEDED(d3dDebug->QueryInterface(IID_PPV_ARGS(&infoQueue))))
  			{
  				// ignore some "expected" errors
  				D3D11_MESSAGE_ID denied[] =
  				{
  					D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
  				};
  
  				D3D11_INFO_QUEUE_FILTER filter;
  				memset(&filter, 0, sizeof(filter));
  				filter.DenyList.NumIDs = _countof(denied);
  				filter.DenyList.pIDList = denied;
  				infoQueue->AddStorageFilterEntries(&filter);
  				infoQueue->Release();
  			}
  			d3dDebug->Release();
  		}
  	}
  #endif
  
  	if (SUCCEEDED(hr))
  	{
  		IDXGIDevice1* pDXGIDev = nullptr;
  		hr = pd3d11Device->QueryInterface(IID_PPV_ARGS(&pDXGIDev));
  		if (SUCCEEDED(hr) && pDXGIDev)
  		{
  			if (!pAdapter)
  			{
  				IDXGIAdapter *pTempAdapter = nullptr;
  				V_RETURN(pDXGIDev->GetAdapter(&pTempAdapter));
  				V_RETURN(pTempAdapter->QueryInterface(IID_PPV_ARGS(&pAdapter)));
  				V_RETURN(pAdapter->GetParent(IID_PPV_ARGS(&pDXGIFactory)));
  				SAFE_RELEASE(pTempAdapter);
  				if (GetDXUTState().GetDXGIFactory() != pDXGIFactory)
  					GetDXUTState().GetDXGIFactory()->Release();
  				GetDXUTState().SetDXGIFactory(pDXGIFactory);
  			}
  		}
  		SAFE_RELEASE(pDXGIDev);
  		GetDXUTState().SetDXGIAdapter(pAdapter);
  	}
  
  	if (FAILED(hr))
  	{
  		DXUT_ERR(L"D3D11CreateDevice", hr);
  		return DXUTERR_CREATINGDEVICE;
  	}
  
  	// set default render state to msaa enabled
  	D3D11_RASTERIZER_DESC drd = {
  		D3D11_FILL_SOLID, //D3D11_FILL_MODE FillMode;
  		D3D11_CULL_BACK,//D3D11_CULL_MODE CullMode;
  		FALSE, //BOOL FrontCounterClockwise;
  		0, //INT DepthBias;
  		0.0f,//FLOAT DepthBiasClamp;
  		0.0f,//FLOAT SlopeScaledDepthBias;
  		TRUE,//BOOL DepthClipEnable;
  		FALSE,//BOOL ScissorEnable;
  		TRUE,//BOOL MultisampleEnable;
  		FALSE//BOOL AntialiasedLineEnable;        
  	};
  	ID3D11RasterizerState* pRS = nullptr;
  	hr = pd3d11Device->CreateRasterizerState(&drd, &pRS);
  	if (FAILED(hr))
  	{
  		DXUT_ERR(L"CreateRasterizerState", hr);
  		return DXUTERR_CREATINGDEVICE;
  	}
  	DXUT_SetDebugName(pRS, "DXUT Default");
  	GetDXUTState().SetD3D11RasterizerState(pRS);
  	pd3dImmediateContext->RSSetState(pRS);
  
  	// Enumerate its outputs.
  	UINT OutputCount, iOutput;
  	for (OutputCount = 0; ; ++OutputCount)
  	{
  		IDXGIOutput* pOutput;
  		if (FAILED(pAdapter->EnumOutputs(OutputCount, &pOutput)))
  			break;
  		SAFE_RELEASE(pOutput);
  	}
  	auto ppOutputArray = new (std::nothrow) IDXGIOutput*[OutputCount];
  	if (!ppOutputArray)
  		return E_OUTOFMEMORY;
  	for (iOutput = 0; iOutput < OutputCount; ++iOutput)
  		pAdapter->EnumOutputs(iOutput, ppOutputArray + iOutput);
  	GetDXUTState().SetDXGIOutputArray(ppOutputArray);
  	GetDXUTState().SetDXGIOutputArraySize(OutputCount);
  
  	if (!GetDXUTState().GetHeadlessMode())
  	{
  		// Create the swapchain
  		hr = pDXGIFactory->CreateSwapChain(pd3d11Device, &pNewDeviceSettings->d3d11.sd, &pSwapChain);
  		if (FAILED(hr))
  		{
  			DXUT_ERR(L"CreateSwapChain", hr);
  			return DXUTERR_CREATINGDEVICE;
  		}
  	}
  
  	GetDXUTState().SetD3D11Device(pd3d11Device);
  	GetDXUTState().SetD3D11DeviceContext(pd3dImmediateContext);
  	GetDXUTState().SetD3D11FeatureLevel(FeatureLevel);
  	GetDXUTState().SetDXGISwapChain(pSwapChain);
  
  	assert(pd3d11Device);
  	_Analysis_assume_(pd3d11Device);
  
  	assert(pd3dImmediateContext);
  	_Analysis_assume_(pd3dImmediateContext);
  
  	// Direct3D 11.1
  	{
  		ID3D11Device1* pd3d11Device1 = nullptr;
  		hr = pd3d11Device->QueryInterface(IID_PPV_ARGS(&pd3d11Device1));
  		if (SUCCEEDED(hr) && pd3d11Device1)
  		{
  			GetDXUTState().SetD3D11Device1(pd3d11Device1);
  
  			ID3D11DeviceContext1* pd3dImmediateContext1 = nullptr;
  			hr = pd3dImmediateContext->QueryInterface(IID_PPV_ARGS(&pd3dImmediateContext1));
  			if (SUCCEEDED(hr) && pd3dImmediateContext1)
  			{
  				GetDXUTState().SetD3D11DeviceContext1(pd3dImmediateContext1);
  			}
  		}
  	}
  
  #ifdef USE_DIRECT3D11_2
  	// Direct3D 11.2
  	{
  		ID3D11Device2* pd3d11Device2 = nullptr;
  		hr = pd3d11Device->QueryInterface(IID_PPV_ARGS(&pd3d11Device2));
  		if (SUCCEEDED(hr) && pd3d11Device2)
  		{
  			GetDXUTState().SetD3D11Device2(pd3d11Device2);
  
  			ID3D11DeviceContext2* pd3dImmediateContext2 = nullptr;
  			hr = pd3dImmediateContext->QueryInterface(IID_PPV_ARGS(&pd3dImmediateContext2));
  			if (SUCCEEDED(hr) && pd3dImmediateContext2)
  			{
  				GetDXUTState().SetD3D11DeviceContext2(pd3dImmediateContext2);
  			}
  		}
  	}
  #endif
  
  #ifdef USE_DIRECT3D11_3
  	// Direct3D 11.3
  	{
  		ID3D11Device3* pd3d11Device3 = nullptr;
  		hr = pd3d11Device->QueryInterface(IID_PPV_ARGS(&pd3d11Device3));
  		if (SUCCEEDED(hr) && pd3d11Device3)
  		{
  			GetDXUTState().SetD3D11Device3(pd3d11Device3);
  
  			ID3D11DeviceContext3* pd3dImmediateContext3 = nullptr;
  			hr = pd3dImmediateContext->QueryInterface(IID_PPV_ARGS(&pd3dImmediateContext3));
  			if (SUCCEEDED(hr) && pd3dImmediateContext3)
  			{
  				GetDXUTState().SetD3D11DeviceContext3(pd3dImmediateContext3);
  			}
  		}
  	}
  #endif
  
  	// If switching to REF, set the exit code to 11.  If switching to HAL and exit code was 11, then set it back to 0.
  	if (pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE && GetDXUTState().GetExitCode() == 0)
  		GetDXUTState().SetExitCode(10);
  	else if (pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE && GetDXUTState().GetExitCode() == 10)
  		GetDXUTState().SetExitCode(0);
  
  	// Update back buffer desc before calling app's device callbacks
  	DXUTUpdateBackBufferDesc();
  
  	// Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state)
  	DXUTSetupCursor();
  
  	// Update the device stats text
  	auto pd3dEnum = DXUTGetD3D11Enumeration();
  	assert(pd3dEnum);
  	_Analysis_assume_(pd3dEnum);
  	auto pAdapterInfo = pd3dEnum->GetAdapterInfo(pNewDeviceSettings->d3d11.AdapterOrdinal);
  	DXUTUpdateD3D11DeviceStats(pNewDeviceSettings->d3d11.DriverType, pNewDeviceSettings->d3d11.DeviceFeatureLevel, &pAdapterInfo->AdapterDesc);
  
  	// Call the app's device created callback if non-NULL
  	auto pBackBufferSurfaceDesc = DXUTGetDXGIBackBufferSurfaceDesc();
  	GetDXUTState().SetInsideDeviceCallback(true);
  	auto pCallbackDeviceCreated = GetDXUTState().GetD3D11DeviceCreatedFunc();
  	hr = S_OK;
  	if (pCallbackDeviceCreated)
  		hr = pCallbackDeviceCreated(DXUTGetD3D11Device(), pBackBufferSurfaceDesc,
  			GetDXUTState().GetD3D11DeviceCreatedFuncUserContext());
  	GetDXUTState().SetInsideDeviceCallback(false);
  	if (!DXUTGetD3D11Device()) // Handle DXUTShutdown from inside callback
  		return E_FAIL;
  	if (FAILED(hr))
  	{
  		DXUT_ERR(L"DeviceCreated callback", hr);
  		return (hr == DXUTERR_MEDIANOTFOUND) ? DXUTERR_MEDIANOTFOUND : DXUTERR_CREATINGDEVICEOBJECTS;
  	}
  	GetDXUTState().SetDeviceObjectsCreated(true);
  
  	// Setup the render target view and viewport
  	hr = DXUTCreateD3D11Views(pd3d11Device, pd3dImmediateContext, pNewDeviceSettings);
  	if (FAILED(hr))
  	{
  		DXUT_ERR(L"DXUTCreateD3D11Views", hr);
  		return DXUTERR_CREATINGDEVICEOBJECTS;
  	}
  
  	// Call the app's swap chain reset callback if non-NULL
  	GetDXUTState().SetInsideDeviceCallback(true);
  	LPDXUTCALLBACKD3D11SWAPCHAINRESIZED pCallbackSwapChainResized = GetDXUTState().GetD3D11SwapChainResizedFunc();
  	hr = S_OK;
  	if (pCallbackSwapChainResized)
  		hr = pCallbackSwapChainResized(DXUTGetD3D11Device(), pSwapChain, pBackBufferSurfaceDesc,
  			GetDXUTState().GetD3D11SwapChainResizedFuncUserContext());
  	GetDXUTState().SetInsideDeviceCallback(false);
  	if (!DXUTGetD3D11Device()) // Handle DXUTShutdown from inside callback
  		return E_FAIL;
  	if (FAILED(hr))
  	{
  		DXUT_ERR(L"DeviceReset callback", hr);
  		return (hr == DXUTERR_MEDIANOTFOUND) ? DXUTERR_MEDIANOTFOUND : DXUTERR_RESETTINGDEVICEOBJECTS;
  	}
  	GetDXUTState().SetDeviceObjectsReset(true);
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Resets the 3D environment by:
  //      - Calls the device lost callback 
  //      - Resets the device
  //      - Stores the back buffer description
  //      - Sets up the full screen Direct3D cursor if requested
  //      - Calls the device reset callback 
  //--------------------------------------------------------------------------------------
  HRESULT DXUTReset3DEnvironment11()
  {
  	HRESULT hr;
  
  	GetDXUTState().SetDeviceObjectsReset(false);
  	DXUTPause(true, true);
  
  	bool bDeferredDXGIAction = false;
  	auto pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  	auto pSwapChain = DXUTGetDXGISwapChain();
  	assert(pSwapChain);
  	_Analysis_assume_(pSwapChain);
  
  	DXGI_SWAP_CHAIN_DESC SCDesc;
  	if (FAILED(pSwapChain->GetDesc(&SCDesc)))
  		memset(&SCDesc, 0, sizeof(SCDesc));
  
  	// Resize backbuffer and target of the swapchain in case they have changed.
  	// For windowed mode, use the client rect as the desired size. Unlike D3D9,
  	// we can't use 0 for width or height.  Therefore, fill in the values from
  	// the window size. For fullscreen mode, the width and height should have
  	// already been filled with the desktop resolution, so don't change it.
  	if (pDeviceSettings->d3d11.sd.Windowed && SCDesc.Windowed)
  	{
  		RECT rcWnd;
  		GetClientRect(DXUTGetHWND(), &rcWnd);
  		pDeviceSettings->d3d11.sd.BufferDesc.Width = rcWnd.right - rcWnd.left;
  		pDeviceSettings->d3d11.sd.BufferDesc.Height = rcWnd.bottom - rcWnd.top;
  	}
  
  	// If the app wants to switch from windowed to fullscreen or vice versa,
  	// call the swapchain's SetFullscreenState
  	// mode.
  	if (SCDesc.Windowed != pDeviceSettings->d3d11.sd.Windowed)
  	{
  		// Set the fullscreen state
  		if (pDeviceSettings->d3d11.sd.Windowed)
  		{
  			V_RETURN(pSwapChain->SetFullscreenState(FALSE, nullptr));
  			bDeferredDXGIAction = true;
  		}
  		else
  		{
  			// Set fullscreen state by setting the display mode to fullscreen, then changing the resolution
  			// to the desired value.
  
  			// SetFullscreenState causes a WM_SIZE message to be sent to the window.  The WM_SIZE message calls
  			// DXUTCheckForDXGIBufferChange which normally stores the new height and width in 
  			// pDeviceSettings->d3d11.sd.BufferDesc.  SetDoNotStoreBufferSize tells DXUTCheckForDXGIBufferChange
  			// not to store the height and width so that we have the correct values when calling ResizeTarget.
  
  			GetDXUTState().SetDoNotStoreBufferSize(true);
  			V_RETURN(pSwapChain->SetFullscreenState(TRUE, nullptr));
  			GetDXUTState().SetDoNotStoreBufferSize(false);
  
  			V_RETURN(pSwapChain->ResizeTarget(&pDeviceSettings->d3d11.sd.BufferDesc));
  			bDeferredDXGIAction = true;
  		}
  	}
  	else
  	{
  		if (pDeviceSettings->d3d11.sd.BufferDesc.Width == SCDesc.BufferDesc.Width &&
  			pDeviceSettings->d3d11.sd.BufferDesc.Height == SCDesc.BufferDesc.Height &&
  			pDeviceSettings->d3d11.sd.BufferDesc.Format != SCDesc.BufferDesc.Format)
  		{
  			DXUTResizeDXGIBuffers(0, 0, !pDeviceSettings->d3d11.sd.Windowed);
  			bDeferredDXGIAction = true;
  		}
  		else if (pDeviceSettings->d3d11.sd.BufferDesc.Width != SCDesc.BufferDesc.Width ||
  			pDeviceSettings->d3d11.sd.BufferDesc.Height != SCDesc.BufferDesc.Height)
  		{
  			V_RETURN(pSwapChain->ResizeTarget(&pDeviceSettings->d3d11.sd.BufferDesc));
  			bDeferredDXGIAction = true;
  		}
  	}
  
  	// If no deferred DXGI actions are to take place, mark the device as reset.
  	// If there is a deferred DXGI action, then the device isn't reset until DXGI sends us a 
  	// window message.  Only then can we mark the device as reset.
  	if (!bDeferredDXGIAction)
  		GetDXUTState().SetDeviceObjectsReset(true);
  	DXUTPause(false, false);
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Render the 3D environment by:
  //      - Checking if the device is lost and trying to reset it if it is
  //      - Get the elapsed time since the last frame
  //      - Calling the app's framemove and render callback
  //      - Calling Present()
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTRender3DEnvironment()
  {
  	HRESULT hr;
  
  	auto pd3dDevice = DXUTGetD3D11Device();
  	if (!pd3dDevice)
  		return;
  
  	auto pd3dImmediateContext = DXUTGetD3D11DeviceContext();
  	if (!pd3dImmediateContext)
  		return;
  
  	auto pSwapChain = DXUTGetDXGISwapChain();
  	if (!pSwapChain && !GetDXUTState().GetHeadlessMode())
  		return;
  
  	if (DXUTIsRenderingPaused() || !DXUTIsActive() || GetDXUTState().GetRenderingOccluded())
  	{
  		// Window is minimized/paused/occluded/or not exclusive so yield CPU time to other processes
  		Sleep(50);
  	}
  
  	// Get the app's time, in seconds. Skip rendering if no time elapsed
  	double fTime, fAbsTime; float fElapsedTime;
  	DXUTGetGlobalTimer()->GetTimeValues(&fTime, &fAbsTime, &fElapsedTime);
  
  	// Store the time for the app
  	if (GetDXUTState().GetConstantFrameTime())
  	{
  		fElapsedTime = GetDXUTState().GetTimePerFrame();
  		fTime = DXUTGetTime() + fElapsedTime;
  	}
  
  	GetDXUTState().SetTime(fTime);
  	GetDXUTState().SetAbsoluteTime(fAbsTime);
  	GetDXUTState().SetElapsedTime(fElapsedTime);
  
  	// Update the FPS stats
  	DXUTUpdateFrameStats();
  
  	DXUTHandleTimers();
  
  	// Animate the scene by calling the app's frame move callback
  	LPDXUTCALLBACKFRAMEMOVE pCallbackFrameMove = GetDXUTState().GetFrameMoveFunc();
  	if (pCallbackFrameMove)
  	{
  		pCallbackFrameMove(fTime, fElapsedTime, GetDXUTState().GetFrameMoveFuncUserContext());
  		pd3dDevice = DXUTGetD3D11Device();
  		if (!pd3dDevice) // Handle DXUTShutdown from inside callback
  			return;
  	}
  
  	if (!GetDXUTState().GetRenderingPaused())
  	{
  		// Render the scene by calling the app's render callback
  		LPDXUTCALLBACKD3D11FRAMERENDER pCallbackFrameRender = GetDXUTState().GetD3D11FrameRenderFunc();
  		if (pCallbackFrameRender && !GetDXUTState().GetRenderingOccluded())
  		{
  			pCallbackFrameRender(pd3dDevice, pd3dImmediateContext, fTime, fElapsedTime,
  				GetDXUTState().GetD3D11FrameRenderFuncUserContext());
  
  			pd3dDevice = DXUTGetD3D11Device();
  			if (!pd3dDevice) // Handle DXUTShutdown from inside callback
  				return;
  		}
  
  #if defined(DEBUG) || defined(_DEBUG)
  		// Phong Cao: Disables these since we allow swapchain to have a different size.
  
  		// The back buffer should always match the client rect 
  		// if the Direct3D backbuffer covers the entire window
  		//RECT rcClient;
  		//GetClientRect( DXUTGetHWND(), &rcClient );
  		//if( !IsIconic( DXUTGetHWND() ) )
  		//{
  		//    GetClientRect( DXUTGetHWND(), &rcClient );
  
  		//    assert( DXUTGetDXGIBackBufferSurfaceDesc()->Width == (UINT)rcClient.right );
  		//    assert( DXUTGetDXGIBackBufferSurfaceDesc()->Height == (UINT)rcClient.bottom );
  		//}
  #endif
  	}
  
  	if (GetDXUTState().GetSaveScreenShot())
  	{
  		DXUTSnapD3D11Screenshot(GetDXUTState().GetScreenShotName(), false);
  	}
  	if (GetDXUTState().GetExitAfterScreenShot())
  	{
  		DXUTShutdown();
  		return;
  	}
  
  	DWORD dwFlags = 0;
  	if (GetDXUTState().GetRenderingOccluded())
  		dwFlags = DXGI_PRESENT_TEST;
  	else
  		dwFlags = GetDXUTState().GetCurrentDeviceSettings()->d3d11.PresentFlags;
  	UINT SyncInterval = GetDXUTState().GetCurrentDeviceSettings()->d3d11.SyncInterval;
  
  	if (!GetDXUTState().GetHeadlessMode() && !GetDXUTState().GetNoSwapChainPresent())
  	{
  		// Show the frame on the primary surface.
  		hr = pSwapChain->Present(SyncInterval, dwFlags);
  		if (DXGI_STATUS_OCCLUDED == hr)
  		{
  			// There is a window covering our entire rendering area.
  			// Don't render until we're visible again.
  			GetDXUTState().SetRenderingOccluded(true);
  		}
  		else if (DXGI_ERROR_DEVICE_RESET == hr)
  		{
  			// If a mode change happened, we must reset the device
  			if (FAILED(hr = DXUTReset3DEnvironment11()))
  			{
  				if (DXUTERR_RESETTINGDEVICEOBJECTS == hr ||
  					DXUTERR_MEDIANOTFOUND == hr)
  				{
  					DXUTDisplayErrorMessage(hr);
  					DXUTShutdown();
  					return;
  				}
  				else
  				{
  					// Reset failed, but the device wasn't lost so something bad happened, 
  					// so recreate the device to try to recover
  					auto pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  					if (FAILED(DXUTChangeDevice(pDeviceSettings, false)))
  					{
  						DXUTShutdown();
  						return;
  					}
  
  					// How to handle display orientation changes in full-screen mode?
  				}
  			}
  		}
  		else if (DXGI_ERROR_DEVICE_REMOVED == hr)
  		{
  			// Use a callback to ask the app if it would like to find a new device.  
  			// If no device removed callback is set, then look for a new device
  			if (FAILED(DXUTHandleDeviceRemoved()))
  			{
  				// Perhaps get more information from pD3DDevice->GetDeviceRemovedReason()?
  				DXUTDisplayErrorMessage(DXUTERR_DEVICEREMOVED);
  				DXUTShutdown();
  				return;
  			}
  		}
  		else if (SUCCEEDED(hr))
  		{
  			if (GetDXUTState().GetRenderingOccluded())
  			{
  				// Now that we're no longer occluded
  				// allow us to render again
  				GetDXUTState().SetRenderingOccluded(false);
  			}
  		}
  	}
  
  	// Update current frame #
  	int nFrame = GetDXUTState().GetCurrentFrameNumber();
  	nFrame++;
  	GetDXUTState().SetCurrentFrameNumber(nFrame);
  
  	// Check to see if the app should shutdown due to cmdline
  	if (GetDXUTState().GetOverrideQuitAfterFrame() != 0)
  	{
  		if (nFrame > GetDXUTState().GetOverrideQuitAfterFrame())
  			DXUTShutdown();
  	}
  
  	return;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Cleans up the 3D environment by:
  //      - Calls the device lost callback 
  //      - Calls the device destroyed callback 
  //      - Releases the D3D device
  //--------------------------------------------------------------------------------------
  void DXUTCleanup3DEnvironment(_In_ bool bReleaseSettings)
  {
  	auto pd3dDevice = DXUTGetD3D11Device();
  
  	if (pd3dDevice)
  	{
  		if (GetDXUTState().GetD3D11RasterizerState())
  			GetDXUTState().GetD3D11RasterizerState()->Release();
  
  		// Call the app's SwapChain lost callback
  		GetDXUTState().SetInsideDeviceCallback(true);
  		if (GetDXUTState().GetDeviceObjectsReset())
  		{
  			LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallbackSwapChainReleasing =
  				GetDXUTState().GetD3D11SwapChainReleasingFunc();
  			if (pCallbackSwapChainReleasing)
  				pCallbackSwapChainReleasing(GetDXUTState().GetD3D11SwapChainReleasingFuncUserContext());
  			GetDXUTState().SetDeviceObjectsReset(false);
  		}
  
  		// Release our old depth stencil texture and view 
  		auto pDS = GetDXUTState().GetD3D11DepthStencil();
  		SAFE_RELEASE(pDS);
  		GetDXUTState().SetD3D11DepthStencil(nullptr);
  		auto pDSV = GetDXUTState().GetD3D11DepthStencilView();
  		SAFE_RELEASE(pDSV);
  		GetDXUTState().SetD3D11DepthStencilView(nullptr);
  
  		// Cleanup the render target view
  		auto pRTV = GetDXUTState().GetD3D11RenderTargetView();
  		SAFE_RELEASE(pRTV);
  		GetDXUTState().SetD3D11RenderTargetView(nullptr);
  
  		// Call the app's device destroyed callback
  		if (GetDXUTState().GetDeviceObjectsCreated())
  		{
  			auto pCallbackDeviceDestroyed = GetDXUTState().GetD3D11DeviceDestroyedFunc();
  			if (pCallbackDeviceDestroyed)
  				pCallbackDeviceDestroyed(GetDXUTState().GetD3D11DeviceDestroyedFuncUserContext());
  			GetDXUTState().SetDeviceObjectsCreated(false);
  		}
  
  		GetDXUTState().SetInsideDeviceCallback(false);
  
  		// Release the swap chain
  		GetDXUTState().SetReleasingSwapChain(true);
  		auto pSwapChain = DXUTGetDXGISwapChain();
  		if (pSwapChain)
  		{
  			pSwapChain->SetFullscreenState(FALSE, 0);
  		}
  		SAFE_RELEASE(pSwapChain);
  		GetDXUTState().SetDXGISwapChain(nullptr);
  		GetDXUTState().SetReleasingSwapChain(false);
  
  		// Release the outputs.
  		auto ppOutputArray = GetDXUTState().GetDXGIOutputArray();
  		UINT OutputCount = GetDXUTState().GetDXGIOutputArraySize();
  		for (UINT o = 0; o < OutputCount; ++o)
  			SAFE_RELEASE(ppOutputArray[o]);
  		delete[] ppOutputArray;
  		GetDXUTState().SetDXGIOutputArray(nullptr);
  		GetDXUTState().SetDXGIOutputArraySize(0);
  
  		// Release the D3D adapter.
  		auto pAdapter = GetDXUTState().GetDXGIAdapter();
  		SAFE_RELEASE(pAdapter);
  		GetDXUTState().SetDXGIAdapter(nullptr);
  
  		// Call ClearState to avoid tons of messy debug spew telling us that we're deleting bound objects
  		auto pImmediateContext = DXUTGetD3D11DeviceContext();
  		assert(pImmediateContext);
  		pImmediateContext->ClearState();
  		pImmediateContext->Flush();
  
  		// Release the D3D11 immediate context (if it exists) because it has a extra ref count on it
  		SAFE_RELEASE(pImmediateContext);
  		GetDXUTState().SetD3D11DeviceContext(nullptr);
  
  		auto pImmediateContext1 = DXUTGetD3D11DeviceContext1();
  		SAFE_RELEASE(pImmediateContext1);
  		GetDXUTState().SetD3D11DeviceContext1(nullptr);
  
  #ifdef USE_DIRECT3D11_2
  		auto pImmediateContext2 = DXUTGetD3D11DeviceContext2();
  		SAFE_RELEASE(pImmediateContext2);
  		GetDXUTState().SetD3D11DeviceContext2(nullptr);
  #endif
  
  #ifdef USE_DIRECT3D11_3
  		auto pImmediateContext3 = DXUTGetD3D11DeviceContext3();
  		SAFE_RELEASE(pImmediateContext3);
  		GetDXUTState().SetD3D11DeviceContext3(nullptr);
  #endif
  
  		// Report live objects
  		if (pd3dDevice)
  		{
  #ifndef NDEBUG
  			ID3D11Debug * d3dDebug = nullptr;
  			if (SUCCEEDED(pd3dDevice->QueryInterface(IID_PPV_ARGS(&d3dDebug))))
  			{
  				d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
  				d3dDebug->Release();
  			}
  #endif
  
  			auto pd3dDevice1 = DXUTGetD3D11Device1();
  			SAFE_RELEASE(pd3dDevice1);
  			GetDXUTState().SetD3D11Device1(nullptr);
  
  #ifdef USE_DIRECT3D11_2
  			auto pd3dDevice2 = DXUTGetD3D11Device2();
  			SAFE_RELEASE(pd3dDevice2);
  			GetDXUTState().SetD3D11Device2(nullptr);
  #endif
  
  #ifdef USE_DIRECT3D11_3
  			auto pd3dDevice3 = DXUTGetD3D11Device3();
  			SAFE_RELEASE(pd3dDevice3);
  			GetDXUTState().SetD3D11Device3(nullptr);
  #endif
  
  			// Release the D3D device and in debug configs, displays a message box if there 
  			// are unrelease objects.
  			UINT references = pd3dDevice->Release();
  			if (references > 0)
  			{
  				DXUTDisplayErrorMessage(DXUTERR_NONZEROREFCOUNT);
  				DXUT_ERR(L"DXUTCleanup3DEnvironment", DXUTERR_NONZEROREFCOUNT);
  			}
  		}
  		GetDXUTState().SetD3D11Device(nullptr);
  
  #ifndef NDEBUG
  		{
  			IDXGIDebug* dxgiDebug = nullptr;
  			if (SUCCEEDED(DXUT_Dynamic_DXGIGetDebugInterface(IID_IDXGIDebug, reinterpret_cast<void**>(&dxgiDebug))))
  			{
  				dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
  				dxgiDebug->Release();
  			}
  		}
  #endif
  
  		if (bReleaseSettings)
  		{
  			auto pOldDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  			SAFE_DELETE(pOldDeviceSettings);
  			GetDXUTState().SetCurrentDeviceSettings(nullptr);
  		}
  
  		auto pBackBufferSurfaceDesc = GetDXUTState().GetBackBufferSurfaceDescDXGI();
  		ZeroMemory(pBackBufferSurfaceDesc, sizeof(DXGI_SURFACE_DESC));
  
  		GetDXUTState().SetDeviceCreated(false);
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Low level keyboard hook to disable Windows key to prevent accidental task switching.  
  //--------------------------------------------------------------------------------------
  LRESULT CALLBACK DXUTLowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
  {
  	if (nCode < 0 || nCode != HC_ACTION)  // do not process message 
  		return CallNextHookEx(GetDXUTState().GetKeyboardHook(), nCode, wParam, lParam);
  
  	bool bEatKeystroke = false;
  	auto p = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
  	switch (wParam)
  	{
  	case WM_KEYDOWN:
  	case WM_KEYUP:
  	{
  		bEatKeystroke = (!GetDXUTState().GetAllowShortcutKeys() &&
  			(p->vkCode == VK_LWIN || p->vkCode == VK_RWIN));
  		break;
  	}
  	}
  
  	if (bEatKeystroke)
  		return 1;
  	else
  		return CallNextHookEx(GetDXUTState().GetKeyboardHook(), nCode, wParam, lParam);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Controls how DXUT behaves when fullscreen and windowed mode with regard to 
  // shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) 
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  void WINAPI DXUTSetShortcutKeySettings(bool bAllowWhenFullscreen, bool bAllowWhenWindowed)
  {
  	GetDXUTState().SetAllowShortcutKeysWhenWindowed(bAllowWhenWindowed);
  	GetDXUTState().SetAllowShortcutKeysWhenFullscreen(bAllowWhenFullscreen);
  
  	// DXUTInit() records initial accessibility states so don't change them until then
  	if (GetDXUTState().GetDXUTInited())
  	{
  		if (DXUTIsWindowed())
  			DXUTAllowShortcutKeys(GetDXUTState().GetAllowShortcutKeysWhenWindowed());
  		else
  			DXUTAllowShortcutKeys(GetDXUTState().GetAllowShortcutKeysWhenFullscreen());
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Enables/disables Windows keys, and disables or restores the StickyKeys/ToggleKeys/FilterKeys 
  // shortcut to help prevent accidental task switching
  //--------------------------------------------------------------------------------------
  void DXUTAllowShortcutKeys(_In_ bool bAllowKeys)
  {
  	GetDXUTState().SetAllowShortcutKeys(bAllowKeys);
  
  	if (bAllowKeys)
  	{
  		// Restore StickyKeys/etc to original state and enable Windows key      
  		STICKYKEYS sk = GetDXUTState().GetStartupStickyKeys();
  		TOGGLEKEYS tk = GetDXUTState().GetStartupToggleKeys();
  		FILTERKEYS fk = GetDXUTState().GetStartupFilterKeys();
  
  		SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &sk, 0);
  		SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tk, 0);
  		SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &fk, 0);
  
  		// Remove the keyboard hoook when it isn't needed to prevent any slow down of other apps
  		if (GetDXUTState().GetKeyboardHook())
  		{
  			UnhookWindowsHookEx(GetDXUTState().GetKeyboardHook());
  			GetDXUTState().SetKeyboardHook(nullptr);
  		}
  	}
  	else
  	{
  		// Set low level keyboard hook if haven't already
  		if (!GetDXUTState().GetKeyboardHook())
  		{
  			// Set the low-level hook procedure.
  			HHOOK hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, DXUTLowLevelKeyboardProc,
  				GetModuleHandle(nullptr), 0);
  			GetDXUTState().SetKeyboardHook(hKeyboardHook);
  		}
  
  		// Disable StickyKeys/etc shortcuts but if the accessibility feature is on, 
  		// then leave the settings alone as its probably being usefully used
  
  		STICKYKEYS skOff = GetDXUTState().GetStartupStickyKeys();
  		if ((skOff.dwFlags & SKF_STICKYKEYSON) == 0)
  		{
  			// Disable the hotkey and the confirmation
  			skOff.dwFlags &= ~SKF_HOTKEYACTIVE;
  			skOff.dwFlags &= ~SKF_CONFIRMHOTKEY;
  
  			SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &skOff, 0);
  		}
  
  		TOGGLEKEYS tkOff = GetDXUTState().GetStartupToggleKeys();
  		if ((tkOff.dwFlags & TKF_TOGGLEKEYSON) == 0)
  		{
  			// Disable the hotkey and the confirmation
  			tkOff.dwFlags &= ~TKF_HOTKEYACTIVE;
  			tkOff.dwFlags &= ~TKF_CONFIRMHOTKEY;
  
  			SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tkOff, 0);
  		}
  
  		FILTERKEYS fkOff = GetDXUTState().GetStartupFilterKeys();
  		if ((fkOff.dwFlags & FKF_FILTERKEYSON) == 0)
  		{
  			// Disable the hotkey and the confirmation
  			fkOff.dwFlags &= ~FKF_HOTKEYACTIVE;
  			fkOff.dwFlags &= ~FKF_CONFIRMHOTKEY;
  
  			SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &fkOff, 0);
  		}
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Pauses time or rendering.  Keeps a ref count so pausing can be layered
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  void WINAPI DXUTPause(bool bPauseTime, bool bPauseRendering)
  {
  	int nPauseTimeCount = GetDXUTState().GetPauseTimeCount();
  	if (bPauseTime) nPauseTimeCount++;
  	else
  		nPauseTimeCount--;
  	if (nPauseTimeCount < 0) nPauseTimeCount = 0;
  	GetDXUTState().SetPauseTimeCount(nPauseTimeCount);
  
  	int nPauseRenderingCount = GetDXUTState().GetPauseRenderingCount();
  	if (bPauseRendering) nPauseRenderingCount++;
  	else
  		nPauseRenderingCount--;
  	if (nPauseRenderingCount < 0) nPauseRenderingCount = 0;
  	GetDXUTState().SetPauseRenderingCount(nPauseRenderingCount);
  
  	if (nPauseTimeCount > 0)
  	{
  		// Stop the scene from animating
  		DXUTGetGlobalTimer()->Stop();
  	}
  	else
  	{
  		// Restart the timer
  		DXUTGetGlobalTimer()->Start();
  	}
  
  	GetDXUTState().SetRenderingPaused(nPauseRenderingCount > 0);
  	GetDXUTState().SetTimePaused(nPauseTimeCount > 0);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Starts a user defined timer callback
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT WINAPI DXUTSetTimer(LPDXUTCALLBACKTIMER pCallbackTimer, float fTimeoutInSecs, UINT* pnIDEvent,
  	void* pCallbackUserContext)
  {
  	if (!pCallbackTimer)
  		return DXUT_ERR_MSGBOX(L"DXUTSetTimer", E_INVALIDARG);
  
  	DXUT_TIMER DXUTTimer;
  	DXUTTimer.pCallbackTimer = pCallbackTimer;
  	DXUTTimer.pCallbackUserContext = pCallbackUserContext;
  	DXUTTimer.fTimeoutInSecs = fTimeoutInSecs;
  	DXUTTimer.fCountdown = fTimeoutInSecs;
  	DXUTTimer.bEnabled = true;
  	DXUTTimer.nID = GetDXUTState().GetTimerLastID() + 1;
  	GetDXUTState().SetTimerLastID(DXUTTimer.nID);
  
  	auto pTimerList = GetDXUTState().GetTimerList();
  	if (!pTimerList)
  	{
  		pTimerList = new (std::nothrow) std::vector<DXUT_TIMER>;
  		if (!pTimerList)
  			return E_OUTOFMEMORY;
  		GetDXUTState().SetTimerList(pTimerList);
  	}
  
  	pTimerList->push_back(DXUTTimer);
  
  	if (pnIDEvent)
  		*pnIDEvent = DXUTTimer.nID;
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Stops a user defined timer callback
  //--------------------------------------------------------------------------------------
  HRESULT WINAPI DXUTKillTimer(_In_ UINT nIDEvent)
  {
  	auto pTimerList = GetDXUTState().GetTimerList();
  	if (!pTimerList)
  		return S_FALSE;
  
  	bool bFound = false;
  
  	for (auto it = pTimerList->begin(); it != pTimerList->end(); ++it)
  	{
  		DXUT_TIMER DXUTTimer = *it;
  		if (DXUTTimer.nID == nIDEvent)
  		{
  			DXUTTimer.bEnabled = false;
  			*it = DXUTTimer;
  			bFound = true;
  			break;
  		}
  	}
  
  	if (!bFound)
  		return DXUT_ERR_MSGBOX(L"DXUTKillTimer", E_INVALIDARG);
  
  	return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Internal helper function to handle calling the user defined timer callbacks
  //--------------------------------------------------------------------------------------
  void DXUTHandleTimers()
  {
  	float fElapsedTime = DXUTGetElapsedTime();
  
  	auto pTimerList = GetDXUTState().GetTimerList();
  	if (!pTimerList)
  		return;
  
  	// Walk through the list of timer callbacks
  	for (auto it = pTimerList->begin(); it != pTimerList->end(); ++it)
  	{
  		DXUT_TIMER DXUTTimer = *it;
  		if (DXUTTimer.bEnabled)
  		{
  			DXUTTimer.fCountdown -= fElapsedTime;
  
  			// Call the callback if count down expired
  			if (DXUTTimer.fCountdown < 0)
  			{
  				DXUTTimer.pCallbackTimer(DXUTTimer.nID, DXUTTimer.pCallbackUserContext);
  				// The callback my have changed the timer.
  				DXUTTimer = *it;
  				DXUTTimer.fCountdown = DXUTTimer.fTimeoutInSecs;
  			}
  			*it = DXUTTimer;
  		}
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Display an custom error msg box 
  //--------------------------------------------------------------------------------------
  void DXUTDisplayErrorMessage(_In_ HRESULT hr)
  {
  	WCHAR strBuffer[512];
  
  	int nExitCode;
  	bool bFound = true;
  	switch (hr)
  	{
  	case DXUTERR_NODIRECT3D:
  	{
  		nExitCode = 2;
  		wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"Could not initialize Direct3D 11. ");
  		break;
  	}
  	case DXUTERR_NOCOMPATIBLEDEVICES:
  		nExitCode = 3;
  		if (GetSystemMetrics(SM_REMOTESESSION) != 0)
  			wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"Direct3D does not work over a remote session.");
  		else
  			wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"Could not find any compatible Direct3D devices.");
  		break;
  	case DXUTERR_MEDIANOTFOUND:          nExitCode = 4; wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"Could not find required media."); break;
  	case DXUTERR_NONZEROREFCOUNT:        nExitCode = 5; wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"The Direct3D device has a non-zero reference count, meaning some objects were not released."); break;
  	case DXUTERR_CREATINGDEVICE:         nExitCode = 6; wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"Failed creating the Direct3D device."); break;
  	case DXUTERR_RESETTINGDEVICE:        nExitCode = 7; wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"Failed resetting the Direct3D device."); break;
  	case DXUTERR_CREATINGDEVICEOBJECTS:  nExitCode = 8; wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"An error occurred in the device create callback function."); break;
  	case DXUTERR_RESETTINGDEVICEOBJECTS: nExitCode = 9; wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"An error occurred in the device reset callback function."); break;
  		// nExitCode 10 means the app exited using a REF device 
  	case DXUTERR_DEVICEREMOVED:          nExitCode = 11; wcscpy_s(strBuffer, ARRAYSIZE(strBuffer), L"The Direct3D device was removed."); break;
  	default: bFound = false; nExitCode = 1; break; // nExitCode 1 means the API was incorrectly called
  
  	}
  
  	GetDXUTState().SetExitCode(nExitCode);
  
  	bool bShowMsgBoxOnError = GetDXUTState().GetShowMsgBoxOnError();
  	if (bFound && bShowMsgBoxOnError)
  	{
  		if (DXUTGetWindowTitle()[0] == 0)
  			MessageBox(DXUTGetHWND(), strBuffer, L"DXUT Application", MB_ICONERROR | MB_OK);
  		else
  			MessageBox(DXUTGetHWND(), strBuffer, DXUTGetWindowTitle(), MB_ICONERROR | MB_OK);
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Internal function to map MK_* to an array index
  //--------------------------------------------------------------------------------------
  int DXUTMapButtonToArrayIndex(_In_ BYTE vButton)
  {
  	switch (vButton)
  	{
  	case MK_LBUTTON:
  		return 0;
  	case VK_MBUTTON:
  	case MK_MBUTTON:
  		return 1;
  	case MK_RBUTTON:
  		return 2;
  	case VK_XBUTTON1:
  	case MK_XBUTTON1:
  		return 3;
  	case VK_XBUTTON2:
  	case MK_XBUTTON2:
  		return 4;
  	}
  
  	return 0;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Toggle between full screen and windowed
  //--------------------------------------------------------------------------------------
  HRESULT WINAPI DXUTToggleFullScreen()
  {
  	auto deviceSettings = DXUTGetDeviceSettings();
  	if (deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_WARP)
  	{
  		// WARP driver type doesn't support fullscreen
  		return S_FALSE;
  	}
  
  	auto orginalDeviceSettings = DXUTGetDeviceSettings();
  
  	deviceSettings.d3d11.sd.Windowed = !deviceSettings.d3d11.sd.Windowed;
  
  	HRESULT hr;
  	if (!deviceSettings.d3d11.sd.Windowed)
  	{
  		DXGI_MODE_DESC adapterDesktopDisplayMode;
  		hr = DXUTGetD3D11AdapterDisplayMode(deviceSettings.d3d11.AdapterOrdinal, 0, &adapterDesktopDisplayMode);
  		if (FAILED(hr))
  		{
  			static const DXGI_MODE_DESC s_adapterDesktopDisplayMode =
  			{
  				800, 600, { 0, 0 }, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
  			};
  			memcpy(&adapterDesktopDisplayMode, &s_adapterDesktopDisplayMode, sizeof(DXGI_MODE_DESC));
  		}
  
  		deviceSettings.d3d11.sd.BufferDesc = adapterDesktopDisplayMode;
  	}
  	else
  	{
  		RECT r = DXUTGetWindowClientRectAtModeChange();
  		deviceSettings.d3d11.sd.BufferDesc.Height = r.bottom;
  		deviceSettings.d3d11.sd.BufferDesc.Width = r.right;
  	}
  
  	hr = DXUTChangeDevice(&deviceSettings, false);
  
  	// If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed
  	if (FAILED(hr) && (hr != E_ABORT))
  	{
  		// Failed creating device, try to switch back.
  		HRESULT hr2 = DXUTChangeDevice(&orginalDeviceSettings, false);
  		if (FAILED(hr2))
  		{
  			// If this failed, then shutdown
  			DXUTShutdown();
  		}
  	}
  
  	return hr;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Toggle between HAL/REF and WARP
  //--------------------------------------------------------------------------------------
  HRESULT WINAPI DXUTToggleWARP()
  {
  	auto deviceSettings = DXUTGetDeviceSettings();
  
  	if (deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE || deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE)
  	{
  		if (!deviceSettings.d3d11.sd.Windowed)
  		{
  			// WARP driver type doesn't support fullscreen
  			return S_FALSE;
  		}
  
  		deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_WARP;
  	}
  	else if (deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_WARP)
  	{
  		deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE;
  	}
  
  	HRESULT hr = DXUTSnapDeviceSettingsToEnumDevice(&deviceSettings, false);
  	if (SUCCEEDED(hr))
  	{
  		DXUTDeviceSettings orginalDeviceSettings = DXUTGetDeviceSettings();
  
  		// Create a Direct3D device using the new device settings.  
  		// If there is an existing device, then it will either reset or recreate the scene.
  		hr = DXUTChangeDevice(&deviceSettings, false);
  
  		// If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed
  		if (FAILED(hr) && (hr != E_ABORT))
  		{
  			// Failed creating device, try to switch back.
  			HRESULT hr2 = DXUTChangeDevice(&orginalDeviceSettings, false);
  			if (FAILED(hr2))
  			{
  				// If this failed, then shutdown
  				DXUTShutdown();
  			}
  		}
  	}
  
  	return hr;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Toggle between HAL/WARP and REF
  //--------------------------------------------------------------------------------------
  HRESULT WINAPI DXUTToggleREF()
  {
  	auto deviceSettings = DXUTGetDeviceSettings();
  
  	if (deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE)
  	{
  		deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_REFERENCE;
  	}
  	else if (deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE)
  	{
  		deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE;
  	}
  	else if (deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_WARP)
  	{
  		if (!deviceSettings.d3d11.sd.Windowed)
  		{
  			// WARP driver type doesn't support fullscreen
  			return S_FALSE;
  		}
  
  		deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_REFERENCE;
  	}
  
  	HRESULT hr = DXUTSnapDeviceSettingsToEnumDevice(&deviceSettings, false);
  	if (SUCCEEDED(hr))
  	{
  		auto orginalDeviceSettings = DXUTGetDeviceSettings();
  
  		// Create a Direct3D device using the new device settings.  
  		// If there is an existing device, then it will either reset or recreate the scene.
  		hr = DXUTChangeDevice(&deviceSettings, false);
  
  		// If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed
  		if (FAILED(hr) && (hr != E_ABORT))
  		{
  			// Failed creating device, try to switch back.
  			HRESULT hr2 = DXUTChangeDevice(&orginalDeviceSettings, false);
  			if (FAILED(hr2))
  			{
  				// If this failed, then shutdown
  				DXUTShutdown();
  			}
  		}
  	}
  
  	return hr;
  }
  
  //--------------------------------------------------------------------------------------
  // Checks to see if DXGI has switched us out of fullscreen or windowed mode
  //--------------------------------------------------------------------------------------
  void DXUTCheckForDXGIFullScreenSwitch()
  {
  	auto pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  	auto pSwapChain = DXUTGetDXGISwapChain();
  	assert(pSwapChain);
  	_Analysis_assume_(pSwapChain);
  	DXGI_SWAP_CHAIN_DESC SCDesc;
  	if (FAILED(pSwapChain->GetDesc(&SCDesc)))
  		memset(&SCDesc, 0, sizeof(SCDesc));
  
  	BOOL bIsWindowed = (BOOL)DXUTIsWindowed();
  	if (bIsWindowed != SCDesc.Windowed)
  	{
  		pDeviceSettings->d3d11.sd.Windowed = SCDesc.Windowed;
  
  		auto deviceSettings = DXUTGetDeviceSettings();
  
  		if (bIsWindowed)
  		{
  			GetDXUTState().SetWindowBackBufferWidthAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Width);
  			GetDXUTState().SetWindowBackBufferHeightAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Height);
  		}
  		else
  		{
  			GetDXUTState().SetFullScreenBackBufferWidthAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Width);
  			GetDXUTState().SetFullScreenBackBufferHeightAtModeChange(deviceSettings.d3d11.sd.BufferDesc.Height);
  		}
  	}
  }
  
  _Use_decl_annotations_
  void DXUTResizeDXGIBuffers(UINT Width, UINT Height, BOOL bFullScreen)
  {
  	HRESULT hr = S_OK;
  	RECT rcCurrentClient;
  	GetClientRect(DXUTGetHWND(), &rcCurrentClient);
  
  	auto pDevSettings = GetDXUTState().GetCurrentDeviceSettings();
  	assert(pDevSettings);
  	_Analysis_assume_(pDevSettings);
  
  	auto pSwapChain = DXUTGetDXGISwapChain();
  
  	auto pd3dDevice = DXUTGetD3D11Device();
  	assert(pd3dDevice);
  	_Analysis_assume_(pd3dDevice);
  
  	auto pd3dImmediateContext = DXUTGetD3D11DeviceContext();
  	assert(pd3dImmediateContext);
  	_Analysis_assume_(pd3dImmediateContext);
  
  	// Determine if we're fullscreen
  	pDevSettings->d3d11.sd.Windowed = !bFullScreen;
  
  	// Call releasing
  	GetDXUTState().SetInsideDeviceCallback(true);
  	LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallbackSwapChainReleasing = GetDXUTState().GetD3D11SwapChainReleasingFunc();
  	if (pCallbackSwapChainReleasing)
  		pCallbackSwapChainReleasing(GetDXUTState().GetD3D11SwapChainResizedFuncUserContext());
  	GetDXUTState().SetInsideDeviceCallback(false);
  
  	// Release our old depth stencil texture and view 
  	auto pDS = GetDXUTState().GetD3D11DepthStencil();
  	SAFE_RELEASE(pDS);
  	GetDXUTState().SetD3D11DepthStencil(nullptr);
  	auto pDSV = GetDXUTState().GetD3D11DepthStencilView();
  	SAFE_RELEASE(pDSV);
  	GetDXUTState().SetD3D11DepthStencilView(nullptr);
  
  	// Release our old render target view
  	if (!GetDXUTState().GetHeadlessMode())
  	{
  		auto pRTV = GetDXUTState().GetD3D11RenderTargetView();
  		SAFE_RELEASE(pRTV);
  	}
  
  	GetDXUTState().SetD3D11RenderTargetView(nullptr);
  
  	// Alternate between 0 and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH when resizing buffers.
  	// When in windowed mode, we want 0 since this allows the app to change to the desktop
  	// resolution from windowed mode during alt+enter.  However, in fullscreen mode, we want
  	// the ability to change display modes from the Device Settings dialog.  Therefore, we
  	// want to set the DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH flag.
  	UINT Flags = 0;
  	if (bFullScreen)
  		Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
  
  	if (!GetDXUTState().GetHeadlessMode())
  	{
  		// ResizeBuffers
  		V(pSwapChain->ResizeBuffers(pDevSettings->d3d11.sd.BufferCount,
  			Width,
  			Height,
  			pDevSettings->d3d11.sd.BufferDesc.Format,
  			Flags));
  	}
  
  	if (!GetDXUTState().GetDoNotStoreBufferSize())
  	{
  		// Phong Cao: We should store the resized buffer not the current window size.
  		//pDevSettings->d3d11.sd.BufferDesc.Width = ( UINT )rcCurrentClient.right;
  		//pDevSettings->d3d11.sd.BufferDesc.Height = ( UINT )rcCurrentClient.bottom;
  		pDevSettings->d3d11.sd.BufferDesc.Width = Width;
  		pDevSettings->d3d11.sd.BufferDesc.Height = Height;
  	}
  
  	// Save off backbuffer desc
  	DXUTUpdateBackBufferDesc();
  
  	// Update the device stats text
  	DXUTUpdateStaticFrameStats();
  
  	// Setup the render target view and viewport
  	hr = DXUTCreateD3D11Views(pd3dDevice, pd3dImmediateContext, pDevSettings);
  	if (FAILED(hr))
  	{
  		DXUT_ERR(L"DXUTCreateD3D11Views", hr);
  		return;
  	}
  
  	// Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state)
  	DXUTSetupCursor();
  
  	// Call the app's SwapChain reset callback
  	GetDXUTState().SetInsideDeviceCallback(true);
  	auto pBackBufferSurfaceDesc = DXUTGetDXGIBackBufferSurfaceDesc();
  	LPDXUTCALLBACKD3D11SWAPCHAINRESIZED pCallbackSwapChainResized = GetDXUTState().GetD3D11SwapChainResizedFunc();
  	hr = S_OK;
  	if (pCallbackSwapChainResized)
  		hr = pCallbackSwapChainResized(pd3dDevice, pSwapChain, pBackBufferSurfaceDesc,
  			GetDXUTState().GetD3D11SwapChainResizedFuncUserContext());
  	GetDXUTState().SetInsideDeviceCallback(false);
  	if (FAILED(hr))
  	{
  		// If callback failed, cleanup
  		DXUT_ERR(L"DeviceResetCallback", hr);
  		if (hr != DXUTERR_MEDIANOTFOUND)
  			hr = DXUTERR_RESETTINGDEVICEOBJECTS;
  
  		GetDXUTState().SetInsideDeviceCallback(true);
  		pCallbackSwapChainReleasing =
  			GetDXUTState().GetD3D11SwapChainReleasingFunc();
  		if (pCallbackSwapChainReleasing)
  			pCallbackSwapChainReleasing(GetDXUTState().GetD3D11SwapChainResizedFuncUserContext());
  		GetDXUTState().SetInsideDeviceCallback(false);
  		DXUTPause(false, false);
  		PostQuitMessage(0);
  	}
  	else
  	{
  		GetDXUTState().SetDeviceObjectsReset(true);
  		DXUTPause(false, false);
  	}
  }
  
  //--------------------------------------------------------------------------------------
  // Checks if DXGI buffers need to change
  //--------------------------------------------------------------------------------------
  void DXUTCheckForDXGIBufferChange()
  {
  	if (DXUTGetDXGISwapChain() && !GetDXUTState().GetReleasingSwapChain())
  	{
  		//DXUTgetdxgi
  		auto pSwapChain = DXUTGetDXGISwapChain();
  		assert(pSwapChain);
  		_Analysis_assume_(pSwapChain);
  
  		// workaround for SAL bug in DXGI header
  #pragma warning(push)
  #pragma warning( disable:4616 6309 6387 )
  		// Determine if we're fullscreen
  		BOOL bFullScreen;
  		if (FAILED(pSwapChain->GetFullscreenState(&bFullScreen, nullptr)))
  			bFullScreen = FALSE;
  #pragma warning(pop)
  
  		DXUTResizeDXGIBuffers(0, 0, bFullScreen);
  
  		ShowWindow(DXUTGetHWND(), SW_SHOW);
  	}
  }
  
  //--------------------------------------------------------------------------------------
  // Checks if the window client rect has changed and if it has, then reset the device
  //--------------------------------------------------------------------------------------
  void DXUTCheckForWindowSizeChange()
  {
  	// Skip the check for various reasons
  
  	if (GetDXUTState().GetIgnoreSizeChange() || !GetDXUTState().GetDeviceCreated())
  		return;
  
  	DXUTCheckForDXGIBufferChange();
  }
  
  
  //--------------------------------------------------------------------------------------
  // Checks to see if the HWND changed monitors, and if it did it creates a device 
  // from the monitor's adapter and recreates the scene.
  //--------------------------------------------------------------------------------------
  void DXUTCheckForWindowChangingMonitors()
  {
  	// Skip this check for various reasons
  	if (!GetDXUTState().GetAutoChangeAdapter() ||
  		GetDXUTState().GetIgnoreSizeChange() || !GetDXUTState().GetDeviceCreated() || !DXUTIsWindowed())
  		return;
  
  	HRESULT hr;
  	HMONITOR hWindowMonitor = DXUTMonitorFromWindow(DXUTGetHWND(), MONITOR_DEFAULTTOPRIMARY);
  	HMONITOR hAdapterMonitor = GetDXUTState().GetAdapterMonitor();
  	if (hWindowMonitor != hAdapterMonitor)
  	{
  		UINT newOrdinal;
  		if (SUCCEEDED(DXUTGetAdapterOrdinalFromMonitor(hWindowMonitor, &newOrdinal)))
  		{
  			// Find the closest valid device settings with the new ordinal
  			auto deviceSettings = DXUTGetDeviceSettings();
  			deviceSettings.d3d11.AdapterOrdinal = newOrdinal;
  			UINT newOutput;
  			if (SUCCEEDED(DXUTGetOutputOrdinalFromMonitor(hWindowMonitor, &newOutput)))
  				deviceSettings.d3d11.Output = newOutput;
  
  			hr = DXUTSnapDeviceSettingsToEnumDevice(&deviceSettings, false);
  			if (SUCCEEDED(hr))
  			{
  				// Create a Direct3D device using the new device settings.  
  				// If there is an existing device, then it will either reset or recreate the scene.
  				hr = DXUTChangeDevice(&deviceSettings, false);
  
  				// If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback
  				if (hr == E_ABORT)
  				{
  					// so nothing changed and keep from attempting to switch adapters next time
  					GetDXUTState().SetAutoChangeAdapter(false);
  				}
  				else if (FAILED(hr))
  				{
  					DXUTShutdown();
  					DXUTPause(false, false);
  					return;
  				}
  			}
  		}
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Returns the HMONITOR attached to an adapter/output
  //--------------------------------------------------------------------------------------
  HMONITOR DXUTGetMonitorFromAdapter(_In_ DXUTDeviceSettings* pDeviceSettings)
  {
  	auto pD3DEnum = DXUTGetD3D11Enumeration();
  	assert(pD3DEnum);
  	_Analysis_assume_(pD3DEnum);
  	auto pOutputInfo = pD3DEnum->GetOutputInfo(pDeviceSettings->d3d11.AdapterOrdinal,
  		pDeviceSettings->d3d11.Output);
  	if (!pOutputInfo)
  		return 0;
  	return DXUTMonitorFromRect(&pOutputInfo->Desc.DesktopCoordinates, MONITOR_DEFAULTTONEAREST);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Look for an adapter ordinal that is tied to a HMONITOR
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT DXUTGetAdapterOrdinalFromMonitor(HMONITOR hMonitor, UINT* pAdapterOrdinal)
  {
  	*pAdapterOrdinal = 0;
  
  	// Get the monitor handle information
  	MONITORINFOEX mi;
  	mi.cbSize = sizeof(MONITORINFOEX);
  	DXUTGetMonitorInfo(hMonitor, &mi);
  
  	// Search for this monitor in our enumeration hierarchy.
  	auto pd3dEnum = DXUTGetD3D11Enumeration();
  	auto pAdapterList = pd3dEnum->GetAdapterInfoList();
  	for (auto it = pAdapterList->cbegin(); it != pAdapterList->cend(); ++it)
  	{
  		auto pAdapterInfo = *it;
  		for (auto jit = pAdapterInfo->outputInfoList.cbegin(); jit != pAdapterInfo->outputInfoList.cend(); ++jit)
  		{
  			auto pOutputInfo = *jit;
  			// Convert output device name from MBCS to Unicode
  			if (wcsncmp(pOutputInfo->Desc.DeviceName, mi.szDevice, sizeof(mi.szDevice) / sizeof
  			(mi.szDevice[0])) == 0)
  			{
  				*pAdapterOrdinal = pAdapterInfo->AdapterOrdinal;
  				return S_OK;
  			}
  		}
  	}
  	return E_FAIL;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Look for a monitor ordinal that is tied to a HMONITOR (D3D11-only)
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT DXUTGetOutputOrdinalFromMonitor(HMONITOR hMonitor, UINT* pOutputOrdinal)
  {
  	// Get the monitor handle information
  	MONITORINFOEX mi;
  	mi.cbSize = sizeof(MONITORINFOEX);
  	DXUTGetMonitorInfo(hMonitor, &mi);
  
  	// Search for this monitor in our enumeration hierarchy.
  	auto pd3dEnum = DXUTGetD3D11Enumeration();
  	auto pAdapterList = pd3dEnum->GetAdapterInfoList();
  	for (auto it = pAdapterList->cbegin(); it != pAdapterList->cend(); ++it)
  	{
  		auto pAdapterInfo = *it;
  		for (auto jit = pAdapterInfo->outputInfoList.cbegin(); jit != pAdapterInfo->outputInfoList.cend(); ++jit)
  		{
  			auto pOutputInfo = *jit;
  			DXGI_OUTPUT_DESC Desc;
  			if (FAILED(pOutputInfo->m_pOutput->GetDesc(&Desc)))
  				memset(&Desc, 0, sizeof(Desc));
  
  			if (hMonitor == Desc.Monitor)
  			{
  				*pOutputOrdinal = pOutputInfo->Output;
  				return S_OK;
  			}
  		}
  	}
  
  	return E_FAIL;
  }
  
  
  //--------------------------------------------------------------------------------------
  // This method is called when D3DERR_DEVICEREMOVED is returned from an API.  DXUT
  // calls the application's DeviceRemoved callback to inform it of the event.  The
  // application returns true if it wants DXUT to look for a closest device to run on.
  // If no device is found, or the app returns false, DXUT shuts down.
  //--------------------------------------------------------------------------------------
  HRESULT DXUTHandleDeviceRemoved()
  {
  	HRESULT hr = S_OK;
  
  	// Device has been removed. Call the application's callback if set.  If no callback
  	// has been set, then just look for a new device
  	bool bLookForNewDevice = true;
  	LPDXUTCALLBACKDEVICEREMOVED pDeviceRemovedFunc = GetDXUTState().GetDeviceRemovedFunc();
  	if (pDeviceRemovedFunc)
  		bLookForNewDevice = pDeviceRemovedFunc(GetDXUTState().GetDeviceRemovedFuncUserContext());
  
  	if (bLookForNewDevice)
  	{
  		auto pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  
  
  		hr = DXUTSnapDeviceSettingsToEnumDevice(pDeviceSettings, false);
  		if (SUCCEEDED(hr))
  		{
  			// Change to a Direct3D device created from the new device settings
  			// that is compatible with the removed device.
  			hr = DXUTChangeDevice(pDeviceSettings, false);
  			if (SUCCEEDED(hr))
  				return S_OK;
  		}
  	}
  
  	// The app does not wish to continue or continuing is not possible.
  	return DXUTERR_DEVICEREMOVED;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Stores back buffer surface desc in GetDXUTState().GetBackBufferSurfaceDesc10()
  //--------------------------------------------------------------------------------------
  void DXUTUpdateBackBufferDesc()
  {
  	auto pBBufferSurfaceDesc = GetDXUTState().GetBackBufferSurfaceDescDXGI();
  	ZeroMemory(pBBufferSurfaceDesc, sizeof(DXGI_SURFACE_DESC));
  	if (!GetDXUTState().GetHeadlessMode())
  	{
  		HRESULT hr;
  		ID3D11Texture2D* pBackBuffer;
  		auto pSwapChain = GetDXUTState().GetDXGISwapChain();
  		assert(pSwapChain);
  		_Analysis_assume_(pSwapChain);
  		hr = pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
  		if (SUCCEEDED(hr))
  		{
  			D3D11_TEXTURE2D_DESC TexDesc;
  			pBackBuffer->GetDesc(&TexDesc);
  			pBBufferSurfaceDesc->Width = (UINT)TexDesc.Width;
  			pBBufferSurfaceDesc->Height = (UINT)TexDesc.Height;
  			pBBufferSurfaceDesc->Format = TexDesc.Format;
  			pBBufferSurfaceDesc->SampleDesc = TexDesc.SampleDesc;
  			SAFE_RELEASE(pBackBuffer);
  		}
  	}
  	else
  	{
  		auto pdeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  		auto desc = pdeviceSettings->d3d11.sd;
  		pBBufferSurfaceDesc->Width = (UINT)desc.BufferDesc.Width;
  		pBBufferSurfaceDesc->Height = (UINT)desc.BufferDesc.Height;
  		pBBufferSurfaceDesc->Format = desc.BufferDesc.Format;
  		pBBufferSurfaceDesc->SampleDesc = desc.SampleDesc;
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state)
  //--------------------------------------------------------------------------------------
  void DXUTSetupCursor()
  {
  	// Clip cursor if requested
  	if (!DXUTIsWindowed() && GetDXUTState().GetClipCursorWhenFullScreen())
  	{
  		// Confine cursor to full screen window
  		RECT rcWindow;
  		GetWindowRect(DXUTGetHWNDDeviceFullScreen(), &rcWindow);
  		ClipCursor(&rcWindow);
  	}
  	else
  	{
  		ClipCursor(nullptr);
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Updates the static part of the frame stats so it doesn't have be generated every frame
  //--------------------------------------------------------------------------------------
  void DXUTUpdateStaticFrameStats()
  {
  	if (GetDXUTState().GetNoStats())
  		return;
  
  	auto pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  	if (!pDeviceSettings)
  		return;
  
  	// D3D11
  	auto pd3dEnum = DXUTGetD3D11Enumeration();
  	if (!pd3dEnum)
  		return;
  
  	auto pDeviceSettingsCombo = pd3dEnum->GetDeviceSettingsCombo(
  		pDeviceSettings->d3d11.AdapterOrdinal,
  		pDeviceSettings->d3d11.sd.BufferDesc.Format, pDeviceSettings->d3d11.sd.Windowed);
  	if (!pDeviceSettingsCombo)
  		return;
  
  	WCHAR strFmt[100];
  	wcscpy_s(strFmt, 100, DXUTDXGIFormatToString(pDeviceSettingsCombo->BackBufferFormat, false));
  
  	WCHAR strMultiSample[100];
  	swprintf_s(strMultiSample, 100, L" (MS%u, Q%u)", pDeviceSettings->d3d11.sd.SampleDesc.Count,
  		pDeviceSettings->d3d11.sd.SampleDesc.Quality);
  	auto pstrStaticFrameStats = GetDXUTState().GetStaticFrameStats();
  	swprintf_s(pstrStaticFrameStats, 256, L"D3D11 %%ls Vsync %ls (%ux%u), %ls%ls",
  		(pDeviceSettings->d3d11.SyncInterval == 0) ? L"off" : L"on",
  		pDeviceSettings->d3d11.sd.BufferDesc.Width, pDeviceSettings->d3d11.sd.BufferDesc.Height,
  		strFmt, strMultiSample);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Updates the frames/sec stat once per second
  //--------------------------------------------------------------------------------------
  void DXUTUpdateFrameStats()
  {
  	if (GetDXUTState().GetNoStats())
  		return;
  
  	// Keep track of the frame count
  	double fLastTime = GetDXUTState().GetLastStatsUpdateTime();
  	DWORD dwFrames = GetDXUTState().GetLastStatsUpdateFrames();
  	double fAbsTime = GetDXUTState().GetAbsoluteTime();
  	dwFrames++;
  	GetDXUTState().SetLastStatsUpdateFrames(dwFrames);
  
  	// Update the scene stats once per second
  	if (fAbsTime - fLastTime > 1.0f)
  	{
  		float fFPS = (float)(dwFrames / (fAbsTime - fLastTime));
  		GetDXUTState().SetFPS(fFPS);
  		GetDXUTState().SetLastStatsUpdateTime(fAbsTime);
  		GetDXUTState().SetLastStatsUpdateFrames(0);
  
  		auto pstrFPS = GetDXUTState().GetFPSStats();
  		swprintf_s(pstrFPS, 64, L"%0.2f fps ", fFPS);
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Returns a string describing the current device.  If bShowFPS is true, then
  // the string contains the frames/sec.  If "-nostats" was used in 
  // the command line, the string will be blank
  //--------------------------------------------------------------------------------------
  LPCWSTR WINAPI DXUTGetFrameStats(_In_ bool bShowFPS)
  {
  	auto pstrFrameStats = GetDXUTState().GetFrameStats();
  	const WCHAR* pstrFPS = (bShowFPS) ? GetDXUTState().GetFPSStats() : L"";
  	WCHAR* pstrStats = GetDXUTState().GetStaticFrameStats();
  	swprintf_s(pstrFrameStats, 256, pstrStats, pstrFPS);
  	return pstrFrameStats;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Updates the string which describes the device 
  //--------------------------------------------------------------------------------------
  #pragma warning( suppress : 6101 )
  _Use_decl_annotations_
  void DXUTUpdateD3D11DeviceStats(D3D_DRIVER_TYPE DeviceType, D3D_FEATURE_LEVEL featureLevel, DXGI_ADAPTER_DESC* pAdapterDesc)
  {
  	if (GetDXUTState().GetNoStats())
  		return;
  
  	// Store device description
  	auto pstrDeviceStats = GetDXUTState().GetDeviceStats();
  	if (DeviceType == D3D_DRIVER_TYPE_REFERENCE)
  		wcscpy_s(pstrDeviceStats, 256, L"REFERENCE");
  	else if (DeviceType == D3D_DRIVER_TYPE_HARDWARE)
  		wcscpy_s(pstrDeviceStats, 256, L"HARDWARE");
  	else if (DeviceType == D3D_DRIVER_TYPE_SOFTWARE)
  		wcscpy_s(pstrDeviceStats, 256, L"SOFTWARE");
  	else if (DeviceType == D3D_DRIVER_TYPE_WARP)
  		wcscpy_s(pstrDeviceStats, 256, L"WARP");
  
  	if (DeviceType == D3D_DRIVER_TYPE_HARDWARE)
  	{
  		// Be sure not to overflow m_strDeviceStats when appending the adapter 
  		// description, since it can be long.  
  		wcscat_s(pstrDeviceStats, 256, L": ");
  
  		// Try to get a unique description from the CD3D11EnumDeviceSettingsCombo
  		auto pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
  		if (!pDeviceSettings)
  			return;
  
  		auto pd3dEnum = DXUTGetD3D11Enumeration();
  		assert(pd3dEnum);
  		_Analysis_assume_(pd3dEnum);
  		auto pDeviceSettingsCombo = pd3dEnum->GetDeviceSettingsCombo(
  			pDeviceSettings->d3d11.AdapterOrdinal,
  			pDeviceSettings->d3d11.sd.BufferDesc.Format, pDeviceSettings->d3d11.sd.Windowed);
  		if (pDeviceSettingsCombo)
  			wcscat_s(pstrDeviceStats, 256, pDeviceSettingsCombo->pAdapterInfo->szUniqueDescription);
  		else
  			wcscat_s(pstrDeviceStats, 256, pAdapterDesc->Description);
  	}
  
  	switch (featureLevel)
  	{
  	case D3D_FEATURE_LEVEL_9_1:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 9.1)");
  		break;
  	case D3D_FEATURE_LEVEL_9_2:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 9.2)");
  		break;
  	case D3D_FEATURE_LEVEL_9_3:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 9.3)");
  		break;
  	case D3D_FEATURE_LEVEL_10_0:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 10.0)");
  		break;
  	case D3D_FEATURE_LEVEL_10_1:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 10.1)");
  		break;
  	case D3D_FEATURE_LEVEL_11_0:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 11.0)");
  		break;
  	case D3D_FEATURE_LEVEL_11_1:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 11.1)");
  		break;
  #ifdef USE_DIRECT3D11_3
  	case D3D_FEATURE_LEVEL_12_0:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 12.0)");
  		break;
  	case D3D_FEATURE_LEVEL_12_1:
  		wcscat_s(pstrDeviceStats, 256, L" (FL 12.1)");
  		break;
  #endif
  	}
  }
  
  
  //--------------------------------------------------------------------------------------
  // Misc functions
  //--------------------------------------------------------------------------------------
  DXUTDeviceSettings WINAPI DXUTGetDeviceSettings()
  {
  	// Return a copy of device settings of the current device.  If no device exists yet, then
  	// return a blank device settings struct
  	auto pDS = GetDXUTState().GetCurrentDeviceSettings();
  	if (pDS)
  	{
  		return *pDS;
  	}
  	else
  	{
  		DXUTDeviceSettings ds;
  		ZeroMemory(&ds, sizeof(DXUTDeviceSettings));
  		return ds;
  	}
  }
  
  bool WINAPI DXUTIsVsyncEnabled()
  {
  	auto pDS = GetDXUTState().GetCurrentDeviceSettings();
  	if (pDS)
  	{
  		return (pDS->d3d11.SyncInterval == 0);
  	}
  	else
  	{
  		return true;
  	}
  };
  
  bool WINAPI DXUTIsKeyDown(_In_ BYTE vKey)
  {
  	bool* bKeys = GetDXUTState().GetKeys();
  	if (vKey >= 0xA0 && vKey <= 0xA5)  // VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL, VK_LMENU, VK_RMENU
  		return GetAsyncKeyState(vKey) != 0; // these keys only are tracked via GetAsyncKeyState()
  	else if (vKey >= 0x01 && vKey <= 0x06 && vKey != 0x03) // mouse buttons (VK_*BUTTON)
  		return DXUTIsMouseButtonDown(vKey);
  	else
  		return bKeys[vKey];
  }
  
  bool WINAPI DXUTWasKeyPressed(_In_ BYTE vKey)
  {
  	bool* bLastKeys = GetDXUTState().GetLastKeys();
  	bool* bKeys = GetDXUTState().GetKeys();
  	GetDXUTState().SetAppCalledWasKeyPressed(true);
  	return (!bLastKeys[vKey] && bKeys[vKey]);
  }
  
  bool WINAPI DXUTIsMouseButtonDown(_In_ BYTE vButton)
  {
  	bool* bMouseButtons = GetDXUTState().GetMouseButtons();
  	int nIndex = DXUTMapButtonToArrayIndex(vButton);
  	return bMouseButtons[nIndex];
  }
  
  void WINAPI DXUTSetMultimonSettings(_In_ bool bAutoChangeAdapter)
  {
  	GetDXUTState().SetAutoChangeAdapter(bAutoChangeAdapter);
  }
  
  _Use_decl_annotations_
  void WINAPI DXUTSetHotkeyHandling(bool bAltEnterToToggleFullscreen, bool bEscapeToQuit, bool bPauseToToggleTimePause)
  {
  	GetDXUTState().SetHandleEscape(bEscapeToQuit);
  	GetDXUTState().SetHandleAltEnter(bAltEnterToToggleFullscreen);
  	GetDXUTState().SetHandlePause(bPauseToToggleTimePause);
  }
  
  _Use_decl_annotations_
  void WINAPI DXUTSetCursorSettings(bool bShowCursorWhenFullScreen, bool bClipCursorWhenFullScreen)
  {
  	GetDXUTState().SetClipCursorWhenFullScreen(bClipCursorWhenFullScreen);
  	GetDXUTState().SetShowCursorWhenFullScreen(bShowCursorWhenFullScreen);
  	DXUTSetupCursor();
  }
  
  void WINAPI DXUTSetWindowSettings(_In_ bool bCallDefWindowProc)
  {
  	GetDXUTState().SetCallDefWindowProc(bCallDefWindowProc);
  }
  
  _Use_decl_annotations_
  void WINAPI DXUTSetConstantFrameTime(bool bEnabled, float fTimePerFrame)
  {
  	if (GetDXUTState().GetOverrideConstantFrameTime())
  	{
  		bEnabled = GetDXUTState().GetOverrideConstantFrameTime();
  		fTimePerFrame = GetDXUTState().GetOverrideConstantTimePerFrame();
  	}
  	GetDXUTState().SetConstantFrameTime(bEnabled);
  	GetDXUTState().SetTimePerFrame(fTimePerFrame);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Resets the state associated with DXUT 
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTResetFrameworkState()
  {
  	GetDXUTState().Destroy();
  	GetDXUTState().Create();
  }
  
  
  //--------------------------------------------------------------------------------------
  // Closes down the window.  When the window closes, it will cleanup everything
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTShutdown(_In_ int nExitCode)
  {
  	HWND hWnd = DXUTGetHWND();
  	if (hWnd)
  		SendMessage(hWnd, WM_CLOSE, 0, 0);
  
  	GetDXUTState().SetExitCode(nExitCode);
  
  	DXUTCleanup3DEnvironment(true);
  
  	// Restore shortcut keys (Windows key, accessibility shortcuts) to original state
  	// This is important to call here if the shortcuts are disabled, 
  	// because accessibility setting changes are permanent.
  	// This means that if this is not done then the accessibility settings 
  	// might not be the same as when the app was started. 
  	// If the app crashes without restoring the settings, this is also true so it
  	// would be wise to backup/restore the settings from a file so they can be 
  	// restored when the crashed app is run again.
  	DXUTAllowShortcutKeys(true);
  
  	// Shutdown D3D11
  	auto pDXGIFactory = GetDXUTState().GetDXGIFactory();
  	SAFE_RELEASE(pDXGIFactory);
  	GetDXUTState().SetDXGIFactory(nullptr);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Tells DXUT whether to operate in gamma correct mode
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTSetIsInGammaCorrectMode(_In_ bool bGammaCorrect)
  {
  	GetDXUTState().SetIsInGammaCorrectMode(bGammaCorrect);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Tells DXUT whether to operate in headless mode
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTSetHeadlessMode(_In_ bool bHeadlessMode)
  {
  	GetDXUTState().SetHeadlessMode(bHeadlessMode);
  }
  
  
  //--------------------------------------------------------------------------------------
  // Tells DXUT not to call swapchain present
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTSetNoSwapChainPresent(_In_ bool bNoSwapChainPresent)
  {
  	GetDXUTState().SetNoSwapChainPresent(bNoSwapChainPresent);
  }
  
  
  //--------------------------------------------------------------------------------------
  void DXUTApplyDefaultDeviceSettings(DXUTDeviceSettings *modifySettings)
  {
  	ZeroMemory(modifySettings, sizeof(DXUTDeviceSettings));
  
  	modifySettings->d3d11.AdapterOrdinal = 0;
  	modifySettings->d3d11.AutoCreateDepthStencil = true;
  	modifySettings->d3d11.AutoDepthStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
  #if defined(DEBUG) || defined(_DEBUG)
  	modifySettings->d3d11.CreateFlags |= D3D11_CREATE_DEVICE_DEBUG;
  #else
  	modifySettings->d3d11.CreateFlags = 0;
  #endif
  	modifySettings->d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE;
  	modifySettings->d3d11.Output = 0;
  	modifySettings->d3d11.PresentFlags = 0;
  	modifySettings->d3d11.sd.BufferCount = 2;
  	// Phong Cao: Azure GPU doesn't support DXGI_FORMAT_R8G8B8A8_UNORM_SRGB.
  	//modifySettings->d3d11.sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
  	modifySettings->d3d11.sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  	modifySettings->d3d11.sd.BufferDesc.Height = 600;
  	modifySettings->d3d11.sd.BufferDesc.RefreshRate.Numerator = 0;
  	modifySettings->d3d11.sd.BufferDesc.RefreshRate.Denominator = 0;
  	modifySettings->d3d11.sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
  	modifySettings->d3d11.sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
  	modifySettings->d3d11.sd.BufferDesc.Width = 800;
  	modifySettings->d3d11.sd.BufferUsage = 32;
  	modifySettings->d3d11.sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
  	modifySettings->d3d11.sd.OutputWindow = DXUTGetHWND();
  	modifySettings->d3d11.sd.SampleDesc.Count = 1;
  	modifySettings->d3d11.sd.SampleDesc.Quality = 0;
  	modifySettings->d3d11.sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
  	modifySettings->d3d11.sd.Windowed = TRUE;
  	modifySettings->d3d11.SyncInterval = 0;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Update settings based on what is enumeratabled
  //--------------------------------------------------------------------------------------
  _Use_decl_annotations_
  HRESULT DXUTSnapDeviceSettingsToEnumDevice(DXUTDeviceSettings* pDeviceSettings, bool forceEnum, D3D_FEATURE_LEVEL forceFL)
  {
  	if (GetSystemMetrics(SM_REMOTESESSION) != 0)
  	{
  		pDeviceSettings->d3d11.sd.Windowed = TRUE;
  	}
  	int bestModeIndex = 0;
  	int bestMSAAIndex = 0;
  
  	//DXUTSetDefaultDeviceSettings
  	CD3D11Enumeration *pEnum = DXUTGetD3D11Enumeration(forceEnum, true, forceFL);
  
  	CD3D11EnumAdapterInfo* pAdapterInfo = nullptr;
  	auto pAdapterList = pEnum->GetAdapterInfoList();
  	for (auto it = pAdapterList->cbegin(); it != pAdapterList->cend(); ++it)
  	{
  		auto tempAdapterInfo = *it;
  		if (tempAdapterInfo->AdapterOrdinal == pDeviceSettings->d3d11.AdapterOrdinal) pAdapterInfo = tempAdapterInfo;
  	}
  	if (!pAdapterInfo)
  	{
  		if (pAdapterList->empty() || pDeviceSettings->d3d11.AdapterOrdinal > 0)
  		{
  			return E_FAIL; // no adapters found.
  		}
  		pAdapterInfo = *pAdapterList->cbegin();
  	}
  	CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo = nullptr;
  	float biggestScore = 0;
  
  	for (size_t iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.size(); iDeviceCombo++)
  	{
  		CD3D11EnumDeviceSettingsCombo* tempDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList[iDeviceCombo];
  
  		int bestMode;
  		int bestMSAA;
  		float score = DXUTRankD3D11DeviceCombo(tempDeviceSettingsCombo, &(pDeviceSettings->d3d11), bestMode, bestMSAA);
  		if (score > biggestScore)
  		{
  			biggestScore = score;
  			pDeviceSettingsCombo = tempDeviceSettingsCombo;
  			bestModeIndex = bestMode;
  			bestMSAAIndex = bestMSAA;
  		}
  	}
  	if (!pDeviceSettingsCombo)
  	{
  		return E_FAIL; // no settings found.
  	}
  
  	pDeviceSettings->d3d11.AdapterOrdinal = pDeviceSettingsCombo->AdapterOrdinal;
  	pDeviceSettings->d3d11.DriverType = pDeviceSettingsCombo->DeviceType;
  	pDeviceSettings->d3d11.Output = pDeviceSettingsCombo->Output;
  
  	pDeviceSettings->d3d11.sd.Windowed = pDeviceSettingsCombo->Windowed;
  	if (GetSystemMetrics(SM_REMOTESESSION) != 0)
  	{
  		pDeviceSettings->d3d11.sd.Windowed = TRUE;
  	}
  	if (pDeviceSettingsCombo->pOutputInfo)
  	{
  		auto bestDisplayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList[bestModeIndex];
  		if (!pDeviceSettingsCombo->Windowed)
  		{
  			pDeviceSettings->d3d11.sd.BufferDesc.Height = bestDisplayMode.Height;
  			pDeviceSettings->d3d11.sd.BufferDesc.Width = bestDisplayMode.Width;
  			pDeviceSettings->d3d11.sd.BufferDesc.RefreshRate.Numerator = bestDisplayMode.RefreshRate.Numerator;
  			pDeviceSettings->d3d11.sd.BufferDesc.RefreshRate.Denominator = bestDisplayMode.RefreshRate.Denominator;
  			pDeviceSettings->d3d11.sd.BufferDesc.Scaling = bestDisplayMode.Scaling;
  			pDeviceSettings->d3d11.sd.BufferDesc.ScanlineOrdering = bestDisplayMode.ScanlineOrdering;
  		}
  	}
  	if (pDeviceSettings->d3d11.DeviceFeatureLevel == 0)
  		pDeviceSettings->d3d11.DeviceFeatureLevel = pDeviceSettingsCombo->pDeviceInfo->SelectedLevel;
  
  	if (pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_WARP)
  	{
  		D3D_FEATURE_LEVEL maxWarpFL = pEnum->GetWARPFeaturevel();
  
  		if (pDeviceSettings->d3d11.DeviceFeatureLevel > maxWarpFL)
  			pDeviceSettings->d3d11.DeviceFeatureLevel = maxWarpFL;
  	}
  
  	if (pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE)
  	{
  		D3D_FEATURE_LEVEL maxRefFL = pEnum->GetREFFeaturevel();
  
  		if (pDeviceSettings->d3d11.DeviceFeatureLevel > maxRefFL)
  			pDeviceSettings->d3d11.DeviceFeatureLevel = maxRefFL;
  	}
  
  	pDeviceSettings->d3d11.sd.SampleDesc.Count = pDeviceSettingsCombo->multiSampleCountList[bestMSAAIndex];
  	if (pDeviceSettings->d3d11.sd.SampleDesc.Quality > pDeviceSettingsCombo->multiSampleQualityList[bestMSAAIndex] - 1)
  		pDeviceSettings->d3d11.sd.SampleDesc.Quality = pDeviceSettingsCombo->multiSampleQualityList[bestMSAAIndex] - 1;
  
  	pDeviceSettings->d3d11.sd.BufferDesc.Format = pDeviceSettingsCombo->BackBufferFormat;
  
  	return S_OK;
  }
  