Torque3D Documentation / _generateds / gfxD3D11Device.cpp

gfxD3D11Device.cpp

Engine/source/gfx/D3D11/gfxD3D11Device.cpp

More...

Classes:

Public Functions

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