text: //--------------------------------------------------------------------------------------
  // File: DXUTMisc.cpp
  //
  // Shortcut macros and functions for using DX objects
  //
  // Copyright (c) Microsoft Corporation. All rights reserved
  //--------------------------------------------------------------------------------------
  #include "dxut.h"
  #include <xinput.h>
  #define DXUT_GAMEPAD_TRIGGER_THRESHOLD      30
  #undef min // use __min instead
  #undef max // use __max instead
  
  CDXUTTimer* WINAPI DXUTGetGlobalTimer()
  {
      // Using an accessor function gives control of the construction order
      static CDXUTTimer timer;
      return &timer;
  }
  
  
  //--------------------------------------------------------------------------------------
  CDXUTTimer::CDXUTTimer()
  {
      m_bTimerStopped = true;
      m_llQPFTicksPerSec = 0;
  
      m_llStopTime = 0;
      m_llLastElapsedTime = 0;
      m_llBaseTime = 0;
  
      // Use QueryPerformanceFrequency to get the frequency of the counter
      LARGE_INTEGER qwTicksPerSec = { 0 };
      QueryPerformanceFrequency( &qwTicksPerSec );
      m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;
  }
  
  
  //--------------------------------------------------------------------------------------
  void CDXUTTimer::Reset()
  {
      LARGE_INTEGER qwTime = GetAdjustedCurrentTime();
  
      m_llBaseTime = qwTime.QuadPart;
      m_llLastElapsedTime = qwTime.QuadPart;
      m_llStopTime = 0;
      m_bTimerStopped = FALSE;
  }
  
  
  //--------------------------------------------------------------------------------------
  void CDXUTTimer::Start()
  {
      // Get the current time
      LARGE_INTEGER qwTime = { 0 };
      QueryPerformanceCounter( &qwTime );
  
      if( m_bTimerStopped )
          m_llBaseTime += qwTime.QuadPart - m_llStopTime;
      m_llStopTime = 0;
      m_llLastElapsedTime = qwTime.QuadPart;
      m_bTimerStopped = FALSE;
  }
  
  
  //--------------------------------------------------------------------------------------
  void CDXUTTimer::Stop()
  {
      if( !m_bTimerStopped )
      {
          LARGE_INTEGER qwTime = { 0 };
          QueryPerformanceCounter( &qwTime );
          m_llStopTime = qwTime.QuadPart;
          m_llLastElapsedTime = qwTime.QuadPart;
          m_bTimerStopped = TRUE;
      }
  }
  
  
  //--------------------------------------------------------------------------------------
  void CDXUTTimer::Advance()
  {
      m_llStopTime += m_llQPFTicksPerSec / 10;
  }
  
  
  //--------------------------------------------------------------------------------------
  double CDXUTTimer::GetAbsoluteTime()
  {
      LARGE_INTEGER qwTime = { 0 };
      QueryPerformanceCounter( &qwTime );
  
      double fTime = qwTime.QuadPart / ( double )m_llQPFTicksPerSec;
  
      return fTime;
  }
  
  
  //--------------------------------------------------------------------------------------
  double CDXUTTimer::GetTime()
  {
      LARGE_INTEGER qwTime = GetAdjustedCurrentTime();
  
      double fAppTime = ( double )( qwTime.QuadPart - m_llBaseTime ) / ( double )m_llQPFTicksPerSec;
  
      return fAppTime;
  }
  
  
  //--------------------------------------------------------------------------------------
  void CDXUTTimer::GetTimeValues( double* pfTime, double* pfAbsoluteTime, float* pfElapsedTime )
  {
      assert( pfTime && pfAbsoluteTime && pfElapsedTime );
  
      LARGE_INTEGER qwTime = GetAdjustedCurrentTime();
  
      float fElapsedTime = ( float )( ( double )( qwTime.QuadPart - m_llLastElapsedTime ) / ( double )
                                      m_llQPFTicksPerSec );
      m_llLastElapsedTime = qwTime.QuadPart;
  
      // Clamp the timer to non-negative values to ensure the timer is accurate.
      // fElapsedTime can be outside this range if processor goes into a 
      // power save mode or we somehow get shuffled to another processor.  
      // However, the main thread should call SetThreadAffinityMask to ensure that 
      // we don't get shuffled to another processor.  Other worker threads should NOT call 
      // SetThreadAffinityMask, but use a shared copy of the timer data gathered from 
      // the main thread.
      if( fElapsedTime < 0.0f )
          fElapsedTime = 0.0f;
  
      *pfAbsoluteTime = qwTime.QuadPart / ( double )m_llQPFTicksPerSec;
      *pfTime = ( qwTime.QuadPart - m_llBaseTime ) / ( double )m_llQPFTicksPerSec;
      *pfElapsedTime = fElapsedTime;
  }
  
  
  //--------------------------------------------------------------------------------------
  float CDXUTTimer::GetElapsedTime()
  {
      LARGE_INTEGER qwTime = GetAdjustedCurrentTime();
  
      double fElapsedTime = ( float )( ( double )( qwTime.QuadPart - m_llLastElapsedTime ) / ( double )
                                       m_llQPFTicksPerSec );
      m_llLastElapsedTime = qwTime.QuadPart;
  
      // See the explanation about clamping in CDXUTTimer::GetTimeValues()
      if( fElapsedTime < 0.0f )
          fElapsedTime = 0.0f;
  
      return ( float )fElapsedTime;
  }
  
  
  //--------------------------------------------------------------------------------------
  // If stopped, returns time when stopped otherwise returns current time
  //--------------------------------------------------------------------------------------
  LARGE_INTEGER CDXUTTimer::GetAdjustedCurrentTime()
  {
      LARGE_INTEGER qwTime;
      if( m_llStopTime != 0 )
          qwTime.QuadPart = m_llStopTime;
      else
          QueryPerformanceCounter( &qwTime );
      return qwTime;
  }
  
  //--------------------------------------------------------------------------------------
  bool CDXUTTimer::IsStopped()
  {
      return m_bTimerStopped;
  }
  
  //--------------------------------------------------------------------------------------
  // Limit the current thread to one processor (the current one). This ensures that timing code 
  // runs on only one processor, and will not suffer any ill effects from power management.
  // See "Game Timing and Multicore Processors" for more details
  //--------------------------------------------------------------------------------------
  void CDXUTTimer::LimitThreadAffinityToCurrentProc()
  {
      HANDLE hCurrentProcess = GetCurrentProcess();
  
      // Get the processor affinity mask for this process
      DWORD_PTR dwProcessAffinityMask = 0;
      DWORD_PTR dwSystemAffinityMask = 0;
  
      if( GetProcessAffinityMask( hCurrentProcess, &dwProcessAffinityMask, &dwSystemAffinityMask ) != 0 &&
          dwProcessAffinityMask )
      {
          // Find the lowest processor that our process is allows to run against
          DWORD_PTR dwAffinityMask = ( dwProcessAffinityMask & ( ( ~dwProcessAffinityMask ) + 1 ) );
  
          // Set this as the processor that our thread must always run against
          // This must be a subset of the process affinity mask
          HANDLE hCurrentThread = GetCurrentThread();
          if( INVALID_HANDLE_VALUE != hCurrentThread )
          {
              SetThreadAffinityMask( hCurrentThread, dwAffinityMask );
              CloseHandle( hCurrentThread );
          }
      }
  
      CloseHandle( hCurrentProcess );
  }
  
  
  //--------------------------------------------------------------------------------------
  // Returns the string for the given D3DFORMAT.
  //--------------------------------------------------------------------------------------
  LPCWSTR WINAPI DXUTD3DFormatToString( D3DFORMAT format, bool bWithPrefix )
  {
      WCHAR* pstr = NULL;
      switch( format )
      {
          case D3DFMT_UNKNOWN:
              pstr = L"D3DFMT_UNKNOWN"; break;
          case D3DFMT_R8G8B8:
              pstr = L"D3DFMT_R8G8B8"; break;
          case D3DFMT_A8R8G8B8:
              pstr = L"D3DFMT_A8R8G8B8"; break;
          case D3DFMT_X8R8G8B8:
              pstr = L"D3DFMT_X8R8G8B8"; break;
          case D3DFMT_R5G6B5:
              pstr = L"D3DFMT_R5G6B5"; break;
          case D3DFMT_X1R5G5B5:
              pstr = L"D3DFMT_X1R5G5B5"; break;
          case D3DFMT_A1R5G5B5:
              pstr = L"D3DFMT_A1R5G5B5"; break;
          case D3DFMT_A4R4G4B4:
              pstr = L"D3DFMT_A4R4G4B4"; break;
          case D3DFMT_R3G3B2:
              pstr = L"D3DFMT_R3G3B2"; break;
          case D3DFMT_A8:
              pstr = L"D3DFMT_A8"; break;
          case D3DFMT_A8R3G3B2:
              pstr = L"D3DFMT_A8R3G3B2"; break;
          case D3DFMT_X4R4G4B4:
              pstr = L"D3DFMT_X4R4G4B4"; break;
          case D3DFMT_A2B10G10R10:
              pstr = L"D3DFMT_A2B10G10R10"; break;
          case D3DFMT_A8B8G8R8:
              pstr = L"D3DFMT_A8B8G8R8"; break;
          case D3DFMT_X8B8G8R8:
              pstr = L"D3DFMT_X8B8G8R8"; break;
          case D3DFMT_G16R16:
              pstr = L"D3DFMT_G16R16"; break;
          case D3DFMT_A2R10G10B10:
              pstr = L"D3DFMT_A2R10G10B10"; break;
          case D3DFMT_A16B16G16R16:
              pstr = L"D3DFMT_A16B16G16R16"; break;
          case D3DFMT_A8P8:
              pstr = L"D3DFMT_A8P8"; break;
          case D3DFMT_P8:
              pstr = L"D3DFMT_P8"; break;
          case D3DFMT_L8:
              pstr = L"D3DFMT_L8"; break;
          case D3DFMT_A8L8:
              pstr = L"D3DFMT_A8L8"; break;
          case D3DFMT_A4L4:
              pstr = L"D3DFMT_A4L4"; break;
          case D3DFMT_V8U8:
              pstr = L"D3DFMT_V8U8"; break;
          case D3DFMT_L6V5U5:
              pstr = L"D3DFMT_L6V5U5"; break;
          case D3DFMT_X8L8V8U8:
              pstr = L"D3DFMT_X8L8V8U8"; break;
          case D3DFMT_Q8W8V8U8:
              pstr = L"D3DFMT_Q8W8V8U8"; break;
          case D3DFMT_V16U16:
              pstr = L"D3DFMT_V16U16"; break;
          case D3DFMT_A2W10V10U10:
              pstr = L"D3DFMT_A2W10V10U10"; break;
          case D3DFMT_UYVY:
              pstr = L"D3DFMT_UYVY"; break;
          case D3DFMT_YUY2:
              pstr = L"D3DFMT_YUY2"; break;
          case D3DFMT_DXT1:
              pstr = L"D3DFMT_DXT1"; break;
          case D3DFMT_DXT2:
              pstr = L"D3DFMT_DXT2"; break;
          case D3DFMT_DXT3:
              pstr = L"D3DFMT_DXT3"; break;
          case D3DFMT_DXT4:
              pstr = L"D3DFMT_DXT4"; break;
          case D3DFMT_DXT5:
              pstr = L"D3DFMT_DXT5"; break;
          case D3DFMT_D16_LOCKABLE:
              pstr = L"D3DFMT_D16_LOCKABLE"; break;
          case D3DFMT_D32:
              pstr = L"D3DFMT_D32"; break;
          case D3DFMT_D15S1:
              pstr = L"D3DFMT_D15S1"; break;
          case D3DFMT_D24S8:
              pstr = L"D3DFMT_D24S8"; break;
          case D3DFMT_D24X8:
              pstr = L"D3DFMT_D24X8"; break;
          case D3DFMT_D24X4S4:
              pstr = L"D3DFMT_D24X4S4"; break;
          case D3DFMT_D16:
              pstr = L"D3DFMT_D16"; break;
          case D3DFMT_L16:
              pstr = L"D3DFMT_L16"; break;
          case D3DFMT_VERTEXDATA:
              pstr = L"D3DFMT_VERTEXDATA"; break;
          case D3DFMT_INDEX16:
              pstr = L"D3DFMT_INDEX16"; break;
          case D3DFMT_INDEX32:
              pstr = L"D3DFMT_INDEX32"; break;
          case D3DFMT_Q16W16V16U16:
              pstr = L"D3DFMT_Q16W16V16U16"; break;
          case D3DFMT_MULTI2_ARGB8:
              pstr = L"D3DFMT_MULTI2_ARGB8"; break;
          case D3DFMT_R16F:
              pstr = L"D3DFMT_R16F"; break;
          case D3DFMT_G16R16F:
              pstr = L"D3DFMT_G16R16F"; break;
          case D3DFMT_A16B16G16R16F:
              pstr = L"D3DFMT_A16B16G16R16F"; break;
          case D3DFMT_R32F:
              pstr = L"D3DFMT_R32F"; break;
          case D3DFMT_G32R32F:
              pstr = L"D3DFMT_G32R32F"; break;
          case D3DFMT_A32B32G32R32F:
              pstr = L"D3DFMT_A32B32G32R32F"; break;
          case D3DFMT_CxV8U8:
              pstr = L"D3DFMT_CxV8U8"; break;
          default:
              pstr = L"Unknown format"; break;
      }
      if( bWithPrefix || wcsstr( pstr, L"D3DFMT_" ) == NULL )
          return pstr;
      else
          return pstr + lstrlen( L"D3DFMT_" );
  }
  
  
  //--------------------------------------------------------------------------------------
  // Returns the string for the given DXGI_FORMAT.
  //--------------------------------------------------------------------------------------
  LPCWSTR WINAPI DXUTDXGIFormatToString( DXGI_FORMAT format, bool bWithPrefix )
  {
      WCHAR* pstr = NULL;
      switch( format )
      {
          case DXGI_FORMAT_R32G32B32A32_TYPELESS:
              pstr = L"DXGI_FORMAT_R32G32B32A32_TYPELESS"; break;
          case DXGI_FORMAT_R32G32B32A32_FLOAT:
              pstr = L"DXGI_FORMAT_R32G32B32A32_FLOAT"; break;
          case DXGI_FORMAT_R32G32B32A32_UINT:
              pstr = L"DXGI_FORMAT_R32G32B32A32_UINT"; break;
          case DXGI_FORMAT_R32G32B32A32_SINT:
              pstr = L"DXGI_FORMAT_R32G32B32A32_SINT"; break;
          case DXGI_FORMAT_R32G32B32_TYPELESS:
              pstr = L"DXGI_FORMAT_R32G32B32_TYPELESS"; break;
          case DXGI_FORMAT_R32G32B32_FLOAT:
              pstr = L"DXGI_FORMAT_R32G32B32_FLOAT"; break;
          case DXGI_FORMAT_R32G32B32_UINT:
              pstr = L"DXGI_FORMAT_R32G32B32_UINT"; break;
          case DXGI_FORMAT_R32G32B32_SINT:
              pstr = L"DXGI_FORMAT_R32G32B32_SINT"; break;
          case DXGI_FORMAT_R16G16B16A16_TYPELESS:
              pstr = L"DXGI_FORMAT_R16G16B16A16_TYPELESS"; break;
          case DXGI_FORMAT_R16G16B16A16_FLOAT:
              pstr = L"DXGI_FORMAT_R16G16B16A16_FLOAT"; break;
          case DXGI_FORMAT_R16G16B16A16_UNORM:
              pstr = L"DXGI_FORMAT_R16G16B16A16_UNORM"; break;
          case DXGI_FORMAT_R16G16B16A16_UINT:
              pstr = L"DXGI_FORMAT_R16G16B16A16_UINT"; break;
          case DXGI_FORMAT_R16G16B16A16_SNORM:
              pstr = L"DXGI_FORMAT_R16G16B16A16_SNORM"; break;
          case DXGI_FORMAT_R16G16B16A16_SINT:
              pstr = L"DXGI_FORMAT_R16G16B16A16_SINT"; break;
          case DXGI_FORMAT_R32G32_TYPELESS:
              pstr = L"DXGI_FORMAT_R32G32_TYPELESS"; break;
          case DXGI_FORMAT_R32G32_FLOAT:
              pstr = L"DXGI_FORMAT_R32G32_FLOAT"; break;
          case DXGI_FORMAT_R32G32_UINT:
              pstr = L"DXGI_FORMAT_R32G32_UINT"; break;
          case DXGI_FORMAT_R32G32_SINT:
              pstr = L"DXGI_FORMAT_R32G32_SINT"; break;
          case DXGI_FORMAT_R32G8X24_TYPELESS:
              pstr = L"DXGI_FORMAT_R32G8X24_TYPELESS"; break;
          case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
              pstr = L"DXGI_FORMAT_D32_FLOAT_S8X24_UINT"; break;
          case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
              pstr = L"DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS"; break;
          case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
              pstr = L"DXGI_FORMAT_X32_TYPELESS_G8X24_UINT"; break;
          case DXGI_FORMAT_R10G10B10A2_TYPELESS:
              pstr = L"DXGI_FORMAT_R10G10B10A2_TYPELESS"; break;
          case DXGI_FORMAT_R10G10B10A2_UNORM:
              pstr = L"DXGI_FORMAT_R10G10B10A2_UNORM"; break;
          case DXGI_FORMAT_R10G10B10A2_UINT:
              pstr = L"DXGI_FORMAT_R10G10B10A2_UINT"; break;
          case DXGI_FORMAT_R11G11B10_FLOAT:
              pstr = L"DXGI_FORMAT_R11G11B10_FLOAT"; break;
          case DXGI_FORMAT_R8G8B8A8_TYPELESS:
              pstr = L"DXGI_FORMAT_R8G8B8A8_TYPELESS"; break;
          case DXGI_FORMAT_R8G8B8A8_UNORM:
              pstr = L"DXGI_FORMAT_R8G8B8A8_UNORM"; break;
          case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
              pstr = L"DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"; break;
          case DXGI_FORMAT_R8G8B8A8_UINT:
              pstr = L"DXGI_FORMAT_R8G8B8A8_UINT"; break;
          case DXGI_FORMAT_R8G8B8A8_SNORM:
              pstr = L"DXGI_FORMAT_R8G8B8A8_SNORM"; break;
          case DXGI_FORMAT_R8G8B8A8_SINT:
              pstr = L"DXGI_FORMAT_R8G8B8A8_SINT"; break;
          case DXGI_FORMAT_R16G16_TYPELESS:
              pstr = L"DXGI_FORMAT_R16G16_TYPELESS"; break;
          case DXGI_FORMAT_R16G16_FLOAT:
              pstr = L"DXGI_FORMAT_R16G16_FLOAT"; break;
          case DXGI_FORMAT_R16G16_UNORM:
              pstr = L"DXGI_FORMAT_R16G16_UNORM"; break;
          case DXGI_FORMAT_R16G16_UINT:
              pstr = L"DXGI_FORMAT_R16G16_UINT"; break;
          case DXGI_FORMAT_R16G16_SNORM:
              pstr = L"DXGI_FORMAT_R16G16_SNORM"; break;
          case DXGI_FORMAT_R16G16_SINT:
              pstr = L"DXGI_FORMAT_R16G16_SINT"; break;
          case DXGI_FORMAT_R32_TYPELESS:
              pstr = L"DXGI_FORMAT_R32_TYPELESS"; break;
          case DXGI_FORMAT_D32_FLOAT:
              pstr = L"DXGI_FORMAT_D32_FLOAT"; break;
          case DXGI_FORMAT_R32_FLOAT:
              pstr = L"DXGI_FORMAT_R32_FLOAT"; break;
          case DXGI_FORMAT_R32_UINT:
              pstr = L"DXGI_FORMAT_R32_UINT"; break;
          case DXGI_FORMAT_R32_SINT:
              pstr = L"DXGI_FORMAT_R32_SINT"; break;
          case DXGI_FORMAT_R24G8_TYPELESS:
              pstr = L"DXGI_FORMAT_R24G8_TYPELESS"; break;
          case DXGI_FORMAT_D24_UNORM_S8_UINT:
              pstr = L"DXGI_FORMAT_D24_UNORM_S8_UINT"; break;
          case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
              pstr = L"DXGI_FORMAT_R24_UNORM_X8_TYPELESS"; break;
          case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
              pstr = L"DXGI_FORMAT_X24_TYPELESS_G8_UINT"; break;
          case DXGI_FORMAT_R8G8_TYPELESS:
              pstr = L"DXGI_FORMAT_R8G8_TYPELESS"; break;
          case DXGI_FORMAT_R8G8_UNORM:
              pstr = L"DXGI_FORMAT_R8G8_UNORM"; break;
          case DXGI_FORMAT_R8G8_UINT:
              pstr = L"DXGI_FORMAT_R8G8_UINT"; break;
          case DXGI_FORMAT_R8G8_SNORM:
              pstr = L"DXGI_FORMAT_R8G8_SNORM"; break;
          case DXGI_FORMAT_R8G8_SINT:
              pstr = L"DXGI_FORMAT_R8G8_SINT"; break;
          case DXGI_FORMAT_R16_TYPELESS:
              pstr = L"DXGI_FORMAT_R16_TYPELESS"; break;
          case DXGI_FORMAT_R16_FLOAT:
              pstr = L"DXGI_FORMAT_R16_FLOAT"; break;
          case DXGI_FORMAT_D16_UNORM:
              pstr = L"DXGI_FORMAT_D16_UNORM"; break;
          case DXGI_FORMAT_R16_UNORM:
              pstr = L"DXGI_FORMAT_R16_UNORM"; break;
          case DXGI_FORMAT_R16_UINT:
              pstr = L"DXGI_FORMAT_R16_UINT"; break;
          case DXGI_FORMAT_R16_SNORM:
              pstr = L"DXGI_FORMAT_R16_SNORM"; break;
          case DXGI_FORMAT_R16_SINT:
              pstr = L"DXGI_FORMAT_R16_SINT"; break;
          case DXGI_FORMAT_R8_TYPELESS:
              pstr = L"DXGI_FORMAT_R8_TYPELESS"; break;
          case DXGI_FORMAT_R8_UNORM:
              pstr = L"DXGI_FORMAT_R8_UNORM"; break;
          case DXGI_FORMAT_R8_UINT:
              pstr = L"DXGI_FORMAT_R8_UINT"; break;
          case DXGI_FORMAT_R8_SNORM:
              pstr = L"DXGI_FORMAT_R8_SNORM"; break;
          case DXGI_FORMAT_R8_SINT:
              pstr = L"DXGI_FORMAT_R8_SINT"; break;
          case DXGI_FORMAT_A8_UNORM:
              pstr = L"DXGI_FORMAT_A8_UNORM"; break;
          case DXGI_FORMAT_R1_UNORM:
              pstr = L"DXGI_FORMAT_R1_UNORM"; break;
          case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
              pstr = L"DXGI_FORMAT_R9G9B9E5_SHAREDEXP"; break;
          case DXGI_FORMAT_R8G8_B8G8_UNORM:
              pstr = L"DXGI_FORMAT_R8G8_B8G8_UNORM"; break;
          case DXGI_FORMAT_G8R8_G8B8_UNORM:
              pstr = L"DXGI_FORMAT_G8R8_G8B8_UNORM"; break;
          case DXGI_FORMAT_BC1_TYPELESS:
              pstr = L"DXGI_FORMAT_BC1_TYPELESS"; break;
          case DXGI_FORMAT_BC1_UNORM:
              pstr = L"DXGI_FORMAT_BC1_UNORM"; break;
          case DXGI_FORMAT_BC1_UNORM_SRGB:
              pstr = L"DXGI_FORMAT_BC1_UNORM_SRGB"; break;
          case DXGI_FORMAT_BC2_TYPELESS:
              pstr = L"DXGI_FORMAT_BC2_TYPELESS"; break;
          case DXGI_FORMAT_BC2_UNORM:
              pstr = L"DXGI_FORMAT_BC2_UNORM"; break;
          case DXGI_FORMAT_BC2_UNORM_SRGB:
              pstr = L"DXGI_FORMAT_BC2_UNORM_SRGB"; break;
          case DXGI_FORMAT_BC3_TYPELESS:
              pstr = L"DXGI_FORMAT_BC3_TYPELESS"; break;
          case DXGI_FORMAT_BC3_UNORM:
              pstr = L"DXGI_FORMAT_BC3_UNORM"; break;
          case DXGI_FORMAT_BC3_UNORM_SRGB:
              pstr = L"DXGI_FORMAT_BC3_UNORM_SRGB"; break;
          case DXGI_FORMAT_BC4_TYPELESS:
              pstr = L"DXGI_FORMAT_BC4_TYPELESS"; break;
          case DXGI_FORMAT_BC4_UNORM:
              pstr = L"DXGI_FORMAT_BC4_UNORM"; break;
          case DXGI_FORMAT_BC4_SNORM:
              pstr = L"DXGI_FORMAT_BC4_SNORM"; break;
          case DXGI_FORMAT_BC5_TYPELESS:
              pstr = L"DXGI_FORMAT_BC5_TYPELESS"; break;
          case DXGI_FORMAT_BC5_UNORM:
              pstr = L"DXGI_FORMAT_BC5_UNORM"; break;
          case DXGI_FORMAT_BC5_SNORM:
              pstr = L"DXGI_FORMAT_BC5_SNORM"; break;
          case DXGI_FORMAT_B5G6R5_UNORM:
              pstr = L"DXGI_FORMAT_B5G6R5_UNORM"; break;
          case DXGI_FORMAT_B5G5R5A1_UNORM:
              pstr = L"DXGI_FORMAT_B5G5R5A1_UNORM"; break;
          case DXGI_FORMAT_B8G8R8A8_UNORM:
              pstr = L"DXGI_FORMAT_B8G8R8A8_UNORM"; break;
          default:
              pstr = L"Unknown format"; break;
      }
      if( bWithPrefix || wcsstr( pstr, L"DXGI_FORMAT_" ) == NULL )
          return pstr;
      else
          return pstr + lstrlen( L"DXGI_FORMAT_" );
  }
  
  
  //--------------------------------------------------------------------------------------
  // Outputs to the debug stream a formatted Unicode string with a variable-argument list.
  //--------------------------------------------------------------------------------------
  VOID WINAPI DXUTOutputDebugStringW( LPCWSTR strMsg, ... )
  {
  #if defined(DEBUG) || defined(_DEBUG)
      WCHAR strBuffer[512];
  
      va_list args;
      va_start(args, strMsg);
      vswprintf_s( strBuffer, 512, strMsg, args );
      strBuffer[511] = L'\0';
      va_end(args);
  
      OutputDebugString( strBuffer );
  #else
      UNREFERENCED_PARAMETER( strMsg );
  #endif
  }
  
  
  //--------------------------------------------------------------------------------------
  // Outputs to the debug stream a formatted MBCS string with a variable-argument list.
  //--------------------------------------------------------------------------------------
  VOID WINAPI DXUTOutputDebugStringA( LPCSTR strMsg, ... )
  {
  #if defined(DEBUG) || defined(_DEBUG)
      CHAR strBuffer[512];
  
      va_list args;
      va_start(args, strMsg);
      vsprintf_s( strBuffer, 512, strMsg, args );
      strBuffer[511] = '\0';
      va_end(args);
  
      OutputDebugStringA( strBuffer );
  #else
      UNREFERENCED_PARAMETER( strMsg );
  #endif
  }
  
  
  //--------------------------------------------------------------------------------------
  // Direct3D9 dynamic linking support -- calls top-level D3D9 APIs with graceful
  // failure if APIs are not present.
  //--------------------------------------------------------------------------------------
  
  // Function prototypes
  typedef IDirect3D9*                         ( WINAPI* LPDIRECT3DCREATE9 )( UINT );
  typedef INT ( WINAPI* LPD3DPERF_BEGINEVENT )( D3DCOLOR, LPCWSTR );
  typedef INT ( WINAPI* LPD3DPERF_ENDEVENT )( void );
  typedef VOID ( WINAPI* LPD3DPERF_SETMARKER )( D3DCOLOR, LPCWSTR );
  typedef VOID ( WINAPI* LPD3DPERF_SETREGION )( D3DCOLOR, LPCWSTR );
  typedef BOOL ( WINAPI* LPD3DPERF_QUERYREPEATFRAME )( void );
  typedef VOID ( WINAPI* LPD3DPERF_SETOPTIONS )( DWORD dwOptions );
  typedef DWORD ( WINAPI* LPD3DPERF_GETSTATUS )( void );
  typedef HRESULT ( WINAPI* LPCREATEDXGIFACTORY )( REFIID, void** );
  typedef HRESULT ( WINAPI* LPD3D10CREATEDEVICE )( IDXGIAdapter*, D3D10_DRIVER_TYPE, HMODULE, UINT, UINT32,
                                                   ID3D10Device** );
  typedef HRESULT ( WINAPI* LPD3D10CREATEDEVICE1 )( IDXGIAdapter*, D3D10_DRIVER_TYPE, HMODULE, UINT,
                                                    D3D10_FEATURE_LEVEL1, UINT, ID3D10Device1** );
  typedef HRESULT ( WINAPI* LPD3D10CREATESTATEBLOCK )( ID3D10Device* pDevice, D3D10_STATE_BLOCK_MASK* pStateBlockMask,
                                                       ID3D10StateBlock** ppStateBlock );
  typedef HRESULT ( WINAPI* LPD3D10STATEBLOCKMASKUNION )( D3D10_STATE_BLOCK_MASK* pA, D3D10_STATE_BLOCK_MASK* pB,
                                                          D3D10_STATE_BLOCK_MASK* pResult );
  typedef HRESULT ( WINAPI* LPD3D10STATEBLOCKMASKINTERSECT )( D3D10_STATE_BLOCK_MASK* pA, D3D10_STATE_BLOCK_MASK* pB,
                                                              D3D10_STATE_BLOCK_MASK* pResult );
  typedef HRESULT ( WINAPI* LPD3D10STATEBLOCKMASKDIFFERENCE )( D3D10_STATE_BLOCK_MASK* pA, D3D10_STATE_BLOCK_MASK* pB,
                                                               D3D10_STATE_BLOCK_MASK* pResult );
  typedef HRESULT ( WINAPI* LPD3D10STATEBLOCKMASKENABLECAPTURE )( D3D10_STATE_BLOCK_MASK* pMask,
                                                                  D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart,
                                                                  UINT RangeLength );
  typedef HRESULT ( WINAPI* LPD3D10STATEBLOCKMASKDISABLECAPTURE )( D3D10_STATE_BLOCK_MASK* pMask,
                                                                   D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart,
                                                                   UINT RangeLength );
  typedef HRESULT ( WINAPI* LPD3D10STATEBLOCKMASKENABLEALL )( D3D10_STATE_BLOCK_MASK* pMask );
  typedef HRESULT ( WINAPI* LPD3D10STATEBLOCKMASKDISABLEALL )( D3D10_STATE_BLOCK_MASK* pMask );
  typedef BOOL ( WINAPI* LPD3D10STATEBLOCKMASKGETSETTING )( D3D10_STATE_BLOCK_MASK* pMask,
                                                            D3D10_DEVICE_STATE_TYPES StateType, UINT Entry );
  
  
  // Module and function pointers
  static HMODULE                              s_hModD3D9 = NULL;
  static LPDIRECT3DCREATE9                    s_DynamicDirect3DCreate9 = NULL;
  static LPD3DPERF_BEGINEVENT                 s_DynamicD3DPERF_BeginEvent = NULL;
  static LPD3DPERF_ENDEVENT                   s_DynamicD3DPERF_EndEvent = NULL;
  static LPD3DPERF_SETMARKER                  s_DynamicD3DPERF_SetMarker = NULL;
  static LPD3DPERF_SETREGION                  s_DynamicD3DPERF_SetRegion = NULL;
  static LPD3DPERF_QUERYREPEATFRAME           s_DynamicD3DPERF_QueryRepeatFrame = NULL;
  static LPD3DPERF_SETOPTIONS                 s_DynamicD3DPERF_SetOptions = NULL;
  static LPD3DPERF_GETSTATUS                  s_DynamicD3DPERF_GetStatus = NULL;
  static HMODULE                              s_hModDXGI = NULL;
  static LPCREATEDXGIFACTORY                  s_DynamicCreateDXGIFactory = NULL;
  static HMODULE                              s_hModD3D10 = NULL;
  static HMODULE                              s_hModD3D101 = NULL;
  static LPD3D10CREATESTATEBLOCK              s_DynamicD3D10CreateStateBlock = NULL;
  static LPD3D10CREATEDEVICE                  s_DynamicD3D10CreateDevice = NULL;
  static LPD3D10CREATEDEVICE1                 s_DynamicD3D10CreateDevice1 = NULL;
  static LPD3D10STATEBLOCKMASKUNION           s_DynamicD3D10StateBlockMaskUnion = NULL;
  static LPD3D10STATEBLOCKMASKINTERSECT       s_DynamicD3D10StateBlockMaskIntersect = NULL;
  static LPD3D10STATEBLOCKMASKDIFFERENCE      s_DynamicD3D10StateBlockMaskDifference = NULL;
  static LPD3D10STATEBLOCKMASKENABLECAPTURE   s_DynamicD3D10StateBlockMaskEnableCapture = NULL;
  static LPD3D10STATEBLOCKMASKDISABLECAPTURE  s_DynamicD3D10StateBlockMaskDisableCapture = NULL;
  static LPD3D10STATEBLOCKMASKENABLEALL       s_DynamicD3D10StateBlockMaskEnableAll = NULL;
  static LPD3D10STATEBLOCKMASKDISABLEALL      s_DynamicD3D10StateBlockMaskDisableAll = NULL;
  static LPD3D10STATEBLOCKMASKGETSETTING      s_DynamicD3D10StateBlockMaskGetSetting = NULL;
  
  
  // Ensure function pointers are initialized
  static bool DXUT_EnsureD3D9APIs( void )
  {
      // If the module is non-NULL, this function has already been called.  Note
      // that this doesn't guarantee that all ProcAddresses were found.
      if( s_hModD3D9 != NULL )
          return true;
  
      // This may fail if Direct3D 9 isn't installed
      s_hModD3D9 = LoadLibrary( L"d3d9.dll" );
      if( s_hModD3D9 != NULL )
      {
          s_DynamicDirect3DCreate9 = ( LPDIRECT3DCREATE9 )GetProcAddress( s_hModD3D9, "Direct3DCreate9" );
          s_DynamicD3DPERF_BeginEvent = ( LPD3DPERF_BEGINEVENT )GetProcAddress( s_hModD3D9, "D3DPERF_BeginEvent" );
          s_DynamicD3DPERF_EndEvent = ( LPD3DPERF_ENDEVENT )GetProcAddress( s_hModD3D9, "D3DPERF_EndEvent" );
          s_DynamicD3DPERF_SetMarker = ( LPD3DPERF_SETMARKER )GetProcAddress( s_hModD3D9, "D3DPERF_SetMarker" );
          s_DynamicD3DPERF_SetRegion = ( LPD3DPERF_SETREGION )GetProcAddress( s_hModD3D9, "D3DPERF_SetRegion" );
          s_DynamicD3DPERF_QueryRepeatFrame = ( LPD3DPERF_QUERYREPEATFRAME )GetProcAddress( s_hModD3D9,
                                                                                            "D3DPERF_QueryRepeatFrame" );
          s_DynamicD3DPERF_SetOptions = ( LPD3DPERF_SETOPTIONS )GetProcAddress( s_hModD3D9, "D3DPERF_SetOptions" );
          s_DynamicD3DPERF_GetStatus = ( LPD3DPERF_GETSTATUS )GetProcAddress( s_hModD3D9, "D3DPERF_GetStatus" );
      }
  
      return s_hModD3D9 != NULL;
  }
  
  static bool DXUT_EnsureD3D10APIs( void )
  {
      // If any module is non-NULL, this function has already been called.  Note
      // that this doesn't guarantee that all ProcAddresses were found.
      if( s_hModD3D10 != NULL || s_hModDXGI != NULL || s_hModD3D101 != NULL )
          return true;
  
      // This may fail if Direct3D 10 isn't installed
      s_hModD3D10 = LoadLibrary( L"d3d10.dll" );
      if( s_hModD3D10 != NULL )
      {
          s_DynamicD3D10CreateStateBlock = ( LPD3D10CREATESTATEBLOCK )GetProcAddress( s_hModD3D10,
                                                                                      "D3D10CreateStateBlock" );
          s_DynamicD3D10CreateDevice = ( LPD3D10CREATEDEVICE )GetProcAddress( s_hModD3D10, "D3D10CreateDevice" );
  
          s_DynamicD3D10StateBlockMaskUnion = ( LPD3D10STATEBLOCKMASKUNION )GetProcAddress( s_hModD3D10,
                                                                                            "D3D10StateBlockMaskUnion" );
          s_DynamicD3D10StateBlockMaskIntersect = ( LPD3D10STATEBLOCKMASKINTERSECT )GetProcAddress( s_hModD3D10,
                                                                                                    "D3D10StateBlockMaskIntersect" );
          s_DynamicD3D10StateBlockMaskDifference = ( LPD3D10STATEBLOCKMASKDIFFERENCE )GetProcAddress( s_hModD3D10,
                                                                                                      "D3D10StateBlockMaskDifference" );
          s_DynamicD3D10StateBlockMaskEnableCapture = ( LPD3D10STATEBLOCKMASKENABLECAPTURE )GetProcAddress( s_hModD3D10,
                                                                                                            "D3D10StateBlockMaskEnableCapture" );
          s_DynamicD3D10StateBlockMaskDisableCapture = ( LPD3D10STATEBLOCKMASKDISABLECAPTURE )
              GetProcAddress( s_hModD3D10, "D3D10StateBlockMaskDisableCapture" );
          s_DynamicD3D10StateBlockMaskEnableAll = ( LPD3D10STATEBLOCKMASKENABLEALL )GetProcAddress( s_hModD3D10,
                                                                                                    "D3D10StateBlockMaskEnableAll" );
          s_DynamicD3D10StateBlockMaskDisableAll = ( LPD3D10STATEBLOCKMASKDISABLEALL )GetProcAddress( s_hModD3D10,
                                                                                                      "D3D10StateBlockMaskDisableAll" );
          s_DynamicD3D10StateBlockMaskGetSetting = ( LPD3D10STATEBLOCKMASKGETSETTING )GetProcAddress( s_hModD3D10,
                                                                                                      "D3D10StateBlockMaskGetSetting" );
      }
  
      s_hModDXGI = LoadLibrary( L"dxgi.dll" );
      if( s_hModDXGI )
      {
          s_DynamicCreateDXGIFactory = ( LPCREATEDXGIFACTORY )GetProcAddress( s_hModDXGI, "CreateDXGIFactory" );
      }
  
      // This may fail if this machine isn't Windows Vista SP1 or later
      s_hModD3D101 = LoadLibrary( L"d3d10_1.dll" );
      if( s_hModD3D101 != NULL )
      {
          s_DynamicD3D10CreateDevice1 = ( LPD3D10CREATEDEVICE1 )GetProcAddress( s_hModD3D101, "D3D10CreateDevice1" );
      }
  
      return ( s_hModDXGI != NULL ) && ( s_hModD3D10 != NULL );
  }
  
  IDirect3D9* WINAPI DXUT_Dynamic_Direct3DCreate9( UINT SDKVersion )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicDirect3DCreate9 != NULL )
          return s_DynamicDirect3DCreate9( SDKVersion );
      else
          return NULL;
  }
  
  int WINAPI DXUT_Dynamic_D3DPERF_BeginEvent( D3DCOLOR col, LPCWSTR wszName )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_BeginEvent != NULL )
          return s_DynamicD3DPERF_BeginEvent( col, wszName );
      else
          return -1;
  }
  
  int WINAPI DXUT_Dynamic_D3DPERF_EndEvent( void )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_EndEvent != NULL )
          return s_DynamicD3DPERF_EndEvent();
      else
          return -1;
  }
  
  void WINAPI DXUT_Dynamic_D3DPERF_SetMarker( D3DCOLOR col, LPCWSTR wszName )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_SetMarker != NULL )
          s_DynamicD3DPERF_SetMarker( col, wszName );
  }
  
  void WINAPI DXUT_Dynamic_D3DPERF_SetRegion( D3DCOLOR col, LPCWSTR wszName )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_SetRegion != NULL )
          s_DynamicD3DPERF_SetRegion( col, wszName );
  }
  
  BOOL WINAPI DXUT_Dynamic_D3DPERF_QueryRepeatFrame( void )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_QueryRepeatFrame != NULL )
          return s_DynamicD3DPERF_QueryRepeatFrame();
      else
          return FALSE;
  }
  
  void WINAPI DXUT_Dynamic_D3DPERF_SetOptions( DWORD dwOptions )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_SetOptions != NULL )
          s_DynamicD3DPERF_SetOptions( dwOptions );
  }
  
  DWORD WINAPI DXUT_Dynamic_D3DPERF_GetStatus( void )
  {
      if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_GetStatus != NULL )
          return s_DynamicD3DPERF_GetStatus();
      else
          return 0;
  }
  
  HRESULT WINAPI DXUT_Dynamic_CreateDXGIFactory( REFIID rInterface, void** ppOut )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicCreateDXGIFactory != NULL )
          return s_DynamicCreateDXGIFactory( rInterface, ppOut );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10CreateDevice( IDXGIAdapter* pAdapter,
                                                 D3D10_DRIVER_TYPE DriverType,
                                                 HMODULE Software,
                                                 UINT32 Flags,
                                                 CONST void* pExtensions,
                                                 UINT32 SDKVersion,
                                                 ID3D10Device** ppDevice )
   {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10CreateDevice != NULL )
          return s_DynamicD3D10CreateDevice( pAdapter, DriverType, Software, Flags, SDKVersion, ppDevice );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10CreateDevice1( IDXGIAdapter* pAdapter,
                                                  D3D10_DRIVER_TYPE DriverType,
                                                  HMODULE Software,
                                                  UINT Flags,
                                                  D3D10_FEATURE_LEVEL1 HardwareLevel,
                                                  UINT SDKVersion,
                                                  ID3D10Device1** ppDevice )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10CreateDevice1 != NULL )
          return s_DynamicD3D10CreateDevice1( pAdapter, DriverType, Software, Flags, HardwareLevel, SDKVersion,
                                              ppDevice );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10CreateStateBlock( ID3D10Device* pDevice, D3D10_STATE_BLOCK_MASK* pStateBlockMask,
                                                     ID3D10StateBlock** ppStateBlock )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10CreateStateBlock != NULL )
          return s_DynamicD3D10CreateStateBlock( pDevice, pStateBlockMask, ppStateBlock );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10StateBlockMaskUnion( D3D10_STATE_BLOCK_MASK* pA, D3D10_STATE_BLOCK_MASK* pB,
                                                        D3D10_STATE_BLOCK_MASK* pResult )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskUnion != NULL )
          return s_DynamicD3D10StateBlockMaskUnion( pA, pB, pResult );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10StateBlockMaskIntersect( D3D10_STATE_BLOCK_MASK* pA, D3D10_STATE_BLOCK_MASK* pB,
                                                            D3D10_STATE_BLOCK_MASK* pResult )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskIntersect != NULL )
          return s_DynamicD3D10StateBlockMaskIntersect( pA, pB, pResult );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10StateBlockMaskDifference( D3D10_STATE_BLOCK_MASK* pA, D3D10_STATE_BLOCK_MASK* pB,
                                                             D3D10_STATE_BLOCK_MASK* pResult )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskDifference != NULL )
          return s_DynamicD3D10StateBlockMaskDifference( pA, pB, pResult );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10StateBlockMaskEnableCapture( D3D10_STATE_BLOCK_MASK* pMask,
                                                                D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart,
                                                                UINT RangeLength )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskEnableCapture != NULL )
          return s_DynamicD3D10StateBlockMaskEnableCapture( pMask, StateType, RangeStart, RangeLength );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10StateBlockMaskDisableCapture( D3D10_STATE_BLOCK_MASK* pMask,
                                                                 D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart,
                                                                 UINT RangeLength )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskDisableCapture != NULL )
          return s_DynamicD3D10StateBlockMaskDisableCapture( pMask, StateType, RangeStart, RangeLength );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10StateBlockMaskEnableAll( D3D10_STATE_BLOCK_MASK* pMask )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskEnableAll != NULL )
          return s_DynamicD3D10StateBlockMaskEnableAll( pMask );
      else
          return E_FAIL;
  }
  
  HRESULT WINAPI DXUT_Dynamic_D3D10StateBlockMaskDisableAll( D3D10_STATE_BLOCK_MASK* pMask )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskDisableAll != NULL )
          return s_DynamicD3D10StateBlockMaskDisableAll( pMask );
      else
          return E_FAIL;
  }
  
  BOOL WINAPI DXUT_Dynamic_D3D10StateBlockMaskGetSetting( D3D10_STATE_BLOCK_MASK* pMask,
                                                          D3D10_DEVICE_STATE_TYPES StateType, UINT Entry )
  {
      if( DXUT_EnsureD3D10APIs() && s_DynamicD3D10StateBlockMaskGetSetting != NULL )
          return s_DynamicD3D10StateBlockMaskGetSetting( pMask, StateType, Entry );
      else
          return FALSE;
  }
  
  //--------------------------------------------------------------------------------------
  // Trace a string description of a decl 
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTTraceDecl( D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE] )
  {
      int iDecl = 0;
      for( iDecl = 0; iDecl < MAX_FVF_DECL_SIZE; iDecl++ )
      {
          if( decl[iDecl].Stream == 0xFF )
              break;
  
          DXUTOutputDebugString( L"decl[%d]=Stream:%d, Offset:%d, %s, %s, %s, UsageIndex:%d\n", iDecl,
                                 decl[iDecl].Stream,
                                 decl[iDecl].Offset,
                                 DXUTTraceD3DDECLTYPEtoString( decl[iDecl].Type ),
                                 DXUTTraceD3DDECLMETHODtoString( decl[iDecl].Method ),
                                 DXUTTraceD3DDECLUSAGEtoString( decl[iDecl].Usage ),
                                 decl[iDecl].UsageIndex );
      }
  
      DXUTOutputDebugString( L"decl[%d]=D3DDECL_END\n", iDecl );
  }
  
  #define TRACE_ID(iD) case iD: return L#iD;
  
  //--------------------------------------------------------------------------------------
  WCHAR* WINAPI DXUTTraceWindowsMessage( UINT uMsg )
  {
      switch( uMsg )
      {
          TRACE_ID(WM_NULL);
          TRACE_ID(WM_CREATE);
          TRACE_ID(WM_DESTROY);
          TRACE_ID(WM_MOVE);
          TRACE_ID(WM_SIZE);
          TRACE_ID(WM_ACTIVATE);
          TRACE_ID(WM_SETFOCUS);
          TRACE_ID(WM_KILLFOCUS);
          TRACE_ID(WM_ENABLE);
          TRACE_ID(WM_SETREDRAW);
          TRACE_ID(WM_SETTEXT);
          TRACE_ID(WM_GETTEXT);
          TRACE_ID(WM_GETTEXTLENGTH);
          TRACE_ID(WM_PAINT);
          TRACE_ID(WM_CLOSE);
          TRACE_ID(WM_QUERYENDSESSION);
          TRACE_ID(WM_QUERYOPEN);
          TRACE_ID(WM_ENDSESSION);
          TRACE_ID(WM_QUIT);
          TRACE_ID(WM_ERASEBKGND);
          TRACE_ID(WM_SYSCOLORCHANGE);
          TRACE_ID(WM_SHOWWINDOW);
          TRACE_ID(WM_WININICHANGE);
          TRACE_ID(WM_DEVMODECHANGE);
          TRACE_ID(WM_ACTIVATEAPP);
          TRACE_ID(WM_FONTCHANGE);
          TRACE_ID(WM_TIMECHANGE);
          TRACE_ID(WM_CANCELMODE);
          TRACE_ID(WM_SETCURSOR);
          TRACE_ID(WM_MOUSEACTIVATE);
          TRACE_ID(WM_CHILDACTIVATE);
          TRACE_ID(WM_QUEUESYNC);
          TRACE_ID(WM_GETMINMAXINFO);
          TRACE_ID(WM_PAINTICON);
          TRACE_ID(WM_ICONERASEBKGND);
          TRACE_ID(WM_NEXTDLGCTL);
          TRACE_ID(WM_SPOOLERSTATUS);
          TRACE_ID(WM_DRAWITEM);
          TRACE_ID(WM_MEASUREITEM);
          TRACE_ID(WM_DELETEITEM);
          TRACE_ID(WM_VKEYTOITEM);
          TRACE_ID(WM_CHARTOITEM);
          TRACE_ID(WM_SETFONT);
          TRACE_ID(WM_GETFONT);
          TRACE_ID(WM_SETHOTKEY);
          TRACE_ID(WM_GETHOTKEY);
          TRACE_ID(WM_QUERYDRAGICON);
          TRACE_ID(WM_COMPAREITEM);
          TRACE_ID(WM_GETOBJECT);
          TRACE_ID(WM_COMPACTING);
          TRACE_ID(WM_COMMNOTIFY);
          TRACE_ID(WM_WINDOWPOSCHANGING);
          TRACE_ID(WM_WINDOWPOSCHANGED);
          TRACE_ID(WM_POWER);
          TRACE_ID(WM_COPYDATA);
          TRACE_ID(WM_CANCELJOURNAL);
          TRACE_ID(WM_NOTIFY);
          TRACE_ID(WM_INPUTLANGCHANGEREQUEST);
          TRACE_ID(WM_INPUTLANGCHANGE);
          TRACE_ID(WM_TCARD);
          TRACE_ID(WM_HELP);
          TRACE_ID(WM_USERCHANGED);
          TRACE_ID(WM_NOTIFYFORMAT);
          TRACE_ID(WM_CONTEXTMENU);
          TRACE_ID(WM_STYLECHANGING);
          TRACE_ID(WM_STYLECHANGED);
          TRACE_ID(WM_DISPLAYCHANGE);
          TRACE_ID(WM_GETICON);
          TRACE_ID(WM_SETICON);
          TRACE_ID(WM_NCCREATE);
          TRACE_ID(WM_NCDESTROY);
          TRACE_ID(WM_NCCALCSIZE);
          TRACE_ID(WM_NCHITTEST);
          TRACE_ID(WM_NCPAINT);
          TRACE_ID(WM_NCACTIVATE);
          TRACE_ID(WM_GETDLGCODE);
          TRACE_ID(WM_SYNCPAINT);
          TRACE_ID(WM_NCMOUSEMOVE);
          TRACE_ID(WM_NCLBUTTONDOWN);
          TRACE_ID(WM_NCLBUTTONUP);
          TRACE_ID(WM_NCLBUTTONDBLCLK);
          TRACE_ID(WM_NCRBUTTONDOWN);
          TRACE_ID(WM_NCRBUTTONUP);
          TRACE_ID(WM_NCRBUTTONDBLCLK);
          TRACE_ID(WM_NCMBUTTONDOWN);
          TRACE_ID(WM_NCMBUTTONUP);
          TRACE_ID(WM_NCMBUTTONDBLCLK);
          TRACE_ID(WM_NCXBUTTONDOWN);
          TRACE_ID(WM_NCXBUTTONUP);
          TRACE_ID(WM_NCXBUTTONDBLCLK);
          TRACE_ID(WM_INPUT);
          TRACE_ID(WM_KEYDOWN);
          TRACE_ID(WM_KEYUP);
          TRACE_ID(WM_CHAR);
          TRACE_ID(WM_DEADCHAR);
          TRACE_ID(WM_SYSKEYDOWN);
          TRACE_ID(WM_SYSKEYUP);
          TRACE_ID(WM_SYSCHAR);
          TRACE_ID(WM_SYSDEADCHAR);
          TRACE_ID(WM_UNICHAR);
          TRACE_ID(WM_IME_STARTCOMPOSITION);
          TRACE_ID(WM_IME_ENDCOMPOSITION);
          TRACE_ID(WM_IME_COMPOSITION);
          TRACE_ID(WM_INITDIALOG);
          TRACE_ID(WM_COMMAND);
          TRACE_ID(WM_SYSCOMMAND);
          TRACE_ID(WM_TIMER);
          TRACE_ID(WM_HSCROLL);
          TRACE_ID(WM_VSCROLL);
          TRACE_ID(WM_INITMENU);
          TRACE_ID(WM_INITMENUPOPUP);
          TRACE_ID(WM_MENUSELECT);
          TRACE_ID(WM_MENUCHAR);
          TRACE_ID(WM_ENTERIDLE);
          TRACE_ID(WM_MENURBUTTONUP);
          TRACE_ID(WM_MENUDRAG);
          TRACE_ID(WM_MENUGETOBJECT);
          TRACE_ID(WM_UNINITMENUPOPUP);
          TRACE_ID(WM_MENUCOMMAND);
          TRACE_ID(WM_CHANGEUISTATE);
          TRACE_ID(WM_UPDATEUISTATE);
          TRACE_ID(WM_QUERYUISTATE);
          TRACE_ID(WM_CTLCOLORMSGBOX);
          TRACE_ID(WM_CTLCOLOREDIT);
          TRACE_ID(WM_CTLCOLORLISTBOX);
          TRACE_ID(WM_CTLCOLORBTN);
          TRACE_ID(WM_CTLCOLORDLG);
          TRACE_ID(WM_CTLCOLORSCROLLBAR);
          TRACE_ID(WM_CTLCOLORSTATIC);
          TRACE_ID(MN_GETHMENU);
          TRACE_ID(WM_MOUSEMOVE);
          TRACE_ID(WM_LBUTTONDOWN);
          TRACE_ID(WM_LBUTTONUP);
          TRACE_ID(WM_LBUTTONDBLCLK);
          TRACE_ID(WM_RBUTTONDOWN);
          TRACE_ID(WM_RBUTTONUP);
          TRACE_ID(WM_RBUTTONDBLCLK);
          TRACE_ID(WM_MBUTTONDOWN);
          TRACE_ID(WM_MBUTTONUP);
          TRACE_ID(WM_MBUTTONDBLCLK);
          TRACE_ID(WM_MOUSEWHEEL);
          TRACE_ID(WM_XBUTTONDOWN);
          TRACE_ID(WM_XBUTTONUP);
          TRACE_ID(WM_XBUTTONDBLCLK);
          TRACE_ID(WM_PARENTNOTIFY);
          TRACE_ID(WM_ENTERMENULOOP);
          TRACE_ID(WM_EXITMENULOOP);
          TRACE_ID(WM_NEXTMENU);
          TRACE_ID(WM_SIZING);
          TRACE_ID(WM_CAPTURECHANGED);
          TRACE_ID(WM_MOVING);
          TRACE_ID(WM_POWERBROADCAST);
          TRACE_ID(WM_DEVICECHANGE);
          TRACE_ID(WM_MDICREATE);
          TRACE_ID(WM_MDIDESTROY);
          TRACE_ID(WM_MDIACTIVATE);
          TRACE_ID(WM_MDIRESTORE);
          TRACE_ID(WM_MDINEXT);
          TRACE_ID(WM_MDIMAXIMIZE);
          TRACE_ID(WM_MDITILE);
          TRACE_ID(WM_MDICASCADE);
          TRACE_ID(WM_MDIICONARRANGE);
          TRACE_ID(WM_MDIGETACTIVE);
          TRACE_ID(WM_MDISETMENU);
          TRACE_ID(WM_ENTERSIZEMOVE);
          TRACE_ID(WM_EXITSIZEMOVE);
          TRACE_ID(WM_DROPFILES);
          TRACE_ID(WM_MDIREFRESHMENU);
          TRACE_ID(WM_IME_SETCONTEXT);
          TRACE_ID(WM_IME_NOTIFY);
          TRACE_ID(WM_IME_CONTROL);
          TRACE_ID(WM_IME_COMPOSITIONFULL);
          TRACE_ID(WM_IME_SELECT);
          TRACE_ID(WM_IME_CHAR);
          TRACE_ID(WM_IME_REQUEST);
          TRACE_ID(WM_IME_KEYDOWN);
          TRACE_ID(WM_IME_KEYUP);
          TRACE_ID(WM_MOUSEHOVER);
          TRACE_ID(WM_MOUSELEAVE);
          TRACE_ID(WM_NCMOUSEHOVER);
          TRACE_ID(WM_NCMOUSELEAVE);
          TRACE_ID(WM_WTSSESSION_CHANGE);
          TRACE_ID(WM_TABLET_FIRST);
          TRACE_ID(WM_TABLET_LAST);
          TRACE_ID(WM_CUT);
          TRACE_ID(WM_COPY);
          TRACE_ID(WM_PASTE);
          TRACE_ID(WM_CLEAR);
          TRACE_ID(WM_UNDO);
          TRACE_ID(WM_RENDERFORMAT);
          TRACE_ID(WM_RENDERALLFORMATS);
          TRACE_ID(WM_DESTROYCLIPBOARD);
          TRACE_ID(WM_DRAWCLIPBOARD);
          TRACE_ID(WM_PAINTCLIPBOARD);
          TRACE_ID(WM_VSCROLLCLIPBOARD);
          TRACE_ID(WM_SIZECLIPBOARD);
          TRACE_ID(WM_ASKCBFORMATNAME);
          TRACE_ID(WM_CHANGECBCHAIN);
          TRACE_ID(WM_HSCROLLCLIPBOARD);
          TRACE_ID(WM_QUERYNEWPALETTE);
          TRACE_ID(WM_PALETTEISCHANGING);
          TRACE_ID(WM_PALETTECHANGED);
          TRACE_ID(WM_HOTKEY);
          TRACE_ID(WM_PRINT);
          TRACE_ID(WM_PRINTCLIENT);
          TRACE_ID(WM_APPCOMMAND);
          TRACE_ID(WM_THEMECHANGED);
          TRACE_ID(WM_HANDHELDFIRST);
          TRACE_ID(WM_HANDHELDLAST);
          TRACE_ID(WM_AFXFIRST);
          TRACE_ID(WM_AFXLAST);
          TRACE_ID(WM_PENWINFIRST);
          TRACE_ID(WM_PENWINLAST);
          TRACE_ID(WM_APP);
          default:
              return L"Unknown";
      }
  }
  
  
  //--------------------------------------------------------------------------------------
  WCHAR* WINAPI DXUTTraceD3DDECLTYPEtoString( BYTE t )
  {
      switch( t )
      {
          case D3DDECLTYPE_FLOAT1:
              return L"D3DDECLTYPE_FLOAT1";
          case D3DDECLTYPE_FLOAT2:
              return L"D3DDECLTYPE_FLOAT2";
          case D3DDECLTYPE_FLOAT3:
              return L"D3DDECLTYPE_FLOAT3";
          case D3DDECLTYPE_FLOAT4:
              return L"D3DDECLTYPE_FLOAT4";
          case D3DDECLTYPE_D3DCOLOR:
              return L"D3DDECLTYPE_D3DCOLOR";
          case D3DDECLTYPE_UBYTE4:
              return L"D3DDECLTYPE_UBYTE4";
          case D3DDECLTYPE_SHORT2:
              return L"D3DDECLTYPE_SHORT2";
          case D3DDECLTYPE_SHORT4:
              return L"D3DDECLTYPE_SHORT4";
          case D3DDECLTYPE_UBYTE4N:
              return L"D3DDECLTYPE_UBYTE4N";
          case D3DDECLTYPE_SHORT2N:
              return L"D3DDECLTYPE_SHORT2N";
          case D3DDECLTYPE_SHORT4N:
              return L"D3DDECLTYPE_SHORT4N";
          case D3DDECLTYPE_USHORT2N:
              return L"D3DDECLTYPE_USHORT2N";
          case D3DDECLTYPE_USHORT4N:
              return L"D3DDECLTYPE_USHORT4N";
          case D3DDECLTYPE_UDEC3:
              return L"D3DDECLTYPE_UDEC3";
          case D3DDECLTYPE_DEC3N:
              return L"D3DDECLTYPE_DEC3N";
          case D3DDECLTYPE_FLOAT16_2:
              return L"D3DDECLTYPE_FLOAT16_2";
          case D3DDECLTYPE_FLOAT16_4:
              return L"D3DDECLTYPE_FLOAT16_4";
          case D3DDECLTYPE_UNUSED:
              return L"D3DDECLTYPE_UNUSED";
          default:
              return L"D3DDECLTYPE Unknown";
      }
  }
  
  WCHAR* WINAPI DXUTTraceD3DDECLMETHODtoString( BYTE m )
  {
      switch( m )
      {
          case D3DDECLMETHOD_DEFAULT:
              return L"D3DDECLMETHOD_DEFAULT";
          case D3DDECLMETHOD_PARTIALU:
              return L"D3DDECLMETHOD_PARTIALU";
          case D3DDECLMETHOD_PARTIALV:
              return L"D3DDECLMETHOD_PARTIALV";
          case D3DDECLMETHOD_CROSSUV:
              return L"D3DDECLMETHOD_CROSSUV";
          case D3DDECLMETHOD_UV:
              return L"D3DDECLMETHOD_UV";
          case D3DDECLMETHOD_LOOKUP:
              return L"D3DDECLMETHOD_LOOKUP";
          case D3DDECLMETHOD_LOOKUPPRESAMPLED:
              return L"D3DDECLMETHOD_LOOKUPPRESAMPLED";
          default:
              return L"D3DDECLMETHOD Unknown";
      }
  }
  
  WCHAR* WINAPI DXUTTraceD3DDECLUSAGEtoString( BYTE u )
  {
      switch( u )
      {
          case D3DDECLUSAGE_POSITION:
              return L"D3DDECLUSAGE_POSITION";
          case D3DDECLUSAGE_BLENDWEIGHT:
              return L"D3DDECLUSAGE_BLENDWEIGHT";
          case D3DDECLUSAGE_BLENDINDICES:
              return L"D3DDECLUSAGE_BLENDINDICES";
          case D3DDECLUSAGE_NORMAL:
              return L"D3DDECLUSAGE_NORMAL";
          case D3DDECLUSAGE_PSIZE:
              return L"D3DDECLUSAGE_PSIZE";
          case D3DDECLUSAGE_TEXCOORD:
              return L"D3DDECLUSAGE_TEXCOORD";
          case D3DDECLUSAGE_TANGENT:
              return L"D3DDECLUSAGE_TANGENT";
          case D3DDECLUSAGE_BINORMAL:
              return L"D3DDECLUSAGE_BINORMAL";
          case D3DDECLUSAGE_TESSFACTOR:
              return L"D3DDECLUSAGE_TESSFACTOR";
          case D3DDECLUSAGE_POSITIONT:
              return L"D3DDECLUSAGE_POSITIONT";
          case D3DDECLUSAGE_COLOR:
              return L"D3DDECLUSAGE_COLOR";
          case D3DDECLUSAGE_FOG:
              return L"D3DDECLUSAGE_FOG";
          case D3DDECLUSAGE_DEPTH:
              return L"D3DDECLUSAGE_DEPTH";
          case D3DDECLUSAGE_SAMPLE:
              return L"D3DDECLUSAGE_SAMPLE";
          default:
              return L"D3DDECLUSAGE Unknown";
      }
  }
  
  
  //--------------------------------------------------------------------------------------
  // Multimon API handling for OSes with or without multimon API support
  //--------------------------------------------------------------------------------------
  #define DXUT_PRIMARY_MONITOR ((HMONITOR)0x12340042)
  typedef HMONITOR ( WINAPI* LPMONITORFROMWINDOW )( HWND, DWORD );
  typedef BOOL ( WINAPI* LPGETMONITORINFO )( HMONITOR, LPMONITORINFO );
  typedef HMONITOR ( WINAPI* LPMONITORFROMRECT )( LPCRECT lprcScreenCoords, DWORD dwFlags );
  
  BOOL WINAPI DXUTGetMonitorInfo( HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo )
  {
      static bool s_bInited = false;
      static LPGETMONITORINFO s_pFnGetMonitorInfo = NULL;
      if( !s_bInited )
      {
          s_bInited = true;
          HMODULE hUser32 = GetModuleHandle( L"USER32" );
          if( hUser32 )
          {
              OSVERSIONINFOA osvi = {0}; osvi.dwOSVersionInfoSize = sizeof( osvi );
              GetVersionExA( ( OSVERSIONINFOA* )&osvi );
              bool bNT = ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId );
              s_pFnGetMonitorInfo = ( LPGETMONITORINFO )( bNT ? GetProcAddress( hUser32,
                                                                                "GetMonitorInfoW" ) :
                                                          GetProcAddress( hUser32, "GetMonitorInfoA" ) );
          }
      }
  
      if( s_pFnGetMonitorInfo )
          return s_pFnGetMonitorInfo( hMonitor, lpMonitorInfo );
  
      RECT rcWork;
      if( ( hMonitor == DXUT_PRIMARY_MONITOR ) && lpMonitorInfo && ( lpMonitorInfo->cbSize >= sizeof( MONITORINFO ) ) &&
          SystemParametersInfoA( SPI_GETWORKAREA, 0, &rcWork, 0 ) )
      {
          lpMonitorInfo->rcMonitor.left = 0;
          lpMonitorInfo->rcMonitor.top = 0;
          lpMonitorInfo->rcMonitor.right = GetSystemMetrics( SM_CXSCREEN );
          lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics( SM_CYSCREEN );
          lpMonitorInfo->rcWork = rcWork;
          lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
          return TRUE;
      }
      return FALSE;
  }
  
  
  HMONITOR WINAPI DXUTMonitorFromWindow( HWND hWnd, DWORD dwFlags )
  {
      static bool s_bInited = false;
      static LPMONITORFROMWINDOW s_pFnGetMonitorFromWindow = NULL;
      if( !s_bInited )
      {
          s_bInited = true;
          HMODULE hUser32 = GetModuleHandle( L"USER32" );
          if( hUser32 ) s_pFnGetMonitorFromWindow = ( LPMONITORFROMWINDOW )GetProcAddress( hUser32,
                                                                                           "MonitorFromWindow" );
      }
  
      if( s_pFnGetMonitorFromWindow )
          return s_pFnGetMonitorFromWindow( hWnd, dwFlags );
      else
          return DXUT_PRIMARY_MONITOR;
  }
  
  
  HMONITOR WINAPI DXUTMonitorFromRect( LPCRECT lprcScreenCoords, DWORD dwFlags )
  {
      static bool s_bInited = false;
      static LPMONITORFROMRECT s_pFnGetMonitorFromRect = NULL;
      if( !s_bInited )
      {
          s_bInited = true;
          HMODULE hUser32 = GetModuleHandle( L"USER32" );
          if( hUser32 ) s_pFnGetMonitorFromRect = ( LPMONITORFROMRECT )GetProcAddress( hUser32, "MonitorFromRect" );
      }
  
      if( s_pFnGetMonitorFromRect )
          return s_pFnGetMonitorFromRect( lprcScreenCoords, dwFlags );
      else
          return DXUT_PRIMARY_MONITOR;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Get the desktop resolution of an adapter. This isn't the same as the current resolution 
  // from GetAdapterDisplayMode since the device might be fullscreen 
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTGetDesktopResolution( UINT AdapterOrdinal, UINT* pWidth, UINT* pHeight )
  {
      DXUTDeviceSettings DeviceSettings = DXUTGetDeviceSettings();
  
      WCHAR strDeviceName[256] = {0};
      DEVMODE devMode;
      ZeroMemory( &devMode, sizeof( DEVMODE ) );
      devMode.dmSize = sizeof( DEVMODE );
      if( DeviceSettings.ver == DXUT_D3D9_DEVICE )
      {
          CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration();
          CD3D9EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo( AdapterOrdinal );
          if( pAdapterInfo )
          {
              MultiByteToWideChar( CP_ACP, 0, pAdapterInfo->AdapterIdentifier.DeviceName, -1, strDeviceName, 256 );
              strDeviceName[255] = 0;
          }
      }
      else
      {
          CD3D10Enumeration* pd3dEnum = DXUTGetD3D10Enumeration();
          CD3D10EnumOutputInfo* pOutputInfo = pd3dEnum->GetOutputInfo( AdapterOrdinal, DeviceSettings.d3d10.Output );
          if( pOutputInfo )
          {
              wcscpy_s( strDeviceName, 256, pOutputInfo->Desc.DeviceName );
          }
      }
  
      EnumDisplaySettings( strDeviceName, ENUM_REGISTRY_SETTINGS, &devMode );
      if( pWidth )
          *pWidth = devMode.dmPelsWidth;
      if( pHeight )
          *pHeight = devMode.dmPelsHeight;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Display error msg box to help debug 
  //--------------------------------------------------------------------------------------
  HRESULT WINAPI DXUTTrace( const CHAR* strFile, DWORD dwLine, HRESULT hr,
                            const WCHAR* strMsg, bool bPopMsgBox )
  {
      bool bShowMsgBoxOnError = DXUTGetShowMsgBoxOnError();
      if( bPopMsgBox && bShowMsgBoxOnError == false )
          bPopMsgBox = false;
  
      return DXTrace( strFile, dwLine, hr, strMsg, bPopMsgBox );
  }
  
  
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTConvertDeviceSettings10to9( DXUTD3D10DeviceSettings* pIn, DXUTD3D9DeviceSettings* pOut )
  {
      pOut->AdapterOrdinal = pIn->AdapterOrdinal;
  
      if( pIn->DriverType == D3D10_DRIVER_TYPE_HARDWARE )
          pOut->DeviceType = D3DDEVTYPE_HAL;
      else if( pIn->DriverType == D3D10_DRIVER_TYPE_REFERENCE )
          pOut->DeviceType = D3DDEVTYPE_REF;
      else if( pIn->DriverType == D3D10_DRIVER_TYPE_NULL )
          pOut->DeviceType = D3DDEVTYPE_NULLREF;
  
      pOut->AdapterFormat = ConvertFormatDXGIToD3D9( pIn->sd.BufferDesc.Format );
      pOut->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
      pOut->pp.BackBufferWidth = pIn->sd.BufferDesc.Width;
      pOut->pp.BackBufferHeight = pIn->sd.BufferDesc.Height;
      pOut->pp.BackBufferFormat = ConvertFormatDXGIToD3D9( pIn->sd.BufferDesc.Format );
      pOut->pp.BackBufferCount = pIn->sd.BufferCount;
      pOut->pp.MultiSampleType = ( D3DMULTISAMPLE_TYPE )pIn->sd.SampleDesc.Count;
      pOut->pp.MultiSampleQuality = pIn->sd.SampleDesc.Quality;
      pOut->pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
      pOut->pp.hDeviceWindow = pIn->sd.OutputWindow;
      pOut->pp.Windowed = pIn->sd.Windowed;
      pOut->pp.EnableAutoDepthStencil = true;
      pOut->pp.AutoDepthStencilFormat = D3DFMT_D24FS8;
      pOut->pp.Flags = 0;
      if( pIn->sd.BufferDesc.RefreshRate.Denominator == 0 )
          pOut->pp.FullScreen_RefreshRateInHz = 60;
      else
          pOut->pp.FullScreen_RefreshRateInHz = pIn->sd.BufferDesc.RefreshRate.Numerator /
              pIn->sd.BufferDesc.RefreshRate.Denominator;
  
      switch( pIn->SyncInterval )
      {
          case 0:
              pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; break;
          case 2:
              pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_TWO; break;
          case 3:
              pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_THREE; break;
          case 4:
              pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_FOUR; break;
  
          case 1:
          default:
              pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
              break;
      }
  }
  
  
  //--------------------------------------------------------------------------------------
  void WINAPI DXUTConvertDeviceSettings9to10( DXUTD3D9DeviceSettings* pIn, DXUTD3D10DeviceSettings* pOut )
  {
      pOut->AdapterOrdinal = pIn->AdapterOrdinal;
  
      if( pIn->DeviceType == D3DDEVTYPE_HAL )
          pOut->DriverType = D3D10_DRIVER_TYPE_HARDWARE;
      else if( pIn->DeviceType == D3DDEVTYPE_REF )
          pOut->DriverType = D3D10_DRIVER_TYPE_REFERENCE;
      else if( pIn->DeviceType == D3DDEVTYPE_NULLREF )
          pOut->DriverType = D3D10_DRIVER_TYPE_NULL;
  
      pOut->Output = 0;
  
      pOut->sd.BufferDesc.Width = pIn->pp.BackBufferWidth;
      pOut->sd.BufferDesc.Height = pIn->pp.BackBufferHeight;
      pOut->sd.BufferDesc.RefreshRate.Numerator = 0;
      pOut->sd.BufferDesc.RefreshRate.Denominator = 0;
      pOut->sd.BufferDesc.Format = ConvertFormatD3D9ToDXGI( pIn->pp.BackBufferFormat );
  
      if( pIn->pp.MultiSampleType == D3DMULTISAMPLE_NONMASKABLE )
      {
          pOut->sd.SampleDesc.Count = pIn->pp.MultiSampleQuality;
          pOut->sd.SampleDesc.Quality = 0;
      }
      else
      {
          pOut->sd.SampleDesc.Count = pIn->pp.MultiSampleType;
          pOut->sd.SampleDesc.Quality = pIn->pp.MultiSampleQuality;
      }
  
      pOut->sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
      pOut->sd.BufferCount = pIn->pp.BackBufferCount;
      pOut->sd.OutputWindow = pIn->pp.hDeviceWindow;
      pOut->sd.Windowed = pIn->pp.Windowed;
  
  #if defined(DEBUG) || defined(_DEBUG)
      pOut->CreateFlags = D3D10_CREATE_DEVICE_DEBUG;
  #else
      pOut->CreateFlags = 0;
  #endif
  
      switch( pIn->pp.PresentationInterval )
      {
          case D3DPRESENT_INTERVAL_IMMEDIATE:
              pOut->SyncInterval = 0; break;
          case D3DPRESENT_INTERVAL_ONE:
              pOut->SyncInterval = 1; break;
          case D3DPRESENT_INTERVAL_TWO:
              pOut->SyncInterval = 2; break;
          case D3DPRESENT_INTERVAL_THREE:
              pOut->SyncInterval = 3; break;
          case D3DPRESENT_INTERVAL_FOUR:
              pOut->SyncInterval = 4; break;
  
          case D3DPRESENT_INTERVAL_DEFAULT:
          default:
              pOut->SyncInterval = 1;
              break;
      }
  
      pOut->PresentFlags = 0;
  }
  
  
  DXGI_FORMAT WINAPI ConvertFormatD3D9ToDXGI( D3DFORMAT fmt )
  {
      switch( fmt )
      {
          case D3DFMT_UNKNOWN:
              return DXGI_FORMAT_UNKNOWN;
          case D3DFMT_R8G8B8:
          case D3DFMT_A8R8G8B8:
          case D3DFMT_X8R8G8B8:
              return DXGI_FORMAT_R8G8B8A8_UNORM;
          case D3DFMT_R5G6B5:
              return DXGI_FORMAT_B5G6R5_UNORM;
          case D3DFMT_X1R5G5B5:
          case D3DFMT_A1R5G5B5:
              return DXGI_FORMAT_B5G5R5A1_UNORM;
          case D3DFMT_A4R4G4B4:
              return DXGI_FORMAT_R8G8B8A8_UNORM;
          case D3DFMT_R3G3B2:
              return DXGI_FORMAT_R8G8B8A8_UNORM;
          case D3DFMT_A8:
              return DXGI_FORMAT_A8_UNORM;
          case D3DFMT_A8R3G3B2:
              return DXGI_FORMAT_R8G8B8A8_UNORM;
          case D3DFMT_X4R4G4B4:
              return DXGI_FORMAT_R8G8B8A8_UNORM;
          case D3DFMT_A2B10G10R10:
              return DXGI_FORMAT_R10G10B10A2_UNORM;
          case D3DFMT_A8B8G8R8:
          case D3DFMT_X8B8G8R8:
              return DXGI_FORMAT_B8G8R8A8_UNORM;
          case D3DFMT_G16R16:
              return DXGI_FORMAT_R16G16_UNORM;
          case D3DFMT_A2R10G10B10:
              return DXGI_FORMAT_R10G10B10A2_UNORM;
          case D3DFMT_A16B16G16R16:
              return DXGI_FORMAT_R16G16B16A16_UNORM;
          case D3DFMT_R16F:
              return DXGI_FORMAT_R16_FLOAT;
          case D3DFMT_G16R16F:
              return DXGI_FORMAT_R16G16_FLOAT;
          case D3DFMT_A16B16G16R16F:
              return DXGI_FORMAT_R16G16B16A16_FLOAT;
          case D3DFMT_R32F:
              return DXGI_FORMAT_R32_FLOAT;
          case D3DFMT_G32R32F:
              return DXGI_FORMAT_R32G32_FLOAT;
          case D3DFMT_A32B32G32R32F:
              return DXGI_FORMAT_R32G32B32A32_FLOAT;
      }
      return DXGI_FORMAT_UNKNOWN;
  }
  
  
  D3DFORMAT WINAPI ConvertFormatDXGIToD3D9( DXGI_FORMAT fmt )
  {
      switch( fmt )
      {
          case DXGI_FORMAT_UNKNOWN:
              return D3DFMT_UNKNOWN;
          case DXGI_FORMAT_R8G8B8A8_UNORM:
              return D3DFMT_A8R8G8B8;
          case DXGI_FORMAT_B5G6R5_UNORM:
              return D3DFMT_R5G6B5;
          case DXGI_FORMAT_B5G5R5A1_UNORM:
              return D3DFMT_A1R5G5B5;
          case DXGI_FORMAT_A8_UNORM:
              return D3DFMT_A8;
          case DXGI_FORMAT_R10G10B10A2_UNORM:
              return D3DFMT_A2B10G10R10;
          case DXGI_FORMAT_B8G8R8A8_UNORM:
              return D3DFMT_A8B8G8R8;
          case DXGI_FORMAT_R16G16_UNORM:
              return D3DFMT_G16R16;
          case DXGI_FORMAT_R16G16B16A16_UNORM:
              return D3DFMT_A16B16G16R16;
          case DXGI_FORMAT_R16_FLOAT:
              return D3DFMT_R16F;
          case DXGI_FORMAT_R16G16_FLOAT:
              return D3DFMT_G16R16F;
          case DXGI_FORMAT_R16G16B16A16_FLOAT:
              return D3DFMT_A16B16G16R16F;
          case DXGI_FORMAT_R32_FLOAT:
              return D3DFMT_R32F;
          case DXGI_FORMAT_R32G32_FLOAT:
              return D3DFMT_G32R32F;
          case DXGI_FORMAT_R32G32B32A32_FLOAT:
              return D3DFMT_A32B32G32R32F;
      }
      return D3DFMT_UNKNOWN;
  }
  
  //--------------------------------------------------------------------------------------
  IDirect3DDevice9* WINAPI DXUTCreateRefDevice9( HWND hWnd, bool bNullRef )
  {
      HRESULT hr;
      IDirect3D9* pD3D = DXUT_Dynamic_Direct3DCreate9( D3D_SDK_VERSION );
      if( NULL == pD3D )
          return NULL;
  
      D3DDISPLAYMODE Mode;
      pD3D->GetAdapterDisplayMode( 0, &Mode );
  
      D3DPRESENT_PARAMETERS pp;
      ZeroMemory( &pp, sizeof( D3DPRESENT_PARAMETERS ) );
      pp.BackBufferWidth = 1;
      pp.BackBufferHeight = 1;
      pp.BackBufferFormat = Mode.Format;
      pp.BackBufferCount = 1;
      pp.SwapEffect = D3DSWAPEFFECT_COPY;
      pp.Windowed = TRUE;
      pp.hDeviceWindow = hWnd;
  
      IDirect3DDevice9* pd3dDevice = NULL;
      hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, bNullRef ? D3DDEVTYPE_NULLREF : D3DDEVTYPE_REF,
                               hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &pd3dDevice );
  
      SAFE_RELEASE( pD3D );
      return pd3dDevice;
  }
  
  //--------------------------------------------------------------------------------------
  ID3D10Device* WINAPI DXUTCreateRefDevice10( bool bNullRef )
  {
      HRESULT hr = S_OK;
      ID3D10Device* pDevice = NULL;
      hr = DXUT_Dynamic_D3D10CreateDevice(
          NULL, bNullRef ? D3D10_DRIVER_TYPE_NULL : D3D10_DRIVER_TYPE_REFERENCE,
          ( HMODULE )0, 0, 0, D3D10_SDK_VERSION, &pDevice );
      return pDevice;
  }
  
  //--------------------------------------------------------------------------------------
  // Helper function to launch the Media Center UI after the program terminates
  //--------------------------------------------------------------------------------------
  bool DXUTReLaunchMediaCenter()
  {
      // Get the path to Media Center
      WCHAR szExpandedPath[MAX_PATH];
      if( !ExpandEnvironmentStrings( L"%SystemRoot%\\ehome\\ehshell.exe", szExpandedPath, MAX_PATH ) )
          return false;
  
      // Skip if ehshell.exe doesn't exist
      if( GetFileAttributes( szExpandedPath ) == 0xFFFFFFFF )
          return false;
  
      // Launch ehshell.exe 
      INT_PTR result = ( INT_PTR )ShellExecute( NULL, TEXT( "open" ), szExpandedPath, NULL, NULL, SW_SHOWNORMAL );
      return ( result > 32 );
  }
  
  typedef DWORD ( WINAPI* LPXINPUTGETSTATE )( DWORD dwUserIndex, XINPUT_STATE* pState );
  typedef DWORD ( WINAPI* LPXINPUTSETSTATE )( DWORD dwUserIndex, XINPUT_VIBRATION* pVibration );
  typedef DWORD ( WINAPI* LPXINPUTGETCAPABILITIES )( DWORD dwUserIndex, DWORD dwFlags,
                                                     XINPUT_CAPABILITIES* pCapabilities );
  typedef void ( WINAPI* LPXINPUTENABLE )( BOOL bEnable );
  
  //--------------------------------------------------------------------------------------
  // Does extra processing on XInput data to make it slightly more convenient to use
  //--------------------------------------------------------------------------------------
  HRESULT DXUTGetGamepadState( DWORD dwPort, DXUT_GAMEPAD* pGamePad, bool bThumbstickDeadZone,
                               bool bSnapThumbstickToCardinals )
  {
      if( dwPort >= DXUT_MAX_CONTROLLERS || pGamePad == NULL )
          return E_FAIL;
  
      static LPXINPUTGETSTATE s_pXInputGetState = NULL;
      static LPXINPUTGETCAPABILITIES s_pXInputGetCapabilities = NULL;
      if( NULL == s_pXInputGetState || NULL == s_pXInputGetCapabilities )
      {
          HINSTANCE hInst = LoadLibrary( XINPUT_DLL );
          if( hInst )
          {
              s_pXInputGetState = ( LPXINPUTGETSTATE )GetProcAddress( hInst, "XInputGetState" );
              s_pXInputGetCapabilities = ( LPXINPUTGETCAPABILITIES )GetProcAddress( hInst, "XInputGetCapabilities" );
          }
      }
      if( s_pXInputGetState == NULL )
          return E_FAIL;
  
      XINPUT_STATE InputState;
      DWORD dwResult = s_pXInputGetState( dwPort, &InputState );
  
      // Track insertion and removals
      BOOL bWasConnected = pGamePad->bConnected;
      pGamePad->bConnected = ( dwResult == ERROR_SUCCESS );
      pGamePad->bRemoved = ( bWasConnected && !pGamePad->bConnected );
      pGamePad->bInserted = ( !bWasConnected && pGamePad->bConnected );
  
      // Don't update rest of the state if not connected
      if( !pGamePad->bConnected )
          return S_OK;
  
      // Store the capabilities of the device
      if( pGamePad->bInserted )
      {
          ZeroMemory( pGamePad, sizeof( DXUT_GAMEPAD ) );
          pGamePad->bConnected = true;
          pGamePad->bInserted = true;
          if( s_pXInputGetCapabilities )
              s_pXInputGetCapabilities( dwPort, XINPUT_DEVTYPE_GAMEPAD, &pGamePad->caps );
      }
  
      // Copy gamepad to local structure (assumes that XINPUT_GAMEPAD at the front in CONTROLER_STATE)
      memcpy( pGamePad, &InputState.Gamepad, sizeof( XINPUT_GAMEPAD ) );
  
      if( bSnapThumbstickToCardinals )
      {
          // Apply deadzone to each axis independantly to slightly snap to up/down/left/right
          if( pGamePad->sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
              pGamePad->sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE )
              pGamePad->sThumbLX = 0;
          if( pGamePad->sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
              pGamePad->sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE )
              pGamePad->sThumbLY = 0;
          if( pGamePad->sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
              pGamePad->sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE )
              pGamePad->sThumbRX = 0;
          if( pGamePad->sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
              pGamePad->sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE )
              pGamePad->sThumbRY = 0;
      }
      else if( bThumbstickDeadZone )
      {
          // Apply deadzone if centered
          if( ( pGamePad->sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
                pGamePad->sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) &&
              ( pGamePad->sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
                pGamePad->sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) )
          {
              pGamePad->sThumbLX = 0;
              pGamePad->sThumbLY = 0;
          }
          if( ( pGamePad->sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
                pGamePad->sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ) &&
              ( pGamePad->sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
                pGamePad->sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ) )
          {
              pGamePad->sThumbRX = 0;
              pGamePad->sThumbRY = 0;
          }
      }
  
      // Convert [-1,+1] range
      pGamePad->fThumbLX = pGamePad->sThumbLX / 32767.0f;
      pGamePad->fThumbLY = pGamePad->sThumbLY / 32767.0f;
      pGamePad->fThumbRX = pGamePad->sThumbRX / 32767.0f;
      pGamePad->fThumbRY = pGamePad->sThumbRY / 32767.0f;
  
      // Get the boolean buttons that have been pressed since the last call. 
      // Each button is represented by one bit.
      pGamePad->wPressedButtons = ( pGamePad->wLastButtons ^ pGamePad->wButtons ) & pGamePad->wButtons;
      pGamePad->wLastButtons = pGamePad->wButtons;
  
      // Figure out if the left trigger has been pressed or released
      bool bPressed = ( pGamePad->bLeftTrigger > DXUT_GAMEPAD_TRIGGER_THRESHOLD );
      pGamePad->bPressedLeftTrigger = ( bPressed ) ? !pGamePad->bLastLeftTrigger : false;
      pGamePad->bLastLeftTrigger = bPressed;
  
      // Figure out if the right trigger has been pressed or released
      bPressed = ( pGamePad->bRightTrigger > DXUT_GAMEPAD_TRIGGER_THRESHOLD );
      pGamePad->bPressedRightTrigger = ( bPressed ) ? !pGamePad->bLastRightTrigger : false;
      pGamePad->bLastRightTrigger = bPressed;
  
      return S_OK;
  }
  
  
  //--------------------------------------------------------------------------------------
  // Don't pause the game or deactive the window without first stopping rumble otherwise 
  // the controller will continue to rumble
  //--------------------------------------------------------------------------------------
  void DXUTEnableXInput( bool bEnable )
  {
      static LPXINPUTENABLE s_pXInputEnable = NULL;
      if( NULL == s_pXInputEnable )
      {
          HINSTANCE hInst = LoadLibrary( XINPUT_DLL );
          if( hInst )
              s_pXInputEnable = ( LPXINPUTENABLE )GetProcAddress( hInst, "XInputEnable" );
      }
  
      if( s_pXInputEnable )
          s_pXInputEnable( bEnable );
  }
  
  
  //--------------------------------------------------------------------------------------
  // Don't pause the game or deactive the window without first stopping rumble otherwise 
  // the controller will continue to rumble
  //--------------------------------------------------------------------------------------
  HRESULT DXUTStopRumbleOnAllControllers()
  {
      static LPXINPUTSETSTATE s_pXInputSetState = NULL;
      if( NULL == s_pXInputSetState )
      {
          HINSTANCE hInst = LoadLibrary( XINPUT_DLL );
          if( hInst )
              s_pXInputSetState = ( LPXINPUTSETSTATE )GetProcAddress( hInst, "XInputSetState" );
      }
      if( s_pXInputSetState == NULL )
          return E_FAIL;
  
      XINPUT_VIBRATION vibration;
      vibration.wLeftMotorSpeed = 0;
      vibration.wRightMotorSpeed = 0;
      for( int iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ )
          s_pXInputSetState( iUserIndex, &vibration );
  
      return S_OK;
  }
  
  //--------------------------------------------------------------------------------------
  // Helper functions to create SRGB formats from typeless formats and vice versa
  //--------------------------------------------------------------------------------------
  DXGI_FORMAT MAKE_SRGB( DXGI_FORMAT format )
  {
      if( !DXUTIsInGammaCorrectMode() )
          return format;
  
      switch( format )
      {
          case DXGI_FORMAT_R8G8B8A8_TYPELESS:
          case DXGI_FORMAT_R8G8B8A8_UNORM:
          case DXGI_FORMAT_R8G8B8A8_UINT:
          case DXGI_FORMAT_R8G8B8A8_SNORM:
          case DXGI_FORMAT_R8G8B8A8_SINT:
              return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
  
          case DXGI_FORMAT_BC1_TYPELESS:
          case DXGI_FORMAT_BC1_UNORM:
              return DXGI_FORMAT_BC1_UNORM_SRGB;
          case DXGI_FORMAT_BC2_TYPELESS:
          case DXGI_FORMAT_BC2_UNORM:
              return DXGI_FORMAT_BC2_UNORM_SRGB;
          case DXGI_FORMAT_BC3_TYPELESS:
          case DXGI_FORMAT_BC3_UNORM:
              return DXGI_FORMAT_BC3_UNORM_SRGB;
  
      };
  
      return format;
  }
  
  //--------------------------------------------------------------------------------------
  DXGI_FORMAT MAKE_TYPELESS( DXGI_FORMAT format )
  {
      if( !DXUTIsInGammaCorrectMode() )
          return format;
  
      switch( format )
      {
          case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
          case DXGI_FORMAT_R8G8B8A8_UNORM:
          case DXGI_FORMAT_R8G8B8A8_UINT:
          case DXGI_FORMAT_R8G8B8A8_SNORM:
          case DXGI_FORMAT_R8G8B8A8_SINT:
              return DXGI_FORMAT_R8G8B8A8_TYPELESS;
  
          case DXGI_FORMAT_BC1_UNORM_SRGB:
          case DXGI_FORMAT_BC1_UNORM:
              return DXGI_FORMAT_BC1_TYPELESS;
          case DXGI_FORMAT_BC2_UNORM_SRGB:
          case DXGI_FORMAT_BC2_UNORM:
              return DXGI_FORMAT_BC2_TYPELESS;
          case DXGI_FORMAT_BC3_UNORM_SRGB:
          case DXGI_FORMAT_BC3_UNORM:
              return DXGI_FORMAT_BC3_TYPELESS;
      };
  
      return format;
  }
  