1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2014 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 #include "OgreD3D11Device.h" 29 #include "OgreException.h" 30 31 namespace Ogre 32 { 33 //--------------------------------------------------------------------- 34 D3D11Device::eExceptionsErrorLevel D3D11Device::mExceptionsErrorLevel = D3D11Device::D3D_NO_EXCEPTION; 35 //--------------------------------------------------------------------- D3D11Device()36 D3D11Device::D3D11Device() 37 { 38 mDriverVersion.QuadPart = 0; 39 } 40 //--------------------------------------------------------------------- ~D3D11Device()41 D3D11Device::~D3D11Device() 42 { 43 ReleaseAll(); 44 } 45 //--------------------------------------------------------------------- ReleaseAll()46 void D3D11Device::ReleaseAll() 47 { 48 // Clear state 49 if (mImmediateContext) 50 { 51 mImmediateContext->Flush(); 52 mImmediateContext->ClearState(); 53 } 54 #if OGRE_D3D11_PROFILING 55 mPerf.Reset(); 56 #endif 57 mInfoQueue.Reset(); 58 mClassLinkage.Reset(); 59 mImmediateContext.Reset(); 60 mD3D11Device.Reset(); 61 mDXGIFactory.Reset(); 62 mDriverVersion.QuadPart = 0; 63 } 64 //--------------------------------------------------------------------- TransferOwnership(ID3D11DeviceN * d3d11device)65 void D3D11Device::TransferOwnership(ID3D11DeviceN* d3d11device) 66 { 67 assert(mD3D11Device.Get() != d3d11device); 68 ReleaseAll(); 69 70 if (d3d11device) 71 { 72 HRESULT hr = S_OK; 73 74 mD3D11Device.Attach(d3d11device); 75 76 // get DXGI factory from device 77 ComPtr<IDXGIDeviceN> pDXGIDevice; 78 ComPtr<IDXGIAdapterN> pDXGIAdapter; 79 if(SUCCEEDED(mD3D11Device.As(&pDXGIDevice)) 80 && SUCCEEDED(pDXGIDevice->GetParent(__uuidof(IDXGIAdapterN), (void **)pDXGIAdapter.GetAddressOf()))) 81 { 82 pDXGIAdapter->GetParent(__uuidof(IDXGIFactoryN), (void **)mDXGIFactory.ReleaseAndGetAddressOf()); 83 84 // We intentionally check for ID3D10Device support instead of ID3D11Device as CheckInterfaceSupport() is not supported for later. 85 // We hope, that there would be one UMD for both D3D10 and D3D11, or two different but with the same version number, 86 // or with different but correlated version numbers, so that blacklisting could be done with high confidence level. 87 if(FAILED(pDXGIAdapter->CheckInterfaceSupport(IID_ID3D10Device /* intentionally D3D10, not D3D11 */, &mDriverVersion))) 88 mDriverVersion.QuadPart = 0; 89 } 90 91 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 92 mD3D11Device->GetImmediateContext(mImmediateContext.ReleaseAndGetAddressOf()); 93 #elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT 94 mD3D11Device->GetImmediateContext1(mImmediateContext.ReleaseAndGetAddressOf()); 95 #endif 96 97 #if OGRE_D3D11_PROFILING 98 hr = mImmediateContext.As(&mPerf); 99 if(FAILED(hr) || !mPerf->GetStatus()) 100 mPerf.Reset(); 101 #endif 102 103 hr = mD3D11Device.As(&mInfoQueue); 104 if (SUCCEEDED(hr)) 105 { 106 mInfoQueue->ClearStoredMessages(); 107 mInfoQueue->ClearRetrievalFilter(); 108 mInfoQueue->ClearStorageFilter(); 109 110 D3D11_INFO_QUEUE_FILTER filter; 111 ZeroMemory(&filter, sizeof(D3D11_INFO_QUEUE_FILTER)); 112 std::vector<D3D11_MESSAGE_SEVERITY> severityList; 113 114 switch(mExceptionsErrorLevel) 115 { 116 case D3D_NO_EXCEPTION: 117 severityList.push_back(D3D11_MESSAGE_SEVERITY_CORRUPTION); 118 case D3D_CORRUPTION: 119 severityList.push_back(D3D11_MESSAGE_SEVERITY_ERROR); 120 case D3D_ERROR: 121 severityList.push_back(D3D11_MESSAGE_SEVERITY_WARNING); 122 case D3D_WARNING: 123 case D3D_INFO: 124 severityList.push_back(D3D11_MESSAGE_SEVERITY_INFO); 125 default: 126 break; 127 } 128 129 130 if (severityList.size() > 0) 131 { 132 filter.DenyList.NumSeverities = severityList.size(); 133 filter.DenyList.pSeverityList = &severityList[0]; 134 } 135 136 mInfoQueue->AddStorageFilterEntries(&filter); 137 mInfoQueue->AddRetrievalFilterEntries(&filter); 138 } 139 140 // If feature level is 11, create class linkage 141 if (mD3D11Device->GetFeatureLevel() == D3D_FEATURE_LEVEL_11_0) 142 { 143 hr = mD3D11Device->CreateClassLinkage(mClassLinkage.ReleaseAndGetAddressOf()); 144 } 145 } 146 } 147 //--------------------------------------------------------------------- throwIfFailed(HRESULT hr,const char * desc,const char * src)148 void D3D11Device::throwIfFailed(HRESULT hr, const char* desc, const char* src) 149 { 150 if(FAILED(hr) || isError()) 151 { 152 String description = std::string(desc).append("\nError Description:").append(getErrorDescription(hr)); 153 OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr, description, src); 154 } 155 } 156 //--------------------------------------------------------------------- getErrorDescription(const HRESULT lastResult) const157 String D3D11Device::getErrorDescription(const HRESULT lastResult /* = NO_ERROR */) const 158 { 159 if (!mD3D11Device) 160 { 161 return "NULL device"; 162 } 163 164 if (D3D_NO_EXCEPTION == mExceptionsErrorLevel) 165 { 166 return "infoQ exceptions are turned off"; 167 } 168 169 String res; 170 171 switch (lastResult) 172 { 173 case NO_ERROR: 174 break; 175 case E_INVALIDARG: 176 res.append("invalid parameters were passed.\n"); 177 break; 178 default: 179 res = StringUtil::format("hr = 0x%08X\n", lastResult); 180 } 181 182 if (mInfoQueue) 183 { 184 UINT64 numStoredMessages = mInfoQueue->GetNumStoredMessages(); 185 for (UINT64 i = 0 ; i < numStoredMessages ; i++ ) 186 { 187 // Get the size of the message 188 SIZE_T messageLength = 0; 189 mInfoQueue->GetMessage(i, NULL, &messageLength); 190 // Allocate space and get the message 191 D3D11_MESSAGE * pMessage = (D3D11_MESSAGE*)malloc(messageLength); 192 mInfoQueue->GetMessage(i, pMessage, &messageLength); 193 res = res + pMessage->pDescription + "\n"; 194 free(pMessage); 195 } 196 } 197 198 return res; 199 } 200 //--------------------------------------------------------------------- _getErrorsFromQueue() const201 bool D3D11Device::_getErrorsFromQueue() const 202 { 203 if (mInfoQueue) 204 { 205 UINT64 numStoredMessages = mInfoQueue->GetNumStoredMessages(); 206 207 if (D3D_INFO == mExceptionsErrorLevel && numStoredMessages > 0) 208 { 209 // if D3D_INFO we don't need to loop if the numStoredMessages > 0 210 return true; 211 } 212 for (UINT64 i = 0 ; i < numStoredMessages ; i++ ) 213 { 214 // Get the size of the message 215 SIZE_T messageLength = 0; 216 mInfoQueue->GetMessage(i, NULL, &messageLength); 217 // Allocate space and get the message 218 D3D11_MESSAGE * pMessage = (D3D11_MESSAGE*)malloc(messageLength); 219 mInfoQueue->GetMessage(i, pMessage, &messageLength); 220 221 bool res = false; 222 switch(pMessage->Severity) 223 { 224 case D3D11_MESSAGE_SEVERITY_CORRUPTION: 225 if (D3D_CORRUPTION == mExceptionsErrorLevel) 226 { 227 res = true; 228 } 229 break; 230 case D3D11_MESSAGE_SEVERITY_ERROR: 231 switch(mExceptionsErrorLevel) 232 { 233 case D3D_INFO: 234 case D3D_WARNING: 235 case D3D_ERROR: 236 res = true; 237 } 238 break; 239 case D3D11_MESSAGE_SEVERITY_WARNING: 240 switch(mExceptionsErrorLevel) 241 { 242 case D3D_INFO: 243 case D3D_WARNING: 244 res = true; 245 } 246 break; 247 } 248 249 free(pMessage); 250 if (res) 251 { 252 // we don't need to loop anymore... 253 return true; 254 } 255 256 } 257 258 clearStoredErrorMessages(); 259 260 return false; 261 262 } 263 else 264 { 265 return false; 266 } 267 } 268 //--------------------------------------------------------------------- clearStoredErrorMessages() const269 void D3D11Device::clearStoredErrorMessages() const 270 { 271 if (mD3D11Device && D3D_NO_EXCEPTION != mExceptionsErrorLevel) 272 { 273 if (mInfoQueue) 274 { 275 mInfoQueue->ClearStoredMessages(); 276 } 277 } 278 } 279 //--------------------------------------------------------------------- getExceptionsErrorLevel()280 const D3D11Device::eExceptionsErrorLevel D3D11Device::getExceptionsErrorLevel() 281 { 282 return mExceptionsErrorLevel; 283 } 284 //--------------------------------------------------------------------- setExceptionsErrorLevel(const eExceptionsErrorLevel exceptionsErrorLevel)285 void D3D11Device::setExceptionsErrorLevel( const eExceptionsErrorLevel exceptionsErrorLevel ) 286 { 287 mExceptionsErrorLevel = exceptionsErrorLevel; 288 } 289 //--------------------------------------------------------------------- setExceptionsErrorLevel(const Ogre::String & exceptionsErrorLevel)290 void D3D11Device::setExceptionsErrorLevel( const Ogre::String& exceptionsErrorLevel ) 291 { 292 eExceptionsErrorLevel onlyIfDebugMode = OGRE_DEBUG_MODE ? D3D11Device::D3D_ERROR : D3D11Device::D3D_NO_EXCEPTION; 293 if("No information queue exceptions" == exceptionsErrorLevel) setExceptionsErrorLevel(onlyIfDebugMode); 294 else if("Corruption" == exceptionsErrorLevel) setExceptionsErrorLevel(D3D11Device::D3D_CORRUPTION); 295 else if("Error" == exceptionsErrorLevel) setExceptionsErrorLevel(D3D11Device::D3D_ERROR); 296 else if("Warning" == exceptionsErrorLevel) setExceptionsErrorLevel(D3D11Device::D3D_WARNING); 297 else if("Info (exception on any message)" == exceptionsErrorLevel) setExceptionsErrorLevel(D3D11Device::D3D_INFO); 298 else setExceptionsErrorLevel(onlyIfDebugMode); 299 } 300 //--------------------------------------------------------------------- parseFeatureLevel(const Ogre::String & value,D3D_FEATURE_LEVEL fallback)301 D3D_FEATURE_LEVEL D3D11Device::parseFeatureLevel(const Ogre::String& value, D3D_FEATURE_LEVEL fallback) 302 { 303 if(value == "9.1") return D3D_FEATURE_LEVEL_9_1; 304 if(value == "9.2") return D3D_FEATURE_LEVEL_9_2; 305 if(value == "9.3") return D3D_FEATURE_LEVEL_9_3; 306 if(value == "10.0") return D3D_FEATURE_LEVEL_10_0; 307 if(value == "10.1") return D3D_FEATURE_LEVEL_10_1; 308 if(value == "11.0") return D3D_FEATURE_LEVEL_11_0; 309 return fallback; 310 } 311 //--------------------------------------------------------------------- parseDriverType(const Ogre::String & driverTypeName,D3D_DRIVER_TYPE fallback)312 D3D_DRIVER_TYPE D3D11Device::parseDriverType(const Ogre::String& driverTypeName, D3D_DRIVER_TYPE fallback) 313 { 314 if("Hardware" == driverTypeName) return D3D_DRIVER_TYPE_HARDWARE; 315 if("Software" == driverTypeName) return D3D_DRIVER_TYPE_SOFTWARE; 316 if("Warp" == driverTypeName) return D3D_DRIVER_TYPE_WARP; 317 return fallback; 318 } 319 //--------------------------------------------------------------------- IsDeviceLost()320 bool D3D11Device::IsDeviceLost() 321 { 322 HRESULT hr = mD3D11Device->GetDeviceRemovedReason(); 323 if(FAILED(hr)) 324 return true; 325 return false; 326 } 327 }