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