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