//-------------------------------------------------------------------------------------- // 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 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 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 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( 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 ); } }