1033 lines
34 KiB
C++
1033 lines
34 KiB
C++
//--------------------------------------------------------------------------------------
|
|
// File: SDKmisc.cpp
|
|
//
|
|
// Various helper functionality that is shared between SDK samples
|
|
//
|
|
// 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"
|
|
#include "SDKmisc.h"
|
|
#include "DXUTres.h"
|
|
|
|
#include "DXUTGui.h"
|
|
|
|
#include "DDSTextureLoader.h"
|
|
#include "WICTextureLoader.h"
|
|
#include "ScreenGrab.h"
|
|
|
|
using namespace DirectX;
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Global/Static Members
|
|
//--------------------------------------------------------------------------------------
|
|
CDXUTResourceCache& WINAPI DXUTGetGlobalResourceCache()
|
|
{
|
|
// Using an accessor function gives control of the construction order
|
|
static CDXUTResourceCache* s_cache = nullptr;
|
|
if ( !s_cache )
|
|
{
|
|
#if defined(DEBUG) || defined(_DEBUG)
|
|
int flag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
|
|
_CrtSetDbgFlag( flag & ~_CRTDBG_ALLOC_MEM_DF );
|
|
#endif
|
|
s_cache = new CDXUTResourceCache;
|
|
#if defined(DEBUG) || defined(_DEBUG)
|
|
_CrtSetDbgFlag( flag );
|
|
#endif
|
|
}
|
|
return *s_cache;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Internal functions forward declarations
|
|
//--------------------------------------------------------------------------------------
|
|
bool DXUTFindMediaSearchTypicalDirs( _Out_writes_(cchSearch) WCHAR* strSearchPath,
|
|
_In_ int cchSearch,
|
|
_In_ LPCWSTR strLeaf,
|
|
_In_ const WCHAR* strExePath,
|
|
_In_ const WCHAR* strExeName );
|
|
bool DXUTFindMediaSearchParentDirs( _Out_writes_(cchSearch) WCHAR* strSearchPath,
|
|
_In_ int cchSearch,
|
|
_In_ const WCHAR* strStartAt,
|
|
_In_ const WCHAR* strLeafName );
|
|
|
|
INT_PTR CALLBACK DisplaySwitchToREFWarningProc( _In_ HWND hDlg, _In_ UINT message, _In_ WPARAM wParam, _In_ LPARAM lParam );
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Shared code for samples to ask user if they want to use a REF device or quit
|
|
//--------------------------------------------------------------------------------------
|
|
void WINAPI DXUTDisplaySwitchingToREFWarning()
|
|
{
|
|
if( DXUTGetShowMsgBoxOnError() )
|
|
{
|
|
DWORD dwSkipWarning = 0, dwRead = 0, dwWritten = 0;
|
|
HANDLE hFile = nullptr;
|
|
|
|
// Read previous user settings
|
|
WCHAR strPath[MAX_PATH];
|
|
if ( SUCCEEDED(SHGetFolderPath(DXUTGetHWND(), CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, strPath)) )
|
|
{
|
|
wcscat_s( strPath, MAX_PATH, L"\\DXUT\\SkipRefWarning.dat" );
|
|
if( ( hFile = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0,
|
|
nullptr ) ) != INVALID_HANDLE_VALUE )
|
|
{
|
|
(void)ReadFile( hFile, &dwSkipWarning, sizeof( DWORD ), &dwRead, nullptr );
|
|
CloseHandle( hFile );
|
|
}
|
|
}
|
|
|
|
if( dwSkipWarning == 0 )
|
|
{
|
|
// Compact code to create a custom dialog box without using a template in a resource file.
|
|
// If this dialog were in a .rc file, this would be a lot simpler but every sample calling this function would
|
|
// need a copy of the dialog in its own .rc file. Also MessageBox API could be used here instead, but
|
|
// the MessageBox API is simpler to call but it can't provide a "Don't show again" checkbox
|
|
typedef struct
|
|
{
|
|
DLGITEMTEMPLATE a;
|
|
WORD b;
|
|
WORD c;
|
|
WORD d;
|
|
WORD e;
|
|
WORD f;
|
|
} DXUT_DLG_ITEM;
|
|
typedef struct
|
|
{
|
|
DLGTEMPLATE a;
|
|
WORD b;
|
|
WORD c;
|
|
WCHAR d[2];
|
|
WORD e;
|
|
WCHAR f[16];
|
|
DXUT_DLG_ITEM i1;
|
|
DXUT_DLG_ITEM i2;
|
|
DXUT_DLG_ITEM i3;
|
|
DXUT_DLG_ITEM i4;
|
|
DXUT_DLG_ITEM i5;
|
|
} DXUT_DLG_DATA;
|
|
|
|
DXUT_DLG_DATA dtp =
|
|
{
|
|
{WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_SYSMENU | DS_ABSALIGN | DS_3DLOOK | DS_SETFONT |
|
|
DS_MODALFRAME | DS_CENTER,0,5,0,0,269,82},0,0,L" ",8,L"MS Shell Dlg 2",
|
|
{ {WS_CHILD | WS_VISIBLE | SS_ICON | SS_CENTERIMAGE,0,7,7,24,24,0x100},0xFFFF,0x0082,0,0,0}, // icon
|
|
{ {WS_CHILD | WS_VISIBLE,0,40,7,230,25,0x101},0xFFFF,0x0082,0,0,0}, // static text
|
|
{ {WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,0,80,39,50,14,IDYES},0xFFFF,0x0080,0,0,0}, // Yes button
|
|
{ {WS_CHILD | WS_VISIBLE | WS_TABSTOP,0,133,39,50,14,IDNO},0xFFFF,0x0080,0,0,0}, // No button
|
|
{ {WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX,0,7,59,70,16,IDIGNORE},0xFFFF,0x0080,0,0,0}, // checkbox
|
|
};
|
|
|
|
LPARAM lParam;
|
|
lParam = 11;
|
|
int nResult = ( int )DialogBoxIndirectParam( DXUTGetHINSTANCE(), ( DLGTEMPLATE* )&dtp, DXUTGetHWND(),
|
|
DisplaySwitchToREFWarningProc, lParam );
|
|
|
|
if( ( nResult & 0x80 ) == 0x80 ) // "Don't show again" checkbox was checked
|
|
{
|
|
// Save user settings
|
|
dwSkipWarning = 1;
|
|
if ( SUCCEEDED(SHGetFolderPath(DXUTGetHWND(), CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, strPath)) )
|
|
{
|
|
wcscat_s( strPath, MAX_PATH, L"\\DXUT" );
|
|
CreateDirectory( strPath, nullptr );
|
|
wcscat_s( strPath, MAX_PATH, L"\\SkipRefWarning.dat" );
|
|
if( ( hFile = CreateFile( strPath, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0,
|
|
nullptr ) ) != INVALID_HANDLE_VALUE )
|
|
{
|
|
WriteFile( hFile, &dwSkipWarning, sizeof( DWORD ), &dwWritten, nullptr );
|
|
CloseHandle( hFile );
|
|
}
|
|
}
|
|
}
|
|
|
|
// User choose not to continue
|
|
if( ( nResult & 0x0F ) == IDNO )
|
|
DXUTShutdown( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// MsgProc for DXUTDisplaySwitchingToREFWarning() dialog box
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
INT_PTR CALLBACK DisplaySwitchToREFWarningProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch( message )
|
|
{
|
|
case WM_INITDIALOG:
|
|
// Easier to set text here than in the DLGITEMTEMPLATE
|
|
SetWindowText( hDlg, DXUTGetWindowTitle() );
|
|
SendMessage( GetDlgItem( hDlg, 0x100 ), STM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadIcon( 0, IDI_QUESTION ) );
|
|
WCHAR sz[512];
|
|
swprintf_s( sz, 512,
|
|
L"This program needs to use the Direct3D %Iu reference device. This device implements the entire Direct3D %Iu feature set, but runs very slowly. Do you wish to continue?", lParam, lParam );
|
|
SetDlgItemText( hDlg, 0x101, sz );
|
|
SetDlgItemText( hDlg, IDYES, L"&Yes" );
|
|
SetDlgItemText( hDlg, IDNO, L"&No" );
|
|
SetDlgItemText( hDlg, IDIGNORE, L"&Don't show again" );
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch( LOWORD( wParam ) )
|
|
{
|
|
case IDIGNORE:
|
|
CheckDlgButton( hDlg, IDIGNORE, ( IsDlgButtonChecked( hDlg,
|
|
IDIGNORE ) == BST_CHECKED ) ? BST_UNCHECKED :
|
|
BST_CHECKED );
|
|
EnableWindow( GetDlgItem( hDlg, IDNO ), ( IsDlgButtonChecked( hDlg, IDIGNORE ) != BST_CHECKED ) );
|
|
break;
|
|
case IDNO:
|
|
EndDialog( hDlg, ( IsDlgButtonChecked( hDlg, IDIGNORE ) == BST_CHECKED ) ? IDNO | 0x80 : IDNO |
|
|
0x00 ); return TRUE;
|
|
case IDCANCEL:
|
|
case IDYES:
|
|
EndDialog( hDlg, ( IsDlgButtonChecked( hDlg, IDIGNORE ) == BST_CHECKED ) ? IDYES | 0x80 : IDYES |
|
|
0x00 ); return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Returns pointer to static media search buffer
|
|
//--------------------------------------------------------------------------------------
|
|
WCHAR* DXUTMediaSearchPath()
|
|
{
|
|
static WCHAR s_strMediaSearchPath[MAX_PATH] =
|
|
{
|
|
0
|
|
};
|
|
return s_strMediaSearchPath;
|
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
LPCWSTR WINAPI DXUTGetMediaSearchPath()
|
|
{
|
|
return DXUTMediaSearchPath();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT WINAPI DXUTSetMediaSearchPath( _In_z_ LPCWSTR strPath )
|
|
{
|
|
HRESULT hr;
|
|
|
|
WCHAR* s_strSearchPath = DXUTMediaSearchPath();
|
|
|
|
hr = wcscpy_s( s_strSearchPath, MAX_PATH, strPath );
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
// append slash if needed
|
|
size_t ch = 0;
|
|
ch = wcsnlen( s_strSearchPath, MAX_PATH);
|
|
if( SUCCEEDED( hr ) && s_strSearchPath[ch - 1] != L'\\' )
|
|
{
|
|
hr = wcscat_s( s_strSearchPath, MAX_PATH, L"\\" );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Tries to find the location of a SDK media file
|
|
// cchDest is the size in WCHARs of strDestPath. Be careful not to
|
|
// pass in sizeof(strDest) on UNICODE builds.
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT WINAPI DXUTFindDXSDKMediaFileCch( WCHAR* strDestPath, int cchDest,
|
|
LPCWSTR strFilename )
|
|
{
|
|
bool bFound;
|
|
WCHAR strSearchFor[MAX_PATH];
|
|
|
|
if( !strFilename || strFilename[0] == 0 || !strDestPath || cchDest < 10 )
|
|
return E_INVALIDARG;
|
|
|
|
// Get the exe name, and exe path
|
|
WCHAR strExePath[MAX_PATH] =
|
|
{
|
|
0
|
|
};
|
|
WCHAR strExeName[MAX_PATH] =
|
|
{
|
|
0
|
|
};
|
|
WCHAR* strLastSlash = nullptr;
|
|
GetModuleFileName( nullptr, strExePath, MAX_PATH );
|
|
strExePath[MAX_PATH - 1] = 0;
|
|
strLastSlash = wcsrchr( strExePath, TEXT( '\\' ) );
|
|
if( strLastSlash )
|
|
{
|
|
wcscpy_s( strExeName, MAX_PATH, &strLastSlash[1] );
|
|
|
|
// Chop the exe name from the exe path
|
|
*strLastSlash = 0;
|
|
|
|
// Chop the .exe from the exe name
|
|
strLastSlash = wcsrchr( strExeName, TEXT( '.' ) );
|
|
if( strLastSlash )
|
|
*strLastSlash = 0;
|
|
}
|
|
|
|
// Typical directories:
|
|
// .\
|
|
// ..\
|
|
// ..\..\
|
|
// %EXE_DIR%\
|
|
// %EXE_DIR%\..\
|
|
// %EXE_DIR%\..\..\
|
|
// %EXE_DIR%\..\%EXE_NAME%
|
|
// %EXE_DIR%\..\..\%EXE_NAME%
|
|
|
|
// Typical directory search
|
|
bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strFilename, strExePath, strExeName );
|
|
if( bFound )
|
|
return S_OK;
|
|
|
|
// Typical directory search again, but also look in a subdir called "\media\"
|
|
swprintf_s( strSearchFor, MAX_PATH, L"media\\%ls", strFilename );
|
|
bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strSearchFor, strExePath, strExeName );
|
|
if( bFound )
|
|
return S_OK;
|
|
|
|
WCHAR strLeafName[MAX_PATH] =
|
|
{
|
|
0
|
|
};
|
|
|
|
// Search all parent directories starting at .\ and using strFilename as the leaf name
|
|
wcscpy_s( strLeafName, MAX_PATH, strFilename );
|
|
bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName );
|
|
if( bFound )
|
|
return S_OK;
|
|
|
|
// Search all parent directories starting at the exe's dir and using strFilename as the leaf name
|
|
bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName );
|
|
if( bFound )
|
|
return S_OK;
|
|
|
|
// Search all parent directories starting at .\ and using "media\strFilename" as the leaf name
|
|
swprintf_s( strLeafName, MAX_PATH, L"media\\%ls", strFilename );
|
|
bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName );
|
|
if( bFound )
|
|
return S_OK;
|
|
|
|
// Search all parent directories starting at the exe's dir and using "media\strFilename" as the leaf name
|
|
bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName );
|
|
if( bFound )
|
|
return S_OK;
|
|
|
|
// On failure, return the file as the path but also return an error code
|
|
wcscpy_s( strDestPath, cchDest, strFilename );
|
|
|
|
return DXUTERR_MEDIANOTFOUND;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Search a set of typical directories
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
bool DXUTFindMediaSearchTypicalDirs( WCHAR* strSearchPath, int cchSearch, LPCWSTR strLeaf,
|
|
const WCHAR* strExePath, const WCHAR* strExeName )
|
|
{
|
|
// Typical directories:
|
|
// .\
|
|
// ..\
|
|
// ..\..\
|
|
// %EXE_DIR%\
|
|
// %EXE_DIR%\..\
|
|
// %EXE_DIR%\..\..\
|
|
// %EXE_DIR%\..\%EXE_NAME%
|
|
// %EXE_DIR%\..\..\%EXE_NAME%
|
|
// DXSDK media path
|
|
|
|
// Search in .\
|
|
wcscpy_s( strSearchPath, cchSearch, strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in ..\
|
|
swprintf_s( strSearchPath, cchSearch, L"..\\%ls", strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in ..\..\
|
|
swprintf_s( strSearchPath, cchSearch, L"..\\..\\%ls", strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in ..\..\
|
|
swprintf_s( strSearchPath, cchSearch, L"..\\..\\%ls", strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in the %EXE_DIR%\
|
|
swprintf_s( strSearchPath, cchSearch, L"%ls\\%ls", strExePath, strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in the %EXE_DIR%\..\
|
|
swprintf_s( strSearchPath, cchSearch, L"%ls\\..\\%ls", strExePath, strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in the %EXE_DIR%\..\..\
|
|
swprintf_s( strSearchPath, cchSearch, L"%ls\\..\\..\\%ls", strExePath, strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in "%EXE_DIR%\..\%EXE_NAME%\". This matches the DirectX SDK layout
|
|
swprintf_s( strSearchPath, cchSearch, L"%ls\\..\\%ls\\%ls", strExePath, strExeName, strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in "%EXE_DIR%\..\..\%EXE_NAME%\". This matches the DirectX SDK layout
|
|
swprintf_s( strSearchPath, cchSearch, L"%ls\\..\\..\\%ls\\%ls", strExePath, strExeName, strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
|
|
// Search in media search dir
|
|
WCHAR* s_strSearchPath = DXUTMediaSearchPath();
|
|
if( s_strSearchPath[0] != 0 )
|
|
{
|
|
swprintf_s( strSearchPath, cchSearch, L"%ls%ls", s_strSearchPath, strLeaf );
|
|
if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Search parent directories starting at strStartAt, and appending strLeafName
|
|
// at each parent directory. It stops at the root directory.
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
bool DXUTFindMediaSearchParentDirs( WCHAR* strSearchPath, int cchSearch, const WCHAR* strStartAt,
|
|
const WCHAR* strLeafName )
|
|
{
|
|
WCHAR strFullPath[MAX_PATH] =
|
|
{
|
|
0
|
|
};
|
|
WCHAR strFullFileName[MAX_PATH] =
|
|
{
|
|
0
|
|
};
|
|
WCHAR strSearch[MAX_PATH] =
|
|
{
|
|
0
|
|
};
|
|
WCHAR* strFilePart = nullptr;
|
|
|
|
if ( !GetFullPathName( strStartAt, MAX_PATH, strFullPath, &strFilePart ) )
|
|
return false;
|
|
|
|
#pragma warning( disable : 6102 )
|
|
while( strFilePart && *strFilePart != '\0' )
|
|
{
|
|
swprintf_s( strFullFileName, MAX_PATH, L"%ls\\%ls", strFullPath, strLeafName );
|
|
if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF )
|
|
{
|
|
wcscpy_s( strSearchPath, cchSearch, strFullFileName );
|
|
return true;
|
|
}
|
|
|
|
swprintf_s( strSearch, MAX_PATH, L"%ls\\..", strFullPath );
|
|
if ( !GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart ) )
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Compiles HLSL shaders
|
|
//--------------------------------------------------------------------------------------
|
|
#if D3D_COMPILER_VERSION < 46
|
|
|
|
namespace
|
|
{
|
|
|
|
struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };
|
|
|
|
typedef public std::unique_ptr<void, handle_closer> ScopedHandle;
|
|
|
|
inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
|
|
|
|
class CIncludeHandler : public ID3DInclude
|
|
// Not as robust as D3D_COMPILE_STANDARD_FILE_INCLUDE, but it works in most cases
|
|
{
|
|
private:
|
|
static const unsigned int MAX_INCLUDES = 9;
|
|
|
|
struct sInclude
|
|
{
|
|
HANDLE hFile;
|
|
HANDLE hFileMap;
|
|
LARGE_INTEGER FileSize;
|
|
void *pMapData;
|
|
};
|
|
|
|
struct sInclude m_includeFiles[MAX_INCLUDES];
|
|
size_t m_nIncludes;
|
|
bool m_reset;
|
|
WCHAR m_workingPath[MAX_PATH];
|
|
|
|
public:
|
|
CIncludeHandler() : m_nIncludes(0), m_reset(false)
|
|
{
|
|
if ( !GetCurrentDirectoryW( MAX_PATH, m_workingPath ) )
|
|
*m_workingPath = 0;
|
|
|
|
for ( size_t i = 0; i < MAX_INCLUDES; ++i )
|
|
{
|
|
m_includeFiles[i].hFile = INVALID_HANDLE_VALUE;
|
|
m_includeFiles[i].hFileMap = INVALID_HANDLE_VALUE;
|
|
m_includeFiles[i].pMapData = nullptr;
|
|
}
|
|
}
|
|
virtual ~CIncludeHandler()
|
|
{
|
|
for ( size_t i = 0; i < m_nIncludes; ++i )
|
|
{
|
|
UnmapViewOfFile( m_includeFiles[i].pMapData );
|
|
|
|
if ( m_includeFiles[i].hFileMap != INVALID_HANDLE_VALUE)
|
|
CloseHandle( m_includeFiles[i].hFileMap );
|
|
|
|
if ( m_includeFiles[i].hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle( m_includeFiles[i].hFile );
|
|
}
|
|
|
|
m_nIncludes = 0;
|
|
|
|
if ( m_reset && *m_workingPath )
|
|
{
|
|
SetCurrentDirectoryW( m_workingPath );
|
|
}
|
|
}
|
|
|
|
STDMETHOD(Open( D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes ) )
|
|
{
|
|
UNREFERENCED_PARAMETER(IncludeType);
|
|
UNREFERENCED_PARAMETER(pParentData);
|
|
|
|
size_t incIndex = m_nIncludes+1;
|
|
|
|
// Make sure we have enough room for this include file
|
|
if ( incIndex >= MAX_INCLUDES )
|
|
return E_FAIL;
|
|
|
|
// try to open the file
|
|
m_includeFiles[incIndex].hFile = CreateFileA( pFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr );
|
|
if( INVALID_HANDLE_VALUE == m_includeFiles[incIndex].hFile )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Get the file size
|
|
GetFileSizeEx( m_includeFiles[incIndex].hFile, &m_includeFiles[incIndex].FileSize );
|
|
|
|
// Use Memory Mapped File I/O for the header data
|
|
m_includeFiles[incIndex].hFileMap = CreateFileMappingA( m_includeFiles[incIndex].hFile, nullptr, PAGE_READONLY, m_includeFiles[incIndex].FileSize.HighPart, m_includeFiles[incIndex].FileSize.LowPart, pFileName);
|
|
if( !m_includeFiles[incIndex].hFileMap )
|
|
{
|
|
if (m_includeFiles[incIndex].hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle( m_includeFiles[incIndex].hFile );
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Create Map view
|
|
*ppData = MapViewOfFile( m_includeFiles[incIndex].hFileMap, FILE_MAP_READ, 0, 0, 0 );
|
|
*pBytes = m_includeFiles[incIndex].FileSize.LowPart;
|
|
|
|
// Success - Increment the include file count
|
|
m_nIncludes = incIndex;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(Close( LPCVOID pData ))
|
|
{
|
|
UNREFERENCED_PARAMETER(pData);
|
|
// Defer Closure until the container destructor
|
|
return S_OK;
|
|
}
|
|
|
|
void SetCWD( LPCWSTR pFileName )
|
|
{
|
|
WCHAR filePath[MAX_PATH];
|
|
wcscpy_s( filePath, MAX_PATH, pFileName );
|
|
|
|
WCHAR *strLastSlash = wcsrchr( filePath, L'\\' );
|
|
if( strLastSlash )
|
|
{
|
|
// Chop the exe name from the exe path
|
|
*strLastSlash = 0;
|
|
m_reset = true;
|
|
SetCurrentDirectoryW( filePath );
|
|
}
|
|
}
|
|
};
|
|
|
|
}; // namespace
|
|
|
|
#endif
|
|
|
|
_Use_decl_annotations_
|
|
HRESULT WINAPI DXUTCompileFromFile( LPCWSTR pFileName,
|
|
const D3D_SHADER_MACRO* pDefines,
|
|
LPCSTR pEntrypoint, LPCSTR pTarget,
|
|
UINT Flags1, UINT Flags2,
|
|
ID3DBlob** ppCode )
|
|
{
|
|
HRESULT hr;
|
|
WCHAR str[MAX_PATH];
|
|
V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, pFileName ) );
|
|
|
|
#if defined( DEBUG ) || defined( _DEBUG )
|
|
// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
|
|
// Setting this flag improves the shader debugging experience, but still allows
|
|
// the shaders to be optimized and to run exactly the way they will run in
|
|
// the release configuration of this program.
|
|
Flags1 |= D3DCOMPILE_DEBUG;
|
|
#endif
|
|
|
|
ID3DBlob* pErrorBlob = nullptr;
|
|
|
|
#if D3D_COMPILER_VERSION >= 46
|
|
|
|
hr = D3DCompileFromFile( str, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
|
pEntrypoint, pTarget, Flags1, Flags2,
|
|
ppCode, &pErrorBlob );
|
|
|
|
#else
|
|
|
|
ScopedHandle hFile( safe_handle( CreateFileW( str, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ) ) );
|
|
|
|
if ( !hFile )
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
|
|
LARGE_INTEGER FileSize = { 0 };
|
|
|
|
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
|
FILE_STANDARD_INFO fileInfo;
|
|
if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) )
|
|
{
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
FileSize = fileInfo.EndOfFile;
|
|
#else
|
|
GetFileSizeEx( hFile.get(), &FileSize );
|
|
#endif
|
|
|
|
if (!FileSize.LowPart || FileSize.HighPart > 0)
|
|
return E_FAIL;
|
|
|
|
std::unique_ptr<char[]> fxData;
|
|
fxData.reset( new (std::nothrow) char[ FileSize.LowPart ] );
|
|
if ( !fxData )
|
|
return E_OUTOFMEMORY;
|
|
|
|
DWORD BytesRead = 0;
|
|
if ( !ReadFile( hFile.get(), fxData.get(), FileSize.LowPart, &BytesRead, nullptr ) )
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
|
|
if (BytesRead < FileSize.LowPart)
|
|
return E_FAIL;
|
|
|
|
char pSrcName[MAX_PATH];
|
|
int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, str, -1, pSrcName, MAX_PATH, nullptr, FALSE );
|
|
if ( !result )
|
|
return E_FAIL;
|
|
|
|
const CHAR* pstrName = strrchr( pSrcName, '\\' );
|
|
if (!pstrName)
|
|
{
|
|
pstrName = pSrcName;
|
|
}
|
|
else
|
|
{
|
|
pstrName++;
|
|
}
|
|
|
|
std::unique_ptr<CIncludeHandler> includes( new (std::nothrow) CIncludeHandler );
|
|
if ( !includes )
|
|
return E_OUTOFMEMORY;
|
|
|
|
includes->SetCWD( str );
|
|
|
|
hr = D3DCompile( fxData.get(), BytesRead, pstrName, pDefines, includes.get(),
|
|
pEntrypoint, pTarget, Flags1, Flags2,
|
|
ppCode, &pErrorBlob );
|
|
|
|
#endif
|
|
|
|
#pragma warning( suppress : 6102 )
|
|
if ( pErrorBlob )
|
|
{
|
|
OutputDebugStringA( reinterpret_cast<const char*>( pErrorBlob->GetBufferPointer() ) );
|
|
pErrorBlob->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Texture utilities
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
_Use_decl_annotations_
|
|
HRESULT WINAPI DXUTCreateShaderResourceViewFromFile( ID3D11Device* d3dDevice, const wchar_t* szFileName, ID3D11ShaderResourceView** textureView )
|
|
{
|
|
if ( !d3dDevice || !szFileName || !textureView )
|
|
return E_INVALIDARG;
|
|
|
|
WCHAR str[MAX_PATH];
|
|
HRESULT hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, szFileName );
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
|
|
WCHAR ext[_MAX_EXT];
|
|
_wsplitpath_s( str, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT );
|
|
|
|
if ( _wcsicmp( ext, L".dds" ) == 0 )
|
|
{
|
|
hr = DirectX::CreateDDSTextureFromFile( d3dDevice, str, nullptr, textureView );
|
|
}
|
|
else
|
|
{
|
|
hr = DirectX::CreateWICTextureFromFile( d3dDevice, nullptr, str, nullptr, textureView );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
HRESULT WINAPI DXUTCreateTextureFromFile( ID3D11Device* d3dDevice, const wchar_t* szFileName, ID3D11Resource** texture )
|
|
{
|
|
if ( !d3dDevice || !szFileName || !texture )
|
|
return E_INVALIDARG;
|
|
|
|
WCHAR str[MAX_PATH];
|
|
HRESULT hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, szFileName );
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
|
|
WCHAR ext[_MAX_EXT];
|
|
_wsplitpath_s( str, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT );
|
|
|
|
if ( _wcsicmp( ext, L".dds" ) == 0 )
|
|
{
|
|
hr = DirectX::CreateDDSTextureFromFile( d3dDevice, str, texture, nullptr );
|
|
}
|
|
else
|
|
{
|
|
hr = DirectX::CreateWICTextureFromFile( d3dDevice, nullptr, str, texture, nullptr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
HRESULT WINAPI DXUTSaveTextureToFile( ID3D11DeviceContext* pContext, ID3D11Resource* pSource, bool usedds, const wchar_t* szFileName )
|
|
{
|
|
if ( !pContext || !pSource || !szFileName )
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr;
|
|
|
|
if ( usedds )
|
|
{
|
|
hr = DirectX::SaveDDSTextureToFile( pContext, pSource, szFileName );
|
|
}
|
|
else
|
|
{
|
|
hr = DirectX::SaveWICTextureToFile( pContext, pSource, GUID_ContainerFormatBmp, szFileName );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Desc: Returns a view matrix for rendering to a face of a cubemap.
|
|
//--------------------------------------------------------------------------------------
|
|
XMMATRIX WINAPI DXUTGetCubeMapViewMatrix( _In_ DWORD dwFace )
|
|
{
|
|
static const XMVECTORF32 s_vLookDir[] =
|
|
{
|
|
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
|
{ -1.0f, 0.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
|
{ 0.0f, -1.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
|
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
};
|
|
|
|
static const XMVECTORF32 s_vUpDir[] =
|
|
{
|
|
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
|
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
|
};
|
|
|
|
static_assert( _countof(s_vLookDir) == _countof(s_vUpDir), "arrays mismatch" );
|
|
|
|
if ( dwFace >= _countof(s_vLookDir)
|
|
|| dwFace >= _countof(s_vUpDir) )
|
|
return XMMatrixIdentity();
|
|
|
|
// Set the view transform for this cubemap surface
|
|
return XMMatrixLookAtLH( g_XMZero, s_vLookDir[ dwFace ], s_vUpDir[ dwFace ] );
|
|
}
|
|
|
|
|
|
//======================================================================================
|
|
// CDXUTResourceCache
|
|
//======================================================================================
|
|
|
|
CDXUTResourceCache::~CDXUTResourceCache()
|
|
{
|
|
OnDestroyDevice();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTResourceCache::CreateTextureFromFile( ID3D11Device* pDevice, ID3D11DeviceContext *pContext, LPCWSTR pSrcFile,
|
|
ID3D11ShaderResourceView** ppOutputRV, bool bSRGB )
|
|
{
|
|
if ( !ppOutputRV )
|
|
return E_INVALIDARG;
|
|
|
|
*ppOutputRV = nullptr;
|
|
|
|
for( auto it = m_TextureCache.cbegin(); it != m_TextureCache.cend(); ++it )
|
|
{
|
|
if( !wcscmp( it->wszSource, pSrcFile )
|
|
&& it->bSRGB == bSRGB
|
|
&& it->pSRV11 )
|
|
{
|
|
it->pSRV11->AddRef();
|
|
*ppOutputRV = it->pSRV11;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
WCHAR ext[_MAX_EXT];
|
|
_wsplitpath_s( pSrcFile, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT );
|
|
|
|
HRESULT hr;
|
|
if ( _wcsicmp( ext, L".dds" ) == 0 )
|
|
{
|
|
hr = DirectX::CreateDDSTextureFromFileEx( pDevice, pSrcFile, 0,
|
|
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, bSRGB,
|
|
nullptr, ppOutputRV, nullptr );
|
|
}
|
|
else
|
|
{
|
|
hr = DirectX::CreateWICTextureFromFileEx( pDevice, pContext, pSrcFile, 0,
|
|
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, bSRGB,
|
|
nullptr, ppOutputRV );
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
|
|
DXUTCache_Texture entry;
|
|
wcscpy_s( entry.wszSource, MAX_PATH, pSrcFile );
|
|
entry.bSRGB = bSRGB;
|
|
entry.pSRV11 = *ppOutputRV;
|
|
entry.pSRV11->AddRef();
|
|
m_TextureCache.push_back( entry );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTResourceCache::CreateTextureFromFile( ID3D11Device* pDevice, ID3D11DeviceContext *pContext, LPCSTR pSrcFile,
|
|
ID3D11ShaderResourceView** ppOutputRV, bool bSRGB )
|
|
{
|
|
WCHAR szSrcFile[MAX_PATH];
|
|
MultiByteToWideChar( CP_ACP, 0, pSrcFile, -1, szSrcFile, MAX_PATH );
|
|
szSrcFile[MAX_PATH - 1] = 0;
|
|
|
|
return CreateTextureFromFile( pDevice, pContext, szSrcFile, ppOutputRV, bSRGB );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Device event callbacks
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT CDXUTResourceCache::OnDestroyDevice()
|
|
{
|
|
// Release all resources
|
|
for( size_t j = 0; j < m_TextureCache.size(); ++j )
|
|
{
|
|
SAFE_RELEASE( m_TextureCache[ j ].pSRV11 );
|
|
}
|
|
m_TextureCache.clear();
|
|
m_TextureCache.shrink_to_fit();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//======================================================================================
|
|
// CDXUTTextHelper
|
|
//======================================================================================
|
|
|
|
_Use_decl_annotations_
|
|
CDXUTTextHelper::CDXUTTextHelper( ID3D11Device* pd3d11Device, ID3D11DeviceContext* pd3d11DeviceContext, CDXUTDialogResourceManager* pManager, int nLineHeight )
|
|
{
|
|
Init( nLineHeight );
|
|
m_pd3d11Device = pd3d11Device;
|
|
m_pd3d11DeviceContext = pd3d11DeviceContext;
|
|
m_pManager = pManager;
|
|
}
|
|
|
|
CDXUTTextHelper::~CDXUTTextHelper()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
void CDXUTTextHelper::Init( _In_ int nLineHeight )
|
|
{
|
|
m_clr = XMFLOAT4( 1, 1, 1, 1 );
|
|
m_pt.x = 0;
|
|
m_pt.y = 0;
|
|
m_nLineHeight = nLineHeight;
|
|
m_pd3d11Device = nullptr;
|
|
m_pd3d11DeviceContext = nullptr;
|
|
m_pManager = nullptr;
|
|
|
|
// Create a blend state if a sprite is passed in
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT CDXUTTextHelper::DrawFormattedTextLine( _In_z_ const WCHAR* strMsg, ... )
|
|
{
|
|
WCHAR strBuffer[512];
|
|
|
|
va_list args;
|
|
va_start( args, strMsg );
|
|
vswprintf_s( strBuffer, 512, strMsg, args );
|
|
strBuffer[511] = L'\0';
|
|
va_end( args );
|
|
|
|
return DrawTextLine( strBuffer );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT CDXUTTextHelper::DrawTextLine( _In_z_ const WCHAR* strMsg )
|
|
{
|
|
if( !m_pd3d11DeviceContext )
|
|
return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG );
|
|
|
|
HRESULT hr = S_OK;
|
|
RECT rc;
|
|
SetRect( &rc, m_pt.x, m_pt.y, 0, 0 );
|
|
DrawText11DXUT( m_pd3d11Device, m_pd3d11DeviceContext, strMsg, rc, m_clr,
|
|
(float)m_pManager->m_nBackBufferWidth, (float)m_pManager->m_nBackBufferHeight, false );
|
|
|
|
if( FAILED( hr ) )
|
|
return DXTRACE_ERR_MSGBOX( L"DrawText", hr );
|
|
|
|
m_pt.y += m_nLineHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTTextHelper::DrawFormattedTextLine( const RECT& rc, const WCHAR* strMsg, ... )
|
|
{
|
|
WCHAR strBuffer[512];
|
|
|
|
va_list args;
|
|
va_start( args, strMsg );
|
|
vswprintf_s( strBuffer, 512, strMsg, args );
|
|
strBuffer[511] = L'\0';
|
|
va_end( args );
|
|
|
|
return DrawTextLine( rc, strBuffer );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CDXUTTextHelper::DrawTextLine( const RECT& rc, const WCHAR* strMsg )
|
|
{
|
|
if( !m_pd3d11DeviceContext )
|
|
return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG );
|
|
|
|
HRESULT hr = S_OK;
|
|
DrawText11DXUT( m_pd3d11Device, m_pd3d11DeviceContext, strMsg, rc, m_clr,
|
|
(float)m_pManager->m_nBackBufferWidth, (float)m_pManager->m_nBackBufferHeight, false );
|
|
|
|
if( FAILED( hr ) )
|
|
return DXTRACE_ERR_MSGBOX( L"DrawText", hr );
|
|
|
|
m_pt.y += m_nLineHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
void CDXUTTextHelper::Begin()
|
|
{
|
|
if( m_pd3d11DeviceContext )
|
|
{
|
|
m_pManager->StoreD3D11State( m_pd3d11DeviceContext );
|
|
m_pManager->ApplyRenderUI11( m_pd3d11DeviceContext );
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
void CDXUTTextHelper::End()
|
|
{
|
|
if( m_pd3d11DeviceContext )
|
|
{
|
|
m_pManager->RestoreD3D11State( m_pd3d11DeviceContext );
|
|
}
|
|
}
|