gfxD3D11Device.cpp
Engine/source/gfx/D3D11/gfxD3D11Device.cpp
Classes:
Public Variables
sgCommandLine (sgPCD3D11DeviceHandleCommandLine)
Public Functions
sgPCD3D11DeviceHandleCommandLine(S32 argc, const char ** argv)
Parse command line arguments for window creation.
Detailed Description
Public Variables
GFXPCD3D11RegisterDevice pPCD3D11RegisterDevice
ProcessRegisterCommandLine sgCommandLine (sgPCD3D11DeviceHandleCommandLine)
Public Functions
sgPCD3D11DeviceHandleCommandLine(S32 argc, const char ** argv)
Parse command line arguments for window creation.
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2015 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "console/console.h" 25#include "core/stream/fileStream.h" 26#include "core/strings/unicode.h" 27#include "core/util/journal/process.h" 28#include "gfx/D3D11/gfxD3D11Device.h" 29#include "gfx/D3D11/gfxD3D11CardProfiler.h" 30#include "gfx/D3D11/gfxD3D11VertexBuffer.h" 31#include "gfx/D3D11/gfxD3D11EnumTranslate.h" 32#include "gfx/D3D11/gfxD3D11QueryFence.h" 33#include "gfx/D3D11/gfxD3D11OcclusionQuery.h" 34#include "gfx/D3D11/gfxD3D11Shader.h" 35#include "gfx/D3D11/gfxD3D11Target.h" 36#include "platformWin32/platformWin32.h" 37#include "windowManager/win32/win32Window.h" 38#include "windowManager/platformWindow.h" 39#include "gfx/D3D11/screenshotD3D11.h" 40#include "materials/shaderData.h" 41 42#ifdef TORQUE_DEBUG 43#include "d3d11sdklayers.h" 44#endif 45 46#pragma comment(lib, "dxgi.lib") 47#pragma comment(lib, "d3d11.lib") 48 49GFXAdapter::CreateDeviceInstanceDelegate GFXD3D11Device::mCreateDeviceInstance(GFXD3D11Device::createInstance); 50 51GFXDevice *GFXD3D11Device::createInstance(U32 adapterIndex) 52{ 53 GFXD3D11Device* dev = new GFXD3D11Device(adapterIndex); 54 return dev; 55} 56 57GFXFormat GFXD3D11Device::selectSupportedFormat(GFXTextureProfile *profile, const Vector<GFXFormat> &formats, bool texture, bool mustblend, bool mustfilter) 58{ 59 U32 features = 0; 60 if(texture) 61 features |= D3D11_FORMAT_SUPPORT_TEXTURE2D; 62 if(mustblend) 63 features |= D3D11_FORMAT_SUPPORT_BLENDABLE; 64 if(mustfilter) 65 features |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; 66 67 for(U32 i = 0; i < formats.size(); i++) 68 { 69 if(GFXD3D11TextureFormat[formats[i]] == DXGI_FORMAT_UNKNOWN) 70 continue; 71 72 U32 supportFlag = 0; 73 mD3DDevice->CheckFormatSupport(GFXD3D11TextureFormat[formats[i]],&supportFlag); 74 if(supportFlag & features) 75 return formats[i]; 76 } 77 78 return GFXFormatR8G8B8A8; 79} 80 81DXGI_SWAP_CHAIN_DESC GFXD3D11Device::setupPresentParams(const GFXVideoMode &mode, const HWND &hwnd) 82{ 83 DXGI_SWAP_CHAIN_DESC d3dpp; 84 ZeroMemory(&d3dpp, sizeof(d3dpp)); 85 86 DXGI_SAMPLE_DESC sampleDesc; 87 sampleDesc.Count = 1; 88 sampleDesc.Quality = 0; 89 90 mMultisampleDesc = sampleDesc; 91 92 d3dpp.BufferCount = !smDisableVSync ? 2 : 1; // triple buffering when vsync is on. 93 d3dpp.BufferDesc.Width = mode.resolution.x; 94 d3dpp.BufferDesc.Height = mode.resolution.y; 95 d3dpp.BufferDesc.Format = GFXD3D11TextureFormat[GFXFormatR8G8B8A8]; 96 d3dpp.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 97 d3dpp.OutputWindow = hwnd; 98 d3dpp.SampleDesc = sampleDesc; 99 d3dpp.Windowed = !mode.fullScreen; 100 d3dpp.BufferDesc.RefreshRate.Numerator = mode.refreshRate; 101 d3dpp.BufferDesc.RefreshRate.Denominator = 1; 102 d3dpp.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 103 104 if (mode.fullScreen) 105 { 106 d3dpp.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 107 d3dpp.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 108 d3dpp.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 109 } 110 111 return d3dpp; 112} 113 114void GFXD3D11Device::enumerateAdapters(Vector<GFXAdapter*> &adapterList) 115{ 116 IDXGIAdapter1* EnumAdapter; 117 IDXGIFactory1* DXGIFactory; 118 119 CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&DXGIFactory)); 120 121 for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) 122 { 123 GFXAdapter *toAdd = new GFXAdapter; 124 toAdd->mType = Direct3D11; 125 toAdd->mIndex = adapterIndex; 126 toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance; 127 128 toAdd->mShaderModel = 5.0f; 129 DXGI_ADAPTER_DESC1 desc; 130 EnumAdapter->GetDesc1(&desc); 131 132 // LUID identifies adapter for oculus rift 133 dMemcpy(&toAdd->mLUID, &desc.AdapterLuid, sizeof(toAdd->mLUID)); 134 135 size_t size=wcslen(desc.Description); 136 char *str = new char[size+1]; 137 138 wcstombs(str, desc.Description,size); 139 str[size]='\0'; 140 String Description=str; 141 SAFE_DELETE_ARRAY(str); 142 143 dStrncpy(toAdd->mName, Description.c_str(), GFXAdapter::MaxAdapterNameLen); 144 dStrncat(toAdd->mName, " (D3D11)", GFXAdapter::MaxAdapterNameLen); 145 146 IDXGIOutput* pOutput = NULL; 147 HRESULT hr; 148 149 hr = EnumAdapter->EnumOutputs(adapterIndex, &pOutput); 150 151 if(hr == DXGI_ERROR_NOT_FOUND) 152 { 153 SAFE_RELEASE(EnumAdapter); 154 break; 155 } 156 157 if(FAILED(hr)) 158 AssertFatal(false, "GFXD3D11Device::enumerateAdapters -> EnumOutputs call failure"); 159 160 UINT numModes = 0; 161 DXGI_MODE_DESC* displayModes = NULL; 162 DXGI_FORMAT format = DXGI_FORMAT_B8G8R8A8_UNORM; 163 164 // Get the number of elements 165 hr = pOutput->GetDisplayModeList(format, 0, &numModes, NULL); 166 167 if(FAILED(hr)) 168 AssertFatal(false, "GFXD3D11Device::enumerateAdapters -> GetDisplayModeList call failure"); 169 170 displayModes = new DXGI_MODE_DESC[numModes]; 171 172 // Get the list 173 hr = pOutput->GetDisplayModeList(format, 0, &numModes, displayModes); 174 175 if(FAILED(hr)) 176 AssertFatal(false, "GFXD3D11Device::enumerateAdapters -> GetDisplayModeList call failure"); 177 178 for(U32 numMode = 0; numMode < numModes; ++numMode) 179 { 180 GFXVideoMode vmAdd; 181 182 vmAdd.fullScreen = true; 183 vmAdd.bitDepth = 32; 184 vmAdd.refreshRate = displayModes[numMode].RefreshRate.Numerator / displayModes[numMode].RefreshRate.Denominator; 185 vmAdd.resolution.x = displayModes[numMode].Width; 186 vmAdd.resolution.y = displayModes[numMode].Height; 187 toAdd->mAvailableModes.push_back(vmAdd); 188 } 189 190 delete[] displayModes; 191 SAFE_RELEASE(pOutput); 192 SAFE_RELEASE(EnumAdapter); 193 adapterList.push_back(toAdd); 194 } 195 196 SAFE_RELEASE(DXGIFactory); 197} 198 199void GFXD3D11Device::enumerateVideoModes() 200{ 201 mVideoModes.clear(); 202 203 IDXGIAdapter1* EnumAdapter; 204 IDXGIFactory1* DXGIFactory; 205 HRESULT hr; 206 207 hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&DXGIFactory)); 208 209 if (FAILED(hr)) 210 AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> CreateDXGIFactory1 call failure"); 211 212 for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) 213 { 214 IDXGIOutput* pOutput = NULL; 215 216 hr = EnumAdapter->EnumOutputs(adapterIndex, &pOutput); 217 218 if(hr == DXGI_ERROR_NOT_FOUND) 219 { 220 SAFE_RELEASE(EnumAdapter); 221 break; 222 } 223 224 if(FAILED(hr)) 225 AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> EnumOutputs call failure"); 226 227 UINT numModes = 0; 228 DXGI_MODE_DESC* displayModes = NULL; 229 DXGI_FORMAT format = GFXD3D11TextureFormat[GFXFormatR8G8B8A8]; 230 231 // Get the number of elements 232 hr = pOutput->GetDisplayModeList(format, 0, &numModes, NULL); 233 234 if(FAILED(hr)) 235 AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> GetDisplayModeList call failure"); 236 237 displayModes = new DXGI_MODE_DESC[numModes]; 238 239 // Get the list 240 hr = pOutput->GetDisplayModeList(format, 0, &numModes, displayModes); 241 242 if(FAILED(hr)) 243 AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> GetDisplayModeList call failure"); 244 245 for(U32 numMode = 0; numMode < numModes; ++numMode) 246 { 247 GFXVideoMode toAdd; 248 249 toAdd.fullScreen = false; 250 toAdd.bitDepth = 32; 251 toAdd.refreshRate = displayModes[numMode].RefreshRate.Numerator / displayModes[numMode].RefreshRate.Denominator; 252 toAdd.resolution.x = displayModes[numMode].Width; 253 toAdd.resolution.y = displayModes[numMode].Height; 254 mVideoModes.push_back(toAdd); 255 } 256 257 delete[] displayModes; 258 SAFE_RELEASE(pOutput); 259 SAFE_RELEASE(EnumAdapter); 260 } 261 262 SAFE_RELEASE(DXGIFactory); 263} 264 265IDXGISwapChain* GFXD3D11Device::getSwapChain() 266{ 267 return mSwapChain; 268} 269 270void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) 271{ 272 AssertFatal(window, "GFXD3D11Device::init - must specify a window!"); 273 274 HWND winHwnd = (HWND)window->getSystemWindow( PlatformWindow::WindowSystem_Windows ); 275 276 UINT createDeviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT; 277#ifdef TORQUE_DEBUG 278 createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; 279 mDebugLayers = true; 280#endif 281 282 DXGI_SWAP_CHAIN_DESC d3dpp = setupPresentParams(mode, winHwnd); 283 284 D3D_FEATURE_LEVEL deviceFeature; 285 D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;// use D3D_DRIVER_TYPE_REFERENCE for reference device 286 // create a device, device context and swap chain using the information in the d3dpp struct 287 HRESULT hres = D3D11CreateDeviceAndSwapChain(NULL, 288 driverType, 289 NULL, 290 createDeviceFlags, 291 NULL, 292 0, 293 D3D11_SDK_VERSION, 294 &d3dpp, 295 &mSwapChain, 296 &mD3DDevice, 297 &deviceFeature, 298 &mD3DDeviceContext); 299 300 if(FAILED(hres)) 301 { 302 #ifdef TORQUE_DEBUG 303 //try again without debug device layer enabled 304 createDeviceFlags &= ~D3D11_CREATE_DEVICE_DEBUG; 305 HRESULT hres = D3D11CreateDeviceAndSwapChain(NULL, driverType,NULL,createDeviceFlags,NULL, 0, 306 D3D11_SDK_VERSION, 307 &d3dpp, 308 &mSwapChain, 309 &mD3DDevice, 310 &deviceFeature, 311 &mD3DDeviceContext); 312 //if we failed again than we definitely have a problem 313 if (FAILED(hres)) 314 AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!"); 315 316 Con::warnf("GFXD3D11Device::init - Debug layers not detected!"); 317 mDebugLayers = false; 318 #else 319 AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!"); 320 #endif 321 } 322 323 //set the fullscreen state here if we need to 324 if(mode.fullScreen) 325 { 326 hres = mSwapChain->SetFullscreenState(TRUE, NULL); 327 if(FAILED(hres)) 328 { 329 AssertFatal(false, "GFXD3D11Device::init- Failed to set fullscreen state!"); 330 } 331 } 332 333 mTextureManager = new GFXD3D11TextureManager(); 334 335 // Now reacquire all the resources we trashed earlier 336 reacquireDefaultPoolResources(); 337 //TODO implement feature levels? 338 if (deviceFeature >= D3D_FEATURE_LEVEL_11_0) 339 mPixVersion = 5.0f; 340 else 341 AssertFatal(false, "GFXD3D11Device::init - We don't support anything below feature level 11."); 342 343 D3D11_QUERY_DESC queryDesc; 344 queryDesc.Query = D3D11_QUERY_OCCLUSION; 345 queryDesc.MiscFlags = 0; 346 347 ID3D11Query *testQuery = NULL; 348 349 // detect occlusion query support 350 if (SUCCEEDED(mD3DDevice->CreateQuery(&queryDesc, &testQuery))) mOcclusionQuerySupported = true; 351 352 SAFE_RELEASE(testQuery); 353 354 Con::printf("Hardware occlusion query detected: %s", mOcclusionQuerySupported ? "Yes" : "No"); 355 356 mCardProfiler = new GFXD3D11CardProfiler(); 357 mCardProfiler->init(); 358 359 D3D11_TEXTURE2D_DESC desc; 360 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; 361 desc.CPUAccessFlags = 0; 362 desc.Format = GFXD3D11TextureFormat[GFXFormatD24S8]; 363 desc.MipLevels = 1; 364 desc.ArraySize = 1; 365 desc.Usage = D3D11_USAGE_DEFAULT; 366 desc.Width = mode.resolution.x; 367 desc.Height = mode.resolution.y; 368 desc.SampleDesc.Count =1; 369 desc.SampleDesc.Quality =0; 370 desc.MiscFlags = 0; 371 372 HRESULT hr = mD3DDevice->CreateTexture2D(&desc, NULL, &mDeviceDepthStencil); 373 if(FAILED(hr)) 374 { 375 AssertFatal(false, "GFXD3D11Device::init - couldn't create device's depth-stencil surface."); 376 } 377 378 D3D11_DEPTH_STENCIL_VIEW_DESC depthDesc; 379 depthDesc.Format = GFXD3D11TextureFormat[GFXFormatD24S8]; 380 depthDesc.Flags =0 ; 381 depthDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 382 depthDesc.Texture2D.MipSlice = 0; 383 384 hr = mD3DDevice->CreateDepthStencilView(mDeviceDepthStencil, &depthDesc, &mDeviceDepthStencilView); 385 386 if(FAILED(hr)) 387 { 388 AssertFatal(false, "GFXD3D11Device::init - couldn't create depth stencil view"); 389 } 390 391 hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mDeviceBackbuffer); 392 if(FAILED(hr)) 393 AssertFatal(false, "GFXD3D11Device::init - coudln't retrieve backbuffer ref"); 394 395 //create back buffer view 396 D3D11_RENDER_TARGET_VIEW_DESC RTDesc; 397 398 RTDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 399 RTDesc.Texture2D.MipSlice = 0; 400 RTDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 401 402 hr = mD3DDevice->CreateRenderTargetView(mDeviceBackbuffer, &RTDesc, &mDeviceBackBufferView); 403 404 if(FAILED(hr)) 405 AssertFatal(false, "GFXD3D11Device::init - couldn't create back buffer target view"); 406 407#ifdef TORQUE_DEBUG 408 String backBufferName = "MainBackBuffer"; 409 String depthSteniclName = "MainDepthStencil"; 410 String backBuffViewName = "MainBackBuffView"; 411 String depthStencViewName = "MainDepthView"; 412 mDeviceBackbuffer->SetPrivateData(WKPDID_D3DDebugObjectName, backBufferName.size(), backBufferName.c_str()); 413 mDeviceDepthStencil->SetPrivateData(WKPDID_D3DDebugObjectName, depthSteniclName.size(), depthSteniclName.c_str()); 414 mDeviceDepthStencilView->SetPrivateData(WKPDID_D3DDebugObjectName, depthStencViewName.size(), depthStencViewName.c_str()); 415 mDeviceBackBufferView->SetPrivateData(WKPDID_D3DDebugObjectName, backBuffViewName.size(), backBuffViewName.c_str()); 416 417 _suppressDebugMessages(); 418 419#endif 420 421 gScreenShot = new ScreenShotD3D11; 422 423 mInitialized = true; 424 deviceInited(); 425} 426 427// Supress any debug layer messages we don't want to see 428void GFXD3D11Device::_suppressDebugMessages() 429{ 430 if (mDebugLayers) 431 { 432 ID3D11Debug *pDebug = NULL; 433 if (SUCCEEDED(mD3DDevice->QueryInterface(__uuidof(ID3D11Debug), (void**)&pDebug))) 434 { 435 ID3D11InfoQueue *pInfoQueue = NULL; 436 if (SUCCEEDED(pDebug->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&pInfoQueue))) 437 { 438 //Disable breaking on error or corruption, this can be handy when using VS graphics debugging 439 pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, false); 440 pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, false); 441 442 D3D11_MESSAGE_ID hide[] = 443 { 444 //this is harmless and no need to spam the console 445 D3D11_MESSAGE_ID_QUERY_BEGIN_ABANDONING_PREVIOUS_RESULTS 446 }; 447 448 D3D11_INFO_QUEUE_FILTER filter; 449 memset(&filter, 0, sizeof(filter)); 450 filter.DenyList.NumIDs = _countof(hide); 451 filter.DenyList.pIDList = hide; 452 pInfoQueue->AddStorageFilterEntries(&filter); 453 SAFE_RELEASE(pInfoQueue); 454 } 455 SAFE_RELEASE(pDebug); 456 } 457 } 458} 459 460bool GFXD3D11Device::beginSceneInternal() 461{ 462 mCanCurrentlyRender = true; 463 return mCanCurrentlyRender; 464} 465 466GFXWindowTarget * GFXD3D11Device::allocWindowTarget(PlatformWindow *window) 467{ 468 AssertFatal(window,"GFXD3D11Device::allocWindowTarget - no window provided!"); 469 470 // Allocate the device. 471 init(window->getVideoMode(), window); 472 473 // Set up a new window target... 474 GFXD3D11WindowTarget *gdwt = new GFXD3D11WindowTarget(); 475 gdwt->mWindow = window; 476 gdwt->mSize = window->getClientExtent(); 477 gdwt->initPresentationParams(); 478 gdwt->registerResourceWithDevice(this); 479 480 return gdwt; 481} 482 483GFXTextureTarget* GFXD3D11Device::allocRenderToTextureTarget() 484{ 485 GFXD3D11TextureTarget *targ = new GFXD3D11TextureTarget(); 486 targ->registerResourceWithDevice(this); 487 488 return targ; 489} 490 491void GFXD3D11Device::reset(DXGI_SWAP_CHAIN_DESC &d3dpp) 492{ 493 if (!mD3DDevice) 494 return; 495 496 mInitialized = false; 497 498 // Clean up some commonly dangling state. This helps prevents issues with 499 // items that are destroyed by the texture manager callbacks and recreated 500 // later, but still left bound. 501 setVertexBuffer(NULL); 502 setPrimitiveBuffer(NULL); 503 for (S32 i = 0; i<getNumSamplers(); i++) 504 setTexture(i, NULL); 505 506 mD3DDeviceContext->ClearState(); 507 508 DXGI_MODE_DESC displayModes; 509 displayModes.Format = d3dpp.BufferDesc.Format; 510 displayModes.Height = d3dpp.BufferDesc.Height; 511 displayModes.Width = d3dpp.BufferDesc.Width; 512 displayModes.RefreshRate = d3dpp.BufferDesc.RefreshRate; 513 displayModes.Scaling = d3dpp.BufferDesc.Scaling; 514 displayModes.ScanlineOrdering = d3dpp.BufferDesc.ScanlineOrdering; 515 516 HRESULT hr; 517 if (!d3dpp.Windowed) 518 { 519 hr = mSwapChain->ResizeTarget(&displayModes); 520 521 if (FAILED(hr)) 522 { 523 AssertFatal(false, "D3D11Device::reset - failed to resize target!"); 524 } 525 } 526 527 // First release all the stuff we allocated from D3DPOOL_DEFAULT 528 releaseDefaultPoolResources(); 529 530 //release the backbuffer, depthstencil, and their views 531 SAFE_RELEASE(mDeviceBackBufferView); 532 SAFE_RELEASE(mDeviceBackbuffer); 533 SAFE_RELEASE(mDeviceDepthStencilView); 534 SAFE_RELEASE(mDeviceDepthStencil); 535 536 hr = mSwapChain->ResizeBuffers(d3dpp.BufferCount, d3dpp.BufferDesc.Width, d3dpp.BufferDesc.Height, d3dpp.BufferDesc.Format, d3dpp.Windowed ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); 537 538 if (FAILED(hr)) 539 { 540 AssertFatal(false, "D3D11Device::reset - failed to resize back buffer!"); 541 } 542 543 //recreate backbuffer view. depth stencil view and texture 544 D3D11_TEXTURE2D_DESC desc; 545 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; 546 desc.CPUAccessFlags = 0; 547 desc.Format = GFXD3D11TextureFormat[GFXFormatD24S8]; 548 desc.MipLevels = 1; 549 desc.ArraySize = 1; 550 desc.Usage = D3D11_USAGE_DEFAULT; 551 desc.Width = d3dpp.BufferDesc.Width; 552 desc.Height = d3dpp.BufferDesc.Height; 553 desc.SampleDesc.Count = 1; 554 desc.SampleDesc.Quality = 0; 555 desc.MiscFlags = 0; 556 557 hr = mD3DDevice->CreateTexture2D(&desc, NULL, &mDeviceDepthStencil); 558 if (FAILED(hr)) 559 { 560 AssertFatal(false, "GFXD3D11Device::reset - couldn't create device's depth-stencil surface."); 561 } 562 563 D3D11_DEPTH_STENCIL_VIEW_DESC depthDesc; 564 depthDesc.Format = GFXD3D11TextureFormat[GFXFormatD24S8]; 565 depthDesc.Flags = 0; 566 depthDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 567 depthDesc.Texture2D.MipSlice = 0; 568 569 hr = mD3DDevice->CreateDepthStencilView(mDeviceDepthStencil, &depthDesc, &mDeviceDepthStencilView); 570 571 if (FAILED(hr)) 572 { 573 AssertFatal(false, "GFXD3D11Device::reset - couldn't create depth stencil view"); 574 } 575 576 hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mDeviceBackbuffer); 577 if (FAILED(hr)) 578 AssertFatal(false, "GFXD3D11Device::reset - coudln't retrieve backbuffer ref"); 579 580 //create back buffer view 581 D3D11_RENDER_TARGET_VIEW_DESC RTDesc; 582 583 RTDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 584 RTDesc.Texture2D.MipSlice = 0; 585 RTDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 586 587 hr = mD3DDevice->CreateRenderTargetView(mDeviceBackbuffer, &RTDesc, &mDeviceBackBufferView); 588 589 if (FAILED(hr)) 590 AssertFatal(false, "GFXD3D11Device::reset - couldn't create back buffer target view"); 591 592 mD3DDeviceContext->OMSetRenderTargets(1, &mDeviceBackBufferView, mDeviceDepthStencilView); 593 594 hr = mSwapChain->SetFullscreenState(!d3dpp.Windowed, NULL); 595 596 if (FAILED(hr)) 597 { 598 AssertFatal(false, "D3D11Device::reset - failed to change screen states!"); 599 } 600 601 //Microsoft recommend this, see DXGI documentation 602 if (!d3dpp.Windowed) 603 { 604 displayModes.RefreshRate.Numerator = 0; 605 displayModes.RefreshRate.Denominator = 0; 606 hr = mSwapChain->ResizeTarget(&displayModes); 607 608 if (FAILED(hr)) 609 { 610 AssertFatal(false, "D3D11Device::reset - failed to resize target!"); 611 } 612 } 613 614 mInitialized = true; 615 616 // Now re aquire all the resources we trashed earlier 617 reacquireDefaultPoolResources(); 618 619 // Mark everything dirty and flush to card, for sanity. 620 updateStates(true); 621} 622 623class GFXPCD3D11RegisterDevice 624{ 625public: 626 GFXPCD3D11RegisterDevice() 627 { 628 GFXInit::getRegisterDeviceSignal().notify(&GFXD3D11Device::enumerateAdapters); 629 } 630}; 631 632static GFXPCD3D11RegisterDevice pPCD3D11RegisterDevice; 633 634//----------------------------------------------------------------------------- 635/// Parse command line arguments for window creation 636//----------------------------------------------------------------------------- 637static void sgPCD3D11DeviceHandleCommandLine(S32 argc, const char **argv) 638{ 639 // useful to pass parameters by command line for d3d (e.g. -dx9 -dx11) 640 for (U32 i = 1; i < argc; i++) 641 { 642 argv[i]; 643 } 644} 645 646// Register the command line parsing hook 647static ProcessRegisterCommandLine sgCommandLine( sgPCD3D11DeviceHandleCommandLine ); 648 649GFXD3D11Device::GFXD3D11Device(U32 index) 650{ 651 mDeviceSwizzle32 = &Swizzles::bgra; 652 GFXVertexColor::setSwizzle( mDeviceSwizzle32 ); 653 654 mDeviceSwizzle24 = &Swizzles::bgr; 655 656 mAdapterIndex = index; 657 mD3DDevice = NULL; 658 mVolatileVB = NULL; 659 660 mCurrentPB = NULL; 661 mDynamicPB = NULL; 662 663 mLastVertShader = NULL; 664 mLastPixShader = NULL; 665 666 mCanCurrentlyRender = false; 667 mTextureManager = NULL; 668 mCurrentStateBlock = NULL; 669 mResourceListHead = NULL; 670 671 mPixVersion = 0.0; 672 673 mDrawInstancesCount = 0; 674 675 mCardProfiler = NULL; 676 677 mDeviceDepthStencil = NULL; 678 mDeviceBackbuffer = NULL; 679 mDeviceBackBufferView = NULL; 680 mDeviceDepthStencilView = NULL; 681 682 mCreateFenceType = -1; // Unknown, test on first allocate 683 684 mCurrentConstBuffer = NULL; 685 686 mOcclusionQuerySupported = false; 687 688 mDebugLayers = false; 689 690 for(U32 i = 0; i < GS_COUNT; ++i) 691 mModelViewProjSC[i] = NULL; 692 693 // Set up the Enum translation tables 694 GFXD3D11EnumTranslate::init(); 695} 696 697GFXD3D11Device::~GFXD3D11Device() 698{ 699 // Release our refcount on the current stateblock object 700 mCurrentStateBlock = NULL; 701 702 releaseDefaultPoolResources(); 703 704 mD3DDeviceContext->ClearState(); 705 mD3DDeviceContext->Flush(); 706 707 // Free the vertex declarations. 708 VertexDeclMap::Iterator iter = mVertexDecls.begin(); 709 for ( ; iter != mVertexDecls.end(); iter++ ) 710 delete iter->value; 711 712 // Forcibly clean up the pools 713 mVolatileVBList.setSize(0); 714 mDynamicPB = NULL; 715 716 // And release our D3D resources. 717 SAFE_RELEASE(mDeviceDepthStencilView); 718 SAFE_RELEASE(mDeviceBackBufferView); 719 SAFE_RELEASE(mDeviceDepthStencil); 720 SAFE_RELEASE(mDeviceBackbuffer); 721 SAFE_RELEASE(mD3DDeviceContext); 722 723 SAFE_DELETE(mCardProfiler); 724 SAFE_DELETE(gScreenShot); 725 726#ifdef TORQUE_DEBUG 727 if (mDebugLayers) 728 { 729 ID3D11Debug *pDebug = NULL; 730 mD3DDevice->QueryInterface(IID_PPV_ARGS(&pDebug)); 731 AssertFatal(pDebug, "~GFXD3D11Device- Failed to get debug layer"); 732 pDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); 733 SAFE_RELEASE(pDebug); 734 } 735#endif 736 737 SAFE_RELEASE(mSwapChain); 738 SAFE_RELEASE(mD3DDevice); 739} 740 741void GFXD3D11Device::setupGenericShaders(GenericShaderType type) 742{ 743 AssertFatal(type != GSTargetRestore, ""); //not used 744 745 if(mGenericShader[GSColor] == NULL) 746 { 747 ShaderData *shaderData; 748 749 shaderData = new ShaderData(); 750 shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/colorV.hlsl"); 751 shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/colorP.hlsl"); 752 shaderData->setField("pixVersion", "5.0"); 753 shaderData->registerObject(); 754 mGenericShader[GSColor] = shaderData->getShader(); 755 mGenericShaderBuffer[GSColor] = mGenericShader[GSColor]->allocConstBuffer(); 756 mModelViewProjSC[GSColor] = mGenericShader[GSColor]->getShaderConstHandle("$modelView"); 757 Sim::getRootGroup()->addObject(shaderData); 758 759 shaderData = new ShaderData(); 760 shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/modColorTextureV.hlsl"); 761 shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/modColorTextureP.hlsl"); 762 shaderData->setField("pixVersion", "5.0"); 763 shaderData->registerObject(); 764 mGenericShader[GSModColorTexture] = shaderData->getShader(); 765 mGenericShaderBuffer[GSModColorTexture] = mGenericShader[GSModColorTexture]->allocConstBuffer(); 766 mModelViewProjSC[GSModColorTexture] = mGenericShader[GSModColorTexture]->getShaderConstHandle("$modelView"); 767 Sim::getRootGroup()->addObject(shaderData); 768 769 shaderData = new ShaderData(); 770 shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/addColorTextureV.hlsl"); 771 shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/addColorTextureP.hlsl"); 772 shaderData->setField("pixVersion", "5.0"); 773 shaderData->registerObject(); 774 mGenericShader[GSAddColorTexture] = shaderData->getShader(); 775 mGenericShaderBuffer[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->allocConstBuffer(); 776 mModelViewProjSC[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->getShaderConstHandle("$modelView"); 777 Sim::getRootGroup()->addObject(shaderData); 778 779 shaderData = new ShaderData(); 780 shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/textureV.hlsl"); 781 shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/textureP.hlsl"); 782 shaderData->setField("pixVersion", "5.0"); 783 shaderData->registerObject(); 784 mGenericShader[GSTexture] = shaderData->getShader(); 785 mGenericShaderBuffer[GSTexture] = mGenericShader[GSTexture]->allocConstBuffer(); 786 mModelViewProjSC[GSTexture] = mGenericShader[GSTexture]->getShaderConstHandle("$modelView"); 787 Sim::getRootGroup()->addObject(shaderData); 788 789 //Force an update 790 mViewportDirty = true; 791 _updateRenderTargets(); 792 } 793 794 MatrixF tempMatrix = mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize]; 795 mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix); 796 797 setShader(mGenericShader[type]); 798 setShaderConstBuffer(mGenericShaderBuffer[type]); 799} 800 801//----------------------------------------------------------------------------- 802/// Creates a state block object based on the desc passed in. This object 803/// represents an immutable state. 804GFXStateBlockRef GFXD3D11Device::createStateBlockInternal(const GFXStateBlockDesc& desc) 805{ 806 return GFXStateBlockRef(new GFXD3D11StateBlock(desc)); 807} 808 809/// Activates a stateblock 810void GFXD3D11Device::setStateBlockInternal(GFXStateBlock* block, bool force) 811{ 812 AssertFatal(static_cast<GFXD3D11StateBlock*>(block), "Incorrect stateblock type for this device!"); 813 GFXD3D11StateBlock* d3dBlock = static_cast<GFXD3D11StateBlock*>(block); 814 GFXD3D11StateBlock* d3dCurrent = static_cast<GFXD3D11StateBlock*>(mCurrentStateBlock.getPointer()); 815 816 if (force) 817 d3dCurrent = NULL; 818 819 d3dBlock->activate(d3dCurrent); 820} 821 822/// Called by base GFXDevice to actually set a const buffer 823void GFXD3D11Device::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer) 824{ 825 if (buffer) 826 { 827 PROFILE_SCOPE(GFXD3D11Device_setShaderConstBufferInternal); 828 AssertFatal(static_cast<GFXD3D11ShaderConstBuffer*>(buffer), "Incorrect shader const buffer type for this device!"); 829 GFXD3D11ShaderConstBuffer* d3dBuffer = static_cast<GFXD3D11ShaderConstBuffer*>(buffer); 830 831 d3dBuffer->activate(mCurrentConstBuffer); 832 mCurrentConstBuffer = d3dBuffer; 833 } 834 else 835 { 836 mCurrentConstBuffer = NULL; 837 } 838} 839 840//----------------------------------------------------------------------------- 841 842void GFXD3D11Device::clear(U32 flags, ColorI color, F32 z, U32 stencil) 843{ 844 // Make sure we have flushed our render target state. 845 _updateRenderTargets(); 846 847 UINT depthstencilFlag = 0; 848 849 ID3D11RenderTargetView* rtView = NULL; 850 ID3D11DepthStencilView* dsView = NULL; 851 852 mD3DDeviceContext->OMGetRenderTargets(1, &rtView, &dsView); 853 854 const FLOAT clearColor[4] = { 855 static_cast<F32>(color.red) * (1.0f / 255.0f), 856 static_cast<F32>(color.green) * (1.0f / 255.0f), 857 static_cast<F32>(color.blue) * (1.0f / 255.0f), 858 static_cast<F32>(color.alpha) * (1.0f / 255.0f) 859 }; 860 861 if (flags & GFXClearTarget && rtView) 862 mD3DDeviceContext->ClearRenderTargetView(rtView, clearColor); 863 864 if (flags & GFXClearZBuffer) 865 depthstencilFlag |= D3D11_CLEAR_DEPTH; 866 867 if (flags & GFXClearStencil) 868 depthstencilFlag |= D3D11_CLEAR_STENCIL; 869 870 if (depthstencilFlag && dsView) 871 mD3DDeviceContext->ClearDepthStencilView(dsView, depthstencilFlag, z, stencil); 872 873 SAFE_RELEASE(rtView); 874 SAFE_RELEASE(dsView); 875} 876 877void GFXD3D11Device::endSceneInternal() 878{ 879 mCanCurrentlyRender = false; 880} 881 882void GFXD3D11Device::_updateRenderTargets() 883{ 884 if (mRTDirty || (mCurrentRT && mCurrentRT->isPendingState())) 885 { 886 if (mRTDeactivate) 887 { 888 mRTDeactivate->deactivate(); 889 mRTDeactivate = NULL; 890 } 891 892 // NOTE: The render target changes are not really accurate 893 // as the GFXTextureTarget supports MRT internally. So when 894 // we activate a GFXTarget it could result in multiple calls 895 // to SetRenderTarget on the actual device. 896 mDeviceStatistics.mRenderTargetChanges++; 897 898 mCurrentRT->activate(); 899 900 mRTDirty = false; 901 } 902 903 if (mViewportDirty) 904 { 905 D3D11_VIEWPORT viewport; 906 907 viewport.TopLeftX = mViewport.point.x; 908 viewport.TopLeftY = mViewport.point.y; 909 viewport.Width = mViewport.extent.x; 910 viewport.Height = mViewport.extent.y; 911 viewport.MinDepth = 0.0f; 912 viewport.MaxDepth = 1.0f; 913 914 mD3DDeviceContext->RSSetViewports(1, &viewport); 915 916 mViewportDirty = false; 917 } 918} 919 920void GFXD3D11Device::releaseDefaultPoolResources() 921{ 922 // Release all the dynamic vertex buffer arrays 923 // Forcibly clean up the pools 924 for(U32 i=0; i<mVolatileVBList.size(); i++) 925 { 926 SAFE_RELEASE(mVolatileVBList[i]->vb); 927 mVolatileVBList[i] = NULL; 928 } 929 mVolatileVBList.setSize(0); 930 931 // We gotta clear the current const buffer else the next 932 // activate may erroneously think the device is still holding 933 // this state and fail to set it. 934 mCurrentConstBuffer = NULL; 935 936 // Set current VB to NULL and set state dirty 937 for (U32 i=0; i < VERTEX_STREAM_COUNT; i++) 938 { 939 mCurrentVertexBuffer[i] = NULL; 940 mVertexBufferDirty[i] = true; 941 mVertexBufferFrequency[i] = 0; 942 mVertexBufferFrequencyDirty[i] = true; 943 } 944 945 // Release dynamic index buffer 946 if(mDynamicPB != NULL) 947 { 948 SAFE_RELEASE(mDynamicPB->ib); 949 } 950 951 // Set current PB/IB to NULL and set state dirty 952 mCurrentPrimitiveBuffer = NULL; 953 mCurrentPB = NULL; 954 mPrimitiveBufferDirty = true; 955 956 // Zombify texture manager (for D3D this only modifies default pool textures) 957 if( mTextureManager ) 958 mTextureManager->zombify(); 959 960 // Set global dirty state so the IB/PB and VB get reset 961 mStateDirty = true; 962 963 // Walk the resource list and zombify everything. 964 GFXResource *walk = mResourceListHead; 965 while(walk) 966 { 967 walk->zombify(); 968 walk = walk->getNextResource(); 969 } 970} 971 972void GFXD3D11Device::reacquireDefaultPoolResources() 973{ 974 // Now do the dynamic index buffers 975 if( mDynamicPB == NULL ) 976 mDynamicPB = new GFXD3D11PrimitiveBuffer(this, 0, 0, GFXBufferTypeDynamic); 977 978 D3D11_BUFFER_DESC desc; 979 desc.ByteWidth = sizeof(U16) * MAX_DYNAMIC_INDICES; 980 desc.Usage = D3D11_USAGE_DYNAMIC; 981 desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 982 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 983 desc.MiscFlags = 0; 984 desc.StructureByteStride = 0; 985 986 HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &mDynamicPB->ib); 987 988 if(FAILED(hr)) 989 { 990 AssertFatal(false, "Failed to allocate dynamic IB"); 991 } 992 993 // Walk the resource list and zombify everything. 994 GFXResource *walk = mResourceListHead; 995 while(walk) 996 { 997 walk->resurrect(); 998 walk = walk->getNextResource(); 999 } 1000 1001 if(mTextureManager) 1002 mTextureManager->resurrect(); 1003} 1004 1005GFXD3D11VertexBuffer* GFXD3D11Device::findVBPool( const GFXVertexFormat *vertexFormat, U32 vertsNeeded ) 1006{ 1007 PROFILE_SCOPE( GFXD3D11Device_findVBPool ); 1008 1009 for( U32 i=0; i<mVolatileVBList.size(); i++ ) 1010 if( mVolatileVBList[i]->mVertexFormat.isEqual( *vertexFormat ) ) 1011 return mVolatileVBList[i]; 1012 1013 return NULL; 1014} 1015 1016GFXD3D11VertexBuffer * GFXD3D11Device::createVBPool( const GFXVertexFormat *vertexFormat, U32 vertSize ) 1017{ 1018 PROFILE_SCOPE( GFXD3D11Device_createVBPool ); 1019 1020 // this is a bit funky, but it will avoid problems with (lack of) copy constructors 1021 // with a push_back() situation 1022 mVolatileVBList.increment(); 1023 StrongRefPtr<GFXD3D11VertexBuffer> newBuff; 1024 mVolatileVBList.last() = new GFXD3D11VertexBuffer(); 1025 newBuff = mVolatileVBList.last(); 1026 1027 newBuff->mNumVerts = 0; 1028 newBuff->mBufferType = GFXBufferTypeVolatile; 1029 newBuff->mVertexFormat.copy( *vertexFormat ); 1030 newBuff->mVertexSize = vertSize; 1031 newBuff->mDevice = this; 1032 1033 // Requesting it will allocate it. 1034 vertexFormat->getDecl(); 1035 1036 D3D11_BUFFER_DESC desc; 1037 desc.ByteWidth = vertSize * MAX_DYNAMIC_VERTS; 1038 desc.Usage = D3D11_USAGE_DYNAMIC; 1039 desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 1040 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 1041 desc.MiscFlags = 0; 1042 desc.StructureByteStride = 0; 1043 1044 HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &newBuff->vb); 1045 1046 if(FAILED(hr)) 1047 { 1048 AssertFatal(false, "Failed to allocate dynamic VB"); 1049 } 1050 1051 return newBuff; 1052} 1053 1054//----------------------------------------------------------------------------- 1055 1056void GFXD3D11Device::setClipRect( const RectI &inRect ) 1057{ 1058 // We transform the incoming rect by the view 1059 // matrix first, so that it can be used to pan 1060 // and scale the clip rect. 1061 // 1062 // This is currently used to take tiled screenshots. 1063 Point3F pos( inRect.point.x, inRect.point.y, 0.0f ); 1064 Point3F extent( inRect.extent.x, inRect.extent.y, 0.0f ); 1065 getViewMatrix().mulP( pos ); 1066 getViewMatrix().mulV( extent ); 1067 RectI rect( pos.x, pos.y, extent.x, extent.y ); 1068 1069 // Clip the rect against the renderable size. 1070 Point2I size = mCurrentRT->getSize(); 1071 1072 RectI maxRect(Point2I(0,0), size); 1073 rect.intersect(maxRect); 1074 1075 mClipRect = rect; 1076 1077 F32 l = F32( mClipRect.point.x ); 1078 F32 r = F32( mClipRect.point.x + mClipRect.extent.x ); 1079 F32 b = F32( mClipRect.point.y + mClipRect.extent.y ); 1080 F32 t = F32( mClipRect.point.y ); 1081 1082 // Set up projection matrix, 1083 static Point4F pt; 1084 pt.set(2.0f / (r - l), 0.0f, 0.0f, 0.0f); 1085 mTempMatrix.setColumn(0, pt); 1086 1087 pt.set(0.0f, 2.0f/(t - b), 0.0f, 0.0f); 1088 mTempMatrix.setColumn(1, pt); 1089 1090 pt.set(0.0f, 0.0f, 1.0f, 0.0f); 1091 mTempMatrix.setColumn(2, pt); 1092 1093 pt.set((l+r)/(l-r), (t+b)/(b-t), 1.0f, 1.0f); 1094 mTempMatrix.setColumn(3, pt); 1095 1096 setProjectionMatrix( mTempMatrix ); 1097 1098 // Set up world/view matrix 1099 mTempMatrix.identity(); 1100 setWorldMatrix( mTempMatrix ); 1101 1102 setViewport( mClipRect ); 1103} 1104 1105void GFXD3D11Device::setVertexStream( U32 stream, GFXVertexBuffer *buffer ) 1106{ 1107 GFXD3D11VertexBuffer *d3dBuffer = static_cast<GFXD3D11VertexBuffer*>( buffer ); 1108 1109 if ( stream == 0 ) 1110 { 1111 // Set the volatile buffer which is used to 1112 // offset the start index when doing draw calls. 1113 if ( d3dBuffer && d3dBuffer->mVolatileStart > 0 ) 1114 mVolatileVB = d3dBuffer; 1115 else 1116 mVolatileVB = NULL; 1117 } 1118 1119 // NOTE: We do not use the stream offset here for stream 0 1120 // as that feature is *supposedly* not as well supported as 1121 // using the start index in drawPrimitive. 1122 // 1123 // If we can verify that this is not the case then we should 1124 // start using this method exclusively for all streams. 1125 1126 U32 strides[1] = { d3dBuffer ? d3dBuffer->mVertexSize : 0 }; 1127 U32 offset = d3dBuffer && stream != 0 ? d3dBuffer->mVolatileStart * d3dBuffer->mVertexSize : 0; 1128 ID3D11Buffer* buff = d3dBuffer ? d3dBuffer->vb : NULL; 1129 1130 getDeviceContext()->IASetVertexBuffers(stream, 1, &buff, strides, &offset); 1131} 1132 1133void GFXD3D11Device::setVertexStreamFrequency( U32 stream, U32 frequency ) 1134{ 1135 if (stream == 0) 1136 mDrawInstancesCount = frequency; // instances count 1137} 1138 1139void GFXD3D11Device::_setPrimitiveBuffer( GFXPrimitiveBuffer *buffer ) 1140{ 1141 mCurrentPB = static_cast<GFXD3D11PrimitiveBuffer *>( buffer ); 1142 1143 mD3DDeviceContext->IASetIndexBuffer(mCurrentPB->ib, DXGI_FORMAT_R16_UINT, 0); 1144} 1145 1146U32 GFXD3D11Device::primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount) 1147{ 1148 switch (primType) 1149 { 1150 case GFXPointList: 1151 return primitiveCount; 1152 break; 1153 case GFXLineList: 1154 return primitiveCount * 2; 1155 break; 1156 case GFXLineStrip: 1157 return primitiveCount + 1; 1158 break; 1159 case GFXTriangleList: 1160 return primitiveCount * 3; 1161 break; 1162 case GFXTriangleStrip: 1163 return 2 + primitiveCount; 1164 break; 1165 default: 1166 AssertFatal(false, "GFXGLDevice::primCountToIndexCount - unrecognized prim type"); 1167 break; 1168 1169 } 1170 return 0; 1171} 1172 1173 1174void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) 1175{ 1176 // This is done to avoid the function call overhead if possible 1177 if( mStateDirty ) 1178 updateStates(); 1179 if (mCurrentShaderConstBuffer) 1180 setShaderConstBufferInternal(mCurrentShaderConstBuffer); 1181 1182 if ( mVolatileVB ) 1183 vertexStart += mVolatileVB->mVolatileStart; 1184 1185 mD3DDeviceContext->IASetPrimitiveTopology(GFXD3D11PrimType[primType]); 1186 1187 if ( mDrawInstancesCount ) 1188 mD3DDeviceContext->DrawInstanced(primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount, vertexStart, 0); 1189 else 1190 mD3DDeviceContext->Draw(primCountToIndexCount(primType, primitiveCount), vertexStart); 1191 1192 mDeviceStatistics.mDrawCalls++; 1193 if ( mVertexBufferFrequency[0] > 1 ) 1194 mDeviceStatistics.mPolyCount += primitiveCount * mVertexBufferFrequency[0]; 1195 else 1196 mDeviceStatistics.mPolyCount += primitiveCount; 1197} 1198 1199void GFXD3D11Device::drawIndexedPrimitive( GFXPrimitiveType primType, 1200 U32 startVertex, 1201 U32 minIndex, 1202 U32 numVerts, 1203 U32 startIndex, 1204 U32 primitiveCount ) 1205{ 1206 // This is done to avoid the function call overhead if possible 1207 if( mStateDirty ) 1208 updateStates(); 1209 if (mCurrentShaderConstBuffer) 1210 setShaderConstBufferInternal(mCurrentShaderConstBuffer); 1211 1212 AssertFatal( mCurrentPB != NULL, "Trying to call drawIndexedPrimitive with no current index buffer, call setIndexBuffer()" ); 1213 1214 if ( mVolatileVB ) 1215 startVertex += mVolatileVB->mVolatileStart; 1216 1217 mD3DDeviceContext->IASetPrimitiveTopology(GFXD3D11PrimType[primType]); 1218 1219 if ( mDrawInstancesCount ) 1220 mD3DDeviceContext->DrawIndexedInstanced(primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount, mCurrentPB->mVolatileStart + startIndex, startVertex, 0); 1221 else 1222 mD3DDeviceContext->DrawIndexed(primCountToIndexCount(primType,primitiveCount), mCurrentPB->mVolatileStart + startIndex, startVertex); 1223 1224 mDeviceStatistics.mDrawCalls++; 1225 if ( mVertexBufferFrequency[0] > 1 ) 1226 mDeviceStatistics.mPolyCount += primitiveCount * mVertexBufferFrequency[0]; 1227 else 1228 mDeviceStatistics.mPolyCount += primitiveCount; 1229} 1230 1231GFXShader* GFXD3D11Device::createShader() 1232{ 1233 GFXD3D11Shader* shader = new GFXD3D11Shader(); 1234 shader->registerResourceWithDevice( this ); 1235 return shader; 1236} 1237 1238//----------------------------------------------------------------------------- 1239// Set shader - this function exists to make sure this is done in one place, 1240// and to make sure redundant shader states are not being 1241// sent to the card. 1242//----------------------------------------------------------------------------- 1243void GFXD3D11Device::setShader(GFXShader *shader, bool force) 1244{ 1245 if(shader) 1246 { 1247 GFXD3D11Shader *d3dShader = static_cast<GFXD3D11Shader*>(shader); 1248 1249 if (d3dShader->mPixShader != mLastPixShader || force) 1250 { 1251 mD3DDeviceContext->PSSetShader( d3dShader->mPixShader, NULL, 0); 1252 mLastPixShader = d3dShader->mPixShader; 1253 } 1254 1255 if (d3dShader->mVertShader != mLastVertShader || force) 1256 { 1257 mD3DDeviceContext->VSSetShader( d3dShader->mVertShader, NULL, 0); 1258 mLastVertShader = d3dShader->mVertShader; 1259 } 1260 } 1261 else 1262 { 1263 setupGenericShaders(); 1264 } 1265} 1266 1267GFXPrimitiveBuffer * GFXD3D11Device::allocPrimitiveBuffer(U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void *data ) 1268{ 1269 // Allocate a buffer to return 1270 GFXD3D11PrimitiveBuffer * res = new GFXD3D11PrimitiveBuffer(this, numIndices, numPrimitives, bufferType); 1271 1272 // Determine usage flags 1273 D3D11_USAGE usage = D3D11_USAGE_DEFAULT; 1274 1275 // Assumptions: 1276 // - static buffers are write once, use many 1277 // - dynamic buffers are write many, use many 1278 // - volatile buffers are write once, use once 1279 // You may never read from a buffer. 1280 //TODO: enable proper support for D3D11_USAGE_IMMUTABLE 1281 switch(bufferType) 1282 { 1283 case GFXBufferTypeImmutable: 1284 case GFXBufferTypeStatic: 1285 usage = D3D11_USAGE_DEFAULT; //D3D11_USAGE_IMMUTABLE; 1286 break; 1287 1288 case GFXBufferTypeDynamic: 1289 case GFXBufferTypeVolatile: 1290 usage = D3D11_USAGE_DYNAMIC; 1291 break; 1292 } 1293 1294 // Register resource 1295 res->registerResourceWithDevice(this); 1296 1297 // Create d3d index buffer 1298 if(bufferType == GFXBufferTypeVolatile) 1299 { 1300 // Get it from the pool if it's a volatile... 1301 AssertFatal(numIndices < MAX_DYNAMIC_INDICES, "Cannot allocate that many indices in a volatile buffer, increase MAX_DYNAMIC_INDICES."); 1302 1303 res->ib = mDynamicPB->ib; 1304 res->mVolatileBuffer = mDynamicPB; 1305 } 1306 else 1307 { 1308 // Otherwise, get it as a seperate buffer... 1309 D3D11_BUFFER_DESC desc; 1310 desc.ByteWidth = sizeof(U16) * numIndices; 1311 desc.Usage = usage; 1312 if(bufferType == GFXBufferTypeDynamic) 1313 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // We never allow reading from a primitive buffer. 1314 else 1315 desc.CPUAccessFlags = 0; 1316 desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 1317 desc.MiscFlags = 0; 1318 desc.StructureByteStride = 0; 1319 1320 HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &res->ib); 1321 1322 if(FAILED(hr)) 1323 { 1324 AssertFatal(false, "Failed to allocate an index buffer."); 1325 } 1326 } 1327 1328 if (data) 1329 { 1330 void* dest; 1331 res->lock(0, numIndices, &dest); 1332 dMemcpy(dest, data, sizeof(U16) * numIndices); 1333 res->unlock(); 1334 } 1335 1336 return res; 1337} 1338 1339GFXVertexBuffer * GFXD3D11Device::allocVertexBuffer(U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, GFXBufferType bufferType, void *data) 1340{ 1341 PROFILE_SCOPE( GFXD3D11Device_allocVertexBuffer ); 1342 1343 GFXD3D11VertexBuffer *res = new GFXD3D11VertexBuffer( this, 1344 numVerts, 1345 vertexFormat, 1346 vertSize, 1347 bufferType ); 1348 1349 // Determine usage flags 1350 D3D11_USAGE usage = D3D11_USAGE_DEFAULT; 1351 1352 res->mNumVerts = 0; 1353 1354 // Assumptions: 1355 // - static buffers are write once, use many 1356 // - dynamic buffers are write many, use many 1357 // - volatile buffers are write once, use once 1358 // You may never read from a buffer. 1359 //TODO: enable proper support for D3D11_USAGE_IMMUTABLE 1360 switch(bufferType) 1361 { 1362 case GFXBufferTypeImmutable: 1363 case GFXBufferTypeStatic: 1364 usage = D3D11_USAGE_DEFAULT; 1365 break; 1366 1367 case GFXBufferTypeDynamic: 1368 case GFXBufferTypeVolatile: 1369 usage = D3D11_USAGE_DYNAMIC; 1370 break; 1371 } 1372 1373 // Register resource 1374 res->registerResourceWithDevice(this); 1375 1376 // Create vertex buffer 1377 if(bufferType == GFXBufferTypeVolatile) 1378 { 1379 // NOTE: Volatile VBs are pooled and will be allocated at lock time. 1380 AssertFatal(numVerts <= MAX_DYNAMIC_VERTS, "GFXD3D11Device::allocVertexBuffer - Volatile vertex buffer is too big... see MAX_DYNAMIC_VERTS!"); 1381 } 1382 else 1383 { 1384 // Requesting it will allocate it. 1385 vertexFormat->getDecl(); //-ALEX disabled to postpone until after shader is actually set... 1386 1387 // Get a new buffer... 1388 D3D11_BUFFER_DESC desc; 1389 desc.ByteWidth = vertSize * numVerts; 1390 desc.Usage = usage; 1391 desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 1392 if(bufferType == GFXBufferTypeDynamic) 1393 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // We never allow reading from a vertex buffer. 1394 else 1395 desc.CPUAccessFlags = 0; 1396 desc.MiscFlags = 0; 1397 desc.StructureByteStride = 0; 1398 1399 HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &res->vb); 1400 1401 if(FAILED(hr)) 1402 { 1403 AssertFatal(false, "Failed to allocate VB"); 1404 } 1405 } 1406 1407 res->mNumVerts = numVerts; 1408 1409 if (data) 1410 { 1411 void* dest; 1412 res->lock(0, numVerts, &dest); 1413 dMemcpy(dest, data, vertSize * numVerts); 1414 res->unlock(); 1415 } 1416 1417 return res; 1418} 1419 1420String GFXD3D11Device::_createTempShaderInternal(const GFXVertexFormat *vertexFormat) 1421{ 1422 U32 elemCount = vertexFormat->getElementCount(); 1423 //Input data 1424 StringBuilder inputData; 1425 inputData.append("struct VertIn {"); 1426 //Output data 1427 StringBuilder outputData; 1428 outputData.append("struct VertOut {"); 1429 // Shader main body data 1430 StringBuilder mainBodyData; 1431 //make shader 1432 mainBodyData.append("VertOut main(VertIn IN){VertOut OUT;"); 1433 1434 bool addedPadding = false; 1435 for (U32 i = 0; i < elemCount; i++) 1436 { 1437 const GFXVertexElement &element = vertexFormat->getElement(i); 1438 String semantic = element.getSemantic(); 1439 String semanticOut = semantic; 1440 String type; 1441 1442 AssertFatal(!(addedPadding && !element.isSemantic(GFXSemantic::PADDING)), "Padding added before data"); 1443 1444 if (element.isSemantic(GFXSemantic::POSITION)) 1445 { 1446 semantic = "POSITION"; 1447 semanticOut = "SV_Position"; 1448 } 1449 else if (element.isSemantic(GFXSemantic::NORMAL)) 1450 { 1451 semantic = "NORMAL"; 1452 semanticOut = semantic; 1453 } 1454 else if (element.isSemantic(GFXSemantic::COLOR)) 1455 { 1456 semantic = "COLOR"; 1457 semanticOut = semantic; 1458 } 1459 else if (element.isSemantic(GFXSemantic::TANGENT)) 1460 { 1461 semantic = "TANGENT"; 1462 semanticOut = semantic; 1463 } 1464 else if (element.isSemantic(GFXSemantic::BINORMAL)) 1465 { 1466 semantic = "BINORMAL"; 1467 semanticOut = semantic; 1468 } 1469 else if (element.isSemantic(GFXSemantic::BLENDINDICES)) 1470 { 1471 semantic = String::ToString("BLENDINDICES%d", element.getSemanticIndex()); 1472 semanticOut = semantic; 1473 } 1474 else if (element.isSemantic(GFXSemantic::BLENDWEIGHT)) 1475 { 1476 semantic = String::ToString("BLENDWEIGHT%d", element.getSemanticIndex()); 1477 semanticOut = semantic; 1478 } 1479 else if (element.isSemantic(GFXSemantic::PADDING)) 1480 { 1481 addedPadding = true; 1482 continue; 1483 } 1484 else 1485 { 1486 //Anything that falls thru to here will be a texture coord. 1487 semantic = String::ToString("TEXCOORD%d", element.getSemanticIndex()); 1488 semanticOut = semantic; 1489 } 1490 1491 switch (GFXD3D11DeclType[element.getType()]) 1492 { 1493 case DXGI_FORMAT_R32_FLOAT: 1494 type = "float"; 1495 break; 1496 case DXGI_FORMAT_R32G32_FLOAT: 1497 type = "float2"; 1498 break; 1499 case DXGI_FORMAT_R32G32B32_FLOAT: 1500 type = "float3"; 1501 break; 1502 case DXGI_FORMAT_R32G32B32A32_FLOAT: 1503 case DXGI_FORMAT_B8G8R8A8_UNORM: 1504 case DXGI_FORMAT_R8G8B8A8_UNORM: 1505 type = "float4"; 1506 break; 1507 case DXGI_FORMAT_R8G8B8A8_UINT: 1508 type = "uint4"; 1509 break; 1510 } 1511 1512 StringBuilder in; 1513 in.format("%s %s%d : %s;", type.c_str(), "var", i, semantic.c_str()); 1514 inputData.append(in.data()); 1515 1516 //SV_Position must be float4 1517 if (semanticOut == String("SV_Position")) 1518 { 1519 StringBuilder out; 1520 out.format("float4 %s%d : %s;", "var", i, semanticOut.c_str()); 1521 outputData.append(out.data()); 1522 StringBuilder body; 1523 body.format("OUT.%s%d = float4(IN.%s%d.xyz,1);", "var", i, "var", i); 1524 mainBodyData.append(body.data()); 1525 } 1526 else 1527 { 1528 StringBuilder out; 1529 out.format("%s %s%d : %s;", type.c_str(), "var", i, semanticOut.c_str()); 1530 outputData.append(out.data()); 1531 StringBuilder body; 1532 body.format("OUT.%s%d = IN.%s%d;", "var", i, "var", i); 1533 mainBodyData.append(body.data()); 1534 } 1535 } 1536 1537 inputData.append("};"); 1538 outputData.append("};"); 1539 mainBodyData.append("return OUT;}"); 1540 1541 //final data 1542 StringBuilder finalData; 1543 finalData.append(inputData.data()); 1544 finalData.append(outputData.data()); 1545 finalData.append(mainBodyData.data()); 1546 1547 return String(finalData.data()); 1548} 1549 1550GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFormat ) 1551{ 1552 PROFILE_SCOPE( GFXD3D11Device_allocVertexDecl ); 1553 1554 // First check the map... you shouldn't allocate VBs very often 1555 // if you want performance. The map lookup should never become 1556 // a performance bottleneck. 1557 D3D11VertexDecl *decl = mVertexDecls[vertexFormat->getDescription()]; 1558 if ( decl ) 1559 return decl; 1560 1561 U32 elemCount = vertexFormat->getElementCount(); 1562 1563 ID3DBlob* code = NULL; 1564 1565 // We have to generate a temporary shader here for now since the input layout creation 1566 // expects a shader to be already compiled to verify the vertex layout structure. The problem 1567 // is that most of the time the regular shaders are compiled AFTER allocVertexDecl is called. 1568 if(!decl) 1569 { 1570 //TODO: Perhaps save/cache the ID3DBlob for later use on identical vertex formats,save creating/compiling the temp shader everytime 1571 String shaderData = _createTempShaderInternal(vertexFormat); 1572 1573#ifdef TORQUE_DEBUG 1574 U32 flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS; 1575#else 1576 U32 flags = D3DCOMPILE_ENABLE_STRICTNESS; 1577#endif 1578 1579 ID3DBlob *errorBlob = NULL; 1580 HRESULT hr = D3DCompile(shaderData.c_str(), shaderData.length(), NULL, NULL, NULL, "main", "vs_5_0", flags, 0, &code, &errorBlob); 1581 StringBuilder error; 1582 1583 if(errorBlob) 1584 { 1585 error.append((char*)errorBlob->GetBufferPointer(), errorBlob->GetBufferSize()); 1586 AssertFatal(hr, error.data()); 1587 } 1588 1589 SAFE_RELEASE(errorBlob); 1590 } 1591 1592 AssertFatal(code, "D3D11Device::allocVertexDecl - compiled vert shader code missing!"); 1593 1594 // Setup the declaration struct. 1595 1596 U32 stream; 1597 D3D11_INPUT_ELEMENT_DESC *vd = new D3D11_INPUT_ELEMENT_DESC[ elemCount]; 1598 1599 S32 elemIndex = 0; 1600 for (S32 i = 0; i < elemCount; i++, elemIndex++) 1601 { 1602 const GFXVertexElement &element = vertexFormat->getElement(elemIndex); 1603 1604 stream = element.getStreamIndex(); 1605 1606 vd[i].InputSlot = stream; 1607 1608 vd[i].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; 1609 vd[i].Format = GFXD3D11DeclType[element.getType()]; 1610 // If instancing is enabled, the per instance data is only used on stream 1. 1611 if (vertexFormat->hasInstancing() && stream == 1) 1612 { 1613 vd[i].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA; 1614 vd[i].InstanceDataStepRate = 1; 1615 } 1616 else 1617 { 1618 vd[i].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 1619 vd[i].InstanceDataStepRate = 0; 1620 } 1621 // We force the usage index of 0 for everything but 1622 // texture coords for now... this may change later. 1623 vd[i].SemanticIndex = 0; 1624 1625 if (element.isSemantic(GFXSemantic::POSITION)) 1626 vd[i].SemanticName = "POSITION"; 1627 else if (element.isSemantic(GFXSemantic::NORMAL)) 1628 vd[i].SemanticName = "NORMAL"; 1629 else if (element.isSemantic(GFXSemantic::COLOR)) 1630 vd[i].SemanticName = "COLOR"; 1631 else if (element.isSemantic(GFXSemantic::TANGENT)) 1632 vd[i].SemanticName = "TANGENT"; 1633 else if (element.isSemantic(GFXSemantic::BINORMAL)) 1634 vd[i].SemanticName = "BINORMAL"; 1635 else if (element.isSemantic(GFXSemantic::BLENDWEIGHT)) 1636 { 1637 vd[i].SemanticName = "BLENDWEIGHT"; 1638 vd[i].SemanticIndex = element.getSemanticIndex(); 1639 } 1640 else if (element.isSemantic(GFXSemantic::BLENDINDICES)) 1641 { 1642 vd[i].SemanticName = "BLENDINDICES"; 1643 vd[i].SemanticIndex = element.getSemanticIndex(); 1644 } 1645 else if (element.isSemantic(GFXSemantic::PADDING)) 1646 { 1647 i--; 1648 elemCount--; 1649 continue; 1650 } 1651 else 1652 { 1653 //Anything that falls thru to here will be a texture coord. 1654 vd[i].SemanticName = "TEXCOORD"; 1655 vd[i].SemanticIndex = element.getSemanticIndex(); 1656 } 1657 1658 } 1659 1660 decl = new D3D11VertexDecl(); 1661 HRESULT hr = mD3DDevice->CreateInputLayout(vd, elemCount,code->GetBufferPointer(), code->GetBufferSize(), &decl->decl); 1662 1663 if (FAILED(hr)) 1664 { 1665 AssertFatal(false, "GFXD3D11Device::allocVertexDecl - Failed to create vertex input layout!"); 1666 } 1667 1668 delete [] vd; 1669 SAFE_RELEASE(code); 1670 1671 // Store it in the cache. 1672 mVertexDecls[vertexFormat->getDescription()] = decl; 1673 1674 return decl; 1675} 1676 1677void GFXD3D11Device::setVertexDecl( const GFXVertexDecl *decl ) 1678{ 1679 ID3D11InputLayout *dx11Decl = NULL; 1680 if (decl) 1681 dx11Decl = static_cast<const D3D11VertexDecl*>(decl)->decl; 1682 1683 mD3DDeviceContext->IASetInputLayout(dx11Decl); 1684} 1685 1686//----------------------------------------------------------------------------- 1687// This function should ONLY be called from GFXDevice::updateStates() !!! 1688//----------------------------------------------------------------------------- 1689void GFXD3D11Device::setTextureInternal( U32 textureUnit, const GFXTextureObject *texture) 1690{ 1691 if( texture == NULL ) 1692 { 1693 ID3D11ShaderResourceView *pView = NULL; 1694 mD3DDeviceContext->PSSetShaderResources(textureUnit, 1, &pView); 1695 return; 1696 } 1697 1698 GFXD3D11TextureObject *tex = (GFXD3D11TextureObject*)(texture); 1699 mD3DDeviceContext->PSSetShaderResources(textureUnit, 1, tex->getSRViewPtr()); 1700} 1701 1702GFXFence *GFXD3D11Device::createFence() 1703{ 1704 // Figure out what fence type we should be making if we don't know 1705 if( mCreateFenceType == -1 ) 1706 { 1707 D3D11_QUERY_DESC desc; 1708 desc.MiscFlags = 0; 1709 desc.Query = D3D11_QUERY_EVENT; 1710 1711 ID3D11Query *testQuery = NULL; 1712 1713 HRESULT hRes = mD3DDevice->CreateQuery(&desc, &testQuery); 1714 1715 if(FAILED(hRes)) 1716 { 1717 mCreateFenceType = true; 1718 } 1719 1720 else 1721 { 1722 mCreateFenceType = false; 1723 } 1724 1725 SAFE_RELEASE(testQuery); 1726 } 1727 1728 // Cool, use queries 1729 if(!mCreateFenceType) 1730 { 1731 GFXFence* fence = new GFXD3D11QueryFence( this ); 1732 fence->registerResourceWithDevice(this); 1733 return fence; 1734 } 1735 1736 // CodeReview: At some point I would like a specialized implementation of 1737 // the method used by the general fence, only without the overhead incurred 1738 // by using the GFX constructs. Primarily the lock() method on texture handles 1739 // will do a data copy, and this method doesn't require a copy, just a lock 1740 // [5/10/2007 Pat] 1741 GFXFence* fence = new GFXGeneralFence( this ); 1742 fence->registerResourceWithDevice(this); 1743 return fence; 1744} 1745 1746GFXOcclusionQuery* GFXD3D11Device::createOcclusionQuery() 1747{ 1748 GFXOcclusionQuery *query; 1749 if (mOcclusionQuerySupported) 1750 query = new GFXD3D11OcclusionQuery( this ); 1751 else 1752 return NULL; 1753 1754 query->registerResourceWithDevice(this); 1755 return query; 1756} 1757 1758GFXCubemap * GFXD3D11Device::createCubemap() 1759{ 1760 GFXD3D11Cubemap* cube = new GFXD3D11Cubemap(); 1761 cube->registerResourceWithDevice(this); 1762 return cube; 1763} 1764
