Torque3D Documentation / _generateds / gfxD3D11Shader.cpp

gfxD3D11Shader.cpp

Engine/source/gfx/D3D11/gfxD3D11Shader.cpp

More...

Classes:

Public Variables

Detailed Description

Public Variables

bool gDisassembleAllShaders 
   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 "platform/platform.h"
  25#include "gfx/D3D11/gfxD3D11Shader.h"
  26#include "core/frameAllocator.h"
  27#include "core/stream/fileStream.h"
  28#include "core/util/safeDelete.h"
  29#include "console/console.h"
  30
  31extern bool gDisassembleAllShaders;
  32
  33#pragma comment(lib, "d3dcompiler.lib")
  34
  35gfxD3DIncludeRef GFXD3D11Shader::smD3DInclude = NULL;
  36
  37class gfxD3D11Include : public ID3DInclude, public StrongRefBase
  38{
  39private:
  40
  41   Vector<String> mLastPath;
  42
  43public:
  44
  45   void setPath(const String &path)
  46   {
  47      mLastPath.clear();
  48      mLastPath.push_back(path);
  49   }
  50
  51   gfxD3D11Include() {}
  52   virtual ~gfxD3D11Include() {}
  53
  54   STDMETHOD(Open)(THIS_ D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes);
  55   STDMETHOD(Close)(THIS_ LPCVOID pData);
  56};
  57
  58HRESULT gfxD3D11Include::Open(THIS_ D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
  59{
  60   using namespace Torque;
  61   // First try making the path relative to the parent.
  62   Torque::Path path = Torque::Path::Join( mLastPath.last(), '/', pFileName );
  63   path = Torque::Path::CompressPath( path );
  64
  65   if ( !Torque::FS::ReadFile( path, (void *&)*ppData, *pBytes, true ) )
  66   {
  67      // Ok... now try using the path as is.
  68      path = String( pFileName );
  69      path = Torque::Path::CompressPath( path );
  70
  71      if ( !Torque::FS::ReadFile( path, (void *&)*ppData, *pBytes, true ) )
  72      {
  73         AssertISV(false, avar( "Failed to open include '%s'.", pFileName));
  74         return E_FAIL;
  75      }
  76   }
  77
  78   // If the data was of zero size then we cannot recurse
  79   // into this file and DX won't call Close() below.
  80   //
  81   // So in this case don't push on the path.
  82   if ( *pBytes > 0 )
  83      mLastPath.push_back( path.getRootAndPath() );
  84
  85   return S_OK;
  86}
  87
  88HRESULT gfxD3D11Include::Close( THIS_ LPCVOID pData )
  89{
  90   // Free the data file and pop its path off the stack.
  91   delete [] (U8*)pData;
  92   mLastPath.pop_back();
  93
  94   return S_OK;
  95}
  96
  97GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle()
  98{
  99   clear();
 100}
 101
 102const String& GFXD3D11ShaderConstHandle::getName() const
 103{
 104   if ( mVertexConstant )
 105      return mVertexHandle.name;
 106   else
 107      return mPixelHandle.name;
 108}
 109
 110GFXShaderConstType GFXD3D11ShaderConstHandle::getType() const
 111{
 112   if ( mVertexConstant )
 113      return mVertexHandle.constType;
 114   else
 115      return mPixelHandle.constType;
 116}
 117
 118U32 GFXD3D11ShaderConstHandle::getArraySize() const
 119{
 120   if ( mVertexConstant )
 121      return mVertexHandle.arraySize;
 122   else
 123      return mPixelHandle.arraySize;
 124}
 125
 126S32 GFXD3D11ShaderConstHandle::getSamplerRegister() const
 127{
 128   if ( !mValid || !isSampler() )
 129      return -1;
 130
 131   // We always store sampler type and register index in the pixelHandle,
 132   // sampler registers are shared between vertex and pixel shaders anyway.
 133
 134   return mPixelHandle.offset;   
 135}
 136
 137GFXD3D11ConstBufferLayout::GFXD3D11ConstBufferLayout()
 138{
 139   mSubBuffers.reserve(CBUFFER_MAX);
 140}
 141
 142bool GFXD3D11ConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 inSize, const void* data, U8* basePointer)
 143{
 144   PROFILE_SCOPE(GenericConstBufferLayout_set);
 145   S32 size = inSize;
 146   // Shader compilers like to optimize float4x4 uniforms into float3x3s.
 147   // So long as the real paramater is a matrix of-some-type and the data
 148   // passed in is a MatrixF ( which is will be ), we DO NOT have a
 149   // mismatched const type.
 150   AssertFatal(pd.constType == constType ||
 151      (
 152      (pd.constType == GFXSCT_Float2x2 ||
 153      pd.constType == GFXSCT_Float3x3 ||
 154      pd.constType == GFXSCT_Float4x3 ||
 155      pd.constType == GFXSCT_Float4x4) &&
 156      (constType == GFXSCT_Float2x2 ||
 157      constType == GFXSCT_Float3x3 ||
 158      constType == GFXSCT_Float4x3 ||
 159      constType == GFXSCT_Float4x4)
 160      ), "Mismatched const type!");
 161
 162   // This "cute" bit of code allows us to support 2x3 and 3x3 matrices in shader constants but use our MatrixF class.  Yes, a hack. -BTR
 163   switch (pd.constType)
 164   {
 165   case GFXSCT_Float2x2:
 166   case GFXSCT_Float3x3:
 167   case GFXSCT_Float4x3:
 168   case GFXSCT_Float4x4:
 169      return setMatrix(pd, constType, size, data, basePointer);
 170      break;
 171      // TODO add other AlignedVector here
 172   case GFXSCT_Float2:
 173      if (size > sizeof(Point2F))
 174         size = pd.size;
 175   default:
 176      break;
 177   }
 178
 179   AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
 180
 181   // Ok, we only set data if it's different than the data we already have, this maybe more expensive than just setting the data, but 
 182   // we'll have to do some timings to see.  For example, the lighting shader constants rarely change, but we can't assume that at the
 183   // renderInstMgr level, but we can check down here. -BTR
 184   if (dMemcmp(basePointer + pd.offset, data, size) != 0)
 185   {
 186      dMemcpy(basePointer + pd.offset, data, size);
 187      return true;
 188   }
 189   return false;
 190}
 191
 192bool GFXD3D11ConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
 193{
 194   PROFILE_SCOPE(GFXD3D11ConstBufferLayout_setMatrix);
 195
 196   if (pd.constType == GFXSCT_Float4x4)
 197   {
 198      // Special case, we can just blast this guy.
 199      AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
 200      if (dMemcmp(basePointer+pd.offset, data, size) != 0)
 201      {
 202         dMemcpy(basePointer+pd.offset, data, size);         
 203         return true;
 204      }
 205
 206      return false;
 207   }
 208   else if (pd.constType == GFXSCT_Float4x3)
 209   {
 210      F32 buffer[4 * 4];
 211      const U32 csize = 48;
 212
 213      // Loop through and copy 
 214      bool ret = false;
 215      U8* currDestPointer = basePointer + pd.offset;
 216      const U8* currSourcePointer = static_cast<const U8*>(data);
 217      const U8* endData = currSourcePointer + size;
 218      while (currSourcePointer < endData)
 219      {
 220#ifdef TORQUE_DOUBLE_CHECK_43MATS
 221         Point4F col;
 222         ((MatrixF*)currSourcePointer)->getRow(3, &col);
 223         AssertFatal(col.x == 0.0f && col.y == 0.0f && col.z == 0.0f && col.w == 1.0f, "3rd row used");
 224#endif
 225
 226         if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0)
 227         {
 228            dMemcpy(currDestPointer, currSourcePointer, csize);
 229            ret = true;
 230         }
 231         else if (pd.constType == GFXSCT_Float4x3)
 232         {
 233            ret = true;
 234         }
 235
 236         currDestPointer += csize;
 237         currSourcePointer += sizeof(MatrixF);
 238      }
 239
 240      return ret;
 241   }
 242   else
 243   {
 244      PROFILE_SCOPE(GFXD3D11ConstBufferLayout_setMatrix_not4x4);
 245
 246      // Figure out how big of a chunk we are copying.  We're going to copy 4 columns by N rows of data
 247      U32 csize;
 248      switch (pd.constType)
 249      {
 250      case GFXSCT_Float2x2 :
 251         csize = 24; //this takes up 16+8
 252         break;
 253      case GFXSCT_Float3x3 : 
 254         csize = 44; //This takes up 16+16+12
 255         break;
 256      default:
 257         AssertFatal(false, "Unhandled case!");
 258         return false;
 259         break;
 260      }
 261
 262      // Loop through and copy 
 263      bool ret = false;
 264      U8* currDestPointer = basePointer+pd.offset;
 265      const U8* currSourcePointer = static_cast<const U8*>(data);
 266      const U8* endData = currSourcePointer + size;
 267      while (currSourcePointer < endData)
 268      {
 269         if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0)
 270         {
 271            dMemcpy(currDestPointer, currSourcePointer, csize);            
 272            ret = true;
 273         }
 274
 275         currDestPointer += csize;
 276         currSourcePointer += sizeof(MatrixF);
 277      }
 278
 279      return ret;
 280   }
 281}
 282
 283//------------------------------------------------------------------------------
 284GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader, 
 285                                                      GFXD3D11ConstBufferLayout* vertexLayout,
 286                                                      GFXD3D11ConstBufferLayout* pixelLayout)
 287{
 288    AssertFatal( shader, "GFXD3D11ShaderConstBuffer() - Got a null shader!" );
 289
 290    // We hold on to this so we don't have to call
 291    // this virtual method during activation.
 292    mShader = shader;
 293
 294    for (U32 i = 0; i < CBUFFER_MAX; ++i)
 295    {
 296       mConstantBuffersV[i] = NULL;
 297       mConstantBuffersP[i] = NULL;
 298    }
 299
 300    // TODO: Remove buffers and layouts that don't exist for performance?
 301    //Mandatory
 302    mVertexConstBufferLayout = vertexLayout;
 303    mVertexConstBuffer = new GenericConstBuffer(vertexLayout);
 304    
 305    mPixelConstBufferLayout = pixelLayout;
 306    mPixelConstBuffer = new GenericConstBuffer(pixelLayout);
 307
 308    _createBuffers();
 309   
 310}
 311
 312GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer()
 313{   
 314   // release constant buffer
 315   for (U32 i = 0; i < CBUFFER_MAX; ++i)
 316   {
 317      SAFE_RELEASE(mConstantBuffersP[i]);
 318      SAFE_RELEASE(mConstantBuffersV[i]);
 319   }
 320
 321   SAFE_DELETE(mVertexConstBuffer);
 322   SAFE_DELETE(mPixelConstBuffer);
 323
 324
 325   if ( mShader )
 326      mShader->_unlinkBuffer( this );
 327}
 328
 329void GFXD3D11ShaderConstBuffer::_createBuffers()
 330{
 331   HRESULT hr;
 332   // Create a vertex constant buffer
 333   if (mVertexConstBufferLayout->getBufferSize() > 0)
 334   {
 335      const Vector<ConstSubBufferDesc> &subBuffers = mVertexConstBufferLayout->getSubBufferDesc();
 336      for (U32 i = 0; i < subBuffers.size(); ++i)
 337      {
 338         D3D11_BUFFER_DESC cbDesc;
 339         cbDesc.ByteWidth = subBuffers[i].size;
 340         cbDesc.Usage = D3D11_USAGE_DEFAULT;
 341         cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
 342         cbDesc.CPUAccessFlags = 0;
 343         cbDesc.MiscFlags = 0;
 344         cbDesc.StructureByteStride = 0;
 345
 346         hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mConstantBuffersV[i]);
 347
 348         if (FAILED(hr))
 349         {
 350            AssertFatal(false, "can't create constant mConstantBuffersV!");
 351         }
 352      }
 353   }
 354
 355   // Create a pixel constant buffer
 356   if (mPixelConstBufferLayout->getBufferSize())
 357   {
 358      const Vector<ConstSubBufferDesc> &subBuffers = mPixelConstBufferLayout->getSubBufferDesc();
 359      for (U32 i = 0; i < subBuffers.size(); ++i)
 360      {
 361         // Create a pixel float constant buffer
 362         D3D11_BUFFER_DESC cbDesc;
 363         cbDesc.ByteWidth = subBuffers[i].size;
 364         cbDesc.Usage = D3D11_USAGE_DEFAULT;
 365         cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
 366         cbDesc.CPUAccessFlags = 0;
 367         cbDesc.MiscFlags = 0;
 368         cbDesc.StructureByteStride = 0;
 369
 370         hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mConstantBuffersP[i]);
 371
 372         if (FAILED(hr))
 373         {
 374            AssertFatal(false, "can't create constant mConstantBuffersP!");
 375         }
 376      }
 377   }
 378}
 379
 380GFXShader* GFXD3D11ShaderConstBuffer::getShader()
 381{
 382   return mShader;
 383}
 384
 385// This is kind of cheesy, but I don't think templates would work well here because 
 386// these functions potentially need to be handled differently by other derived types
 387template<class T>
 388inline void GFXD3D11ShaderConstBuffer::SET_CONSTANT(  GFXShaderConstHandle* handle, const T& fv,
 389                                                      GenericConstBuffer *vBuffer, GenericConstBuffer *pBuffer )
 390{
 391   AssertFatal(static_cast<const GFXD3D11ShaderConstHandle*>(handle), "Incorrect const buffer type!");
 392   const GFXD3D11ShaderConstHandle* h = static_cast<const GFXD3D11ShaderConstHandle*>(handle);
 393   AssertFatal(h, "Handle is NULL!" );
 394   AssertFatal(h->isValid(), "Handle is not valid!" );
 395   AssertFatal(!h->isSampler(), "Handle is sampler constant!" );
 396   AssertFatal(!mShader.isNull(), "Buffer's shader is null!" );
 397   AssertFatal(!h->mShader.isNull(), "Handle's shader is null!" );
 398   AssertFatal(h->mShader.getPointer() == mShader.getPointer(), "Mismatched shaders!");
 399
 400   if ( h->mInstancingConstant )
 401   {
 402      dMemcpy( mInstPtr+h->mPixelHandle.offset, &fv, sizeof( fv ) );
 403      return;
 404   }
 405   if (h->mVertexConstant)
 406      vBuffer->set(h->mVertexHandle, fv);
 407   if (h->mPixelConstant)
 408      pBuffer->set(h->mPixelHandle, fv);
 409}
 410
 411void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) 
 412{
 413   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 414}
 415
 416void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv) 
 417{ 
 418   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 419}
 420
 421void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv) 
 422{ 
 423   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 424}
 425
 426void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv) 
 427{ 
 428   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 429}
 430
 431void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv) 
 432{ 
 433   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 434}
 435
 436void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const ColorF& fv)
 437{ 
 438   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 439}
 440
 441void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 f)
 442{ 
 443   // This is the only type that is allowed to be used
 444   // with a sampler shader constant type, but it is only
 445   // allowed to be set from GLSL.
 446   //
 447   // So we ignore it here... all other cases will assert.
 448   //
 449   if ( ((GFXD3D11ShaderConstHandle*)handle)->isSampler() )
 450      return;
 451
 452   SET_CONSTANT(handle, f, mVertexConstBuffer, mPixelConstBuffer);
 453}
 454
 455void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2I& fv)
 456{ 
 457   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 458}
 459
 460void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3I& fv)
 461{ 
 462   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 463}
 464
 465void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4I& fv)
 466{ 
 467   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 468}
 469
 470void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv)
 471{ 
 472   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 473}
 474
 475void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv)
 476{ 
 477   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 478}
 479
 480void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv)
 481{ 
 482   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 483}
 484
 485void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv)
 486{ 
 487   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 488}
 489
 490void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv)
 491{ 
 492   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 493}
 494
 495void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv)
 496{ 
 497   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 498}
 499
 500void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv)
 501{ 
 502   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 503}
 504
 505void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv)
 506{ 
 507   SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer);
 508}
 509#undef SET_CONSTANT
 510
 511void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) 
 512{    
 513   AssertFatal(handle, "Handle is NULL!" );
 514   AssertFatal(handle->isValid(), "Handle is not valid!" );
 515
 516   AssertFatal(static_cast<const GFXD3D11ShaderConstHandle*>(handle), "Incorrect const buffer type!"); 
 517   const GFXD3D11ShaderConstHandle* h = static_cast<const GFXD3D11ShaderConstHandle*>(handle); 
 518   AssertFatal(!h->isSampler(), "Handle is sampler constant!" );
 519   AssertFatal(h->mShader == mShader, "Mismatched shaders!"); 
 520
 521   MatrixF transposed;
 522   if (matrixType == GFXSCT_Float4x3)
 523   {
 524      transposed = mat;
 525   }
 526   else
 527   {
 528      mat.transposeTo(transposed);
 529   }
 530
 531   if (h->mInstancingConstant) 
 532   {
 533      if ( matrixType == GFXSCT_Float4x4 )
 534         dMemcpy( mInstPtr+h->mPixelHandle.offset, mat, sizeof( mat ) );
 535         
 536      // TODO: Support 3x3 and 2x2 matricies?      
 537      return;
 538   }
 539
 540   if (h->mVertexConstant) 
 541      mVertexConstBuffer->set(h->mVertexHandle, transposed, matrixType); 
 542   if (h->mPixelConstant) 
 543      mPixelConstBuffer->set(h->mPixelHandle, transposed, matrixType);
 544}
 545
 546void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType)
 547{
 548   AssertFatal(handle, "Handle is NULL!" );
 549   AssertFatal(handle->isValid(), "Handle is not valid!" );
 550
 551   AssertFatal(static_cast<const GFXD3D11ShaderConstHandle*>(handle), "Incorrect const buffer type!"); 
 552   const GFXD3D11ShaderConstHandle* h = static_cast<const GFXD3D11ShaderConstHandle*>(handle); 
 553   AssertFatal(!h->isSampler(), "Handle is sampler constant!" );
 554   AssertFatal(h->mShader == mShader, "Mismatched shaders!"); 
 555
 556   static Vector<MatrixF> transposed;
 557   if (arraySize > transposed.size())
 558      transposed.setSize(arraySize);
 559
 560   if (matrixType == GFXSCT_Float4x3)
 561   {
 562      dMemcpy(transposed.address(), mat, arraySize * sizeof(MatrixF));
 563   }
 564   else
 565   {
 566      for (U32 i = 0; i < arraySize; i++)
 567         mat[i].transposeTo(transposed[i]);
 568   }
 569
 570   // TODO: Maybe support this in the future?
 571   if (h->mInstancingConstant) 
 572      return;
 573
 574   if (h->mVertexConstant) 
 575      mVertexConstBuffer->set(h->mVertexHandle, transposed.begin(), arraySize, matrixType);
 576   if (h->mPixelConstant) 
 577      mPixelConstBuffer->set(h->mPixelHandle, transposed.begin(), arraySize, matrixType);
 578}
 579
 580const String GFXD3D11ShaderConstBuffer::describeSelf() const
 581{
 582   String ret;
 583   ret = String("   GFXD3D11ShaderConstBuffer\n");
 584
 585   for (U32 i = 0; i < mVertexConstBufferLayout->getParameterCount(); i++)
 586   {
 587      GenericConstBufferLayout::ParamDesc pd;
 588      mVertexConstBufferLayout->getDesc(i, pd);
 589
 590      ret += String::ToString("      Constant name: %s", pd.name);
 591   }
 592
 593   return ret;
 594}
 595
 596void GFXD3D11ShaderConstBuffer::zombify()
 597{
 598}
 599
 600void GFXD3D11ShaderConstBuffer::resurrect()
 601{
 602}
 603
 604bool GFXD3D11ShaderConstBuffer::isDirty()
 605{
 606   bool ret = mVertexConstBuffer->isDirty();
 607   ret |= mPixelConstBuffer->isDirty();
 608 
 609   return ret;
 610}
 611
 612void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer )
 613{
 614   PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate);
 615
 616   // NOTE: This is a really critical function as it gets
 617   // called between every draw call to update the constants.
 618   //
 619   // Alot of the calls here are inlined... be careful 
 620   // what you change.
 621
 622   // If the buffer has changed we need to compare it
 623   // with the new buffer to see if we can skip copying
 624   // equal buffer content.
 625   //
 626   // If the buffer hasn't changed then we only will
 627   // be copying the changes that have occured since
 628   // the last activate call.
 629   if ( prevShaderBuffer != this )
 630   {
 631      // If the previous buffer is dirty, than we can't compare 
 632      // against it, because it hasn't sent its contents to the
 633      // card yet and must be copied.
 634      if ( prevShaderBuffer && !prevShaderBuffer->isDirty() )
 635      {
 636         PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate_dirty_check_1);
 637         // If the buffer content is equal then we set the dirty
 638         // flag to false knowing the current state of the card matches
 639         // the new buffer.
 640         //
 641         // If the content is not equal we set the dirty flag to
 642         // true which causes the full content of the buffer to be
 643         // copied to the card.
 644         //
 645         mVertexConstBuffer->setDirty( !prevShaderBuffer->mVertexConstBuffer->isEqual( mVertexConstBuffer ) );
 646         mPixelConstBuffer->setDirty( !prevShaderBuffer->mPixelConstBuffer->isEqual( mPixelConstBuffer ) ); 
 647      } 
 648      else
 649      {
 650         // This happens rarely... but it can happen.
 651         // We copy the entire dirty state to the card.
 652         PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate_dirty_check_2);
 653
 654         mVertexConstBuffer->setDirty( true );
 655         mPixelConstBuffer->setDirty( true );
 656      }      
 657   }
 658
 659   ID3D11DeviceContext* devCtx = D3D11DEVICECONTEXT;
 660
 661   D3D11_MAPPED_SUBRESOURCE pConstData;
 662   ZeroMemory(&pConstData, sizeof(D3D11_MAPPED_SUBRESOURCE));
 663   
 664   const U8* buf;
 665   U32 nbBuffers = 0;
 666   if(mVertexConstBuffer->isDirty())
 667   {
 668      const Vector<ConstSubBufferDesc> &subBuffers = mVertexConstBufferLayout->getSubBufferDesc();
 669      // TODO: This is not very effecient updating the whole lot, re-implement the dirty system to work with multiple constant buffers.
 670      // TODO: Implement DX 11.1 UpdateSubresource1 which supports updating ranges with constant buffers
 671      buf = mVertexConstBuffer->getEntireBuffer();
 672      for (U32 i = 0; i < subBuffers.size(); ++i)
 673      {
 674         const ConstSubBufferDesc &desc = subBuffers[i];
 675         devCtx->UpdateSubresource(mConstantBuffersV[i], 0, NULL, buf + desc.start, desc.size, 0);
 676         nbBuffers++;
 677      }
 678
 679      devCtx->VSSetConstantBuffers(0, nbBuffers, mConstantBuffersV);
 680   }
 681
 682   nbBuffers = 0;
 683
 684   if(mPixelConstBuffer->isDirty())    
 685   {
 686      const Vector<ConstSubBufferDesc> &subBuffers = mPixelConstBufferLayout->getSubBufferDesc();
 687      // TODO: This is not very effecient updating the whole lot, re-implement the dirty system to work with multiple constant buffers.
 688      // TODO: Implement DX 11.1 UpdateSubresource1 which supports updating ranges with constant buffers
 689      buf = mPixelConstBuffer->getEntireBuffer();
 690      for (U32 i = 0; i < subBuffers.size(); ++i)
 691      {
 692         const ConstSubBufferDesc &desc = subBuffers[i];
 693         devCtx->UpdateSubresource(mConstantBuffersP[i], 0, NULL, buf + desc.start, desc.size, 0);
 694         nbBuffers++;
 695      }
 696
 697      devCtx->PSSetConstantBuffers(0, nbBuffers, mConstantBuffersP);
 698   }
 699
 700   #ifdef TORQUE_DEBUG
 701      // Make sure all the constants for this buffer were assigned.
 702      if(mWasLost)
 703      {
 704         mVertexConstBuffer->assertUnassignedConstants( mShader->getVertexShaderFile().c_str() );
 705         mPixelConstBuffer->assertUnassignedConstants( mShader->getPixelShaderFile().c_str() );        
 706      }
 707   #endif
 708
 709   // Clear the lost state.
 710   mWasLost = false;
 711}
 712
 713void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader )
 714{
 715   AssertFatal( shader == mShader, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" );
 716
 717   // release constant buffers
 718   for (U32 i = 0; i < CBUFFER_MAX; ++i)
 719   {
 720      SAFE_RELEASE(mConstantBuffersP[i]);
 721      SAFE_RELEASE(mConstantBuffersV[i]);
 722   }
 723
 724   SAFE_DELETE( mVertexConstBuffer );
 725   SAFE_DELETE( mPixelConstBuffer );
 726        
 727   AssertFatal( mVertexConstBufferLayout == shader->mVertexConstBufferLayout, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" );
 728   AssertFatal( mPixelConstBufferLayout == shader->mPixelConstBufferLayout, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" );
 729
 730   mVertexConstBuffer = new GenericConstBuffer( mVertexConstBufferLayout );      
 731   mPixelConstBuffer = new GenericConstBuffer( mPixelConstBufferLayout ); 
 732  
 733   _createBuffers();
 734   
 735   // Set the lost state.
 736   mWasLost = true;
 737}
 738
 739//------------------------------------------------------------------------------
 740
 741GFXD3D11Shader::GFXD3D11Shader()
 742{
 743   VECTOR_SET_ASSOCIATION( mShaderConsts );
 744
 745   AssertFatal(D3D11DEVICE, "Invalid device for shader.");
 746   mVertShader = NULL;
 747   mPixShader = NULL;
 748   mVertexConstBufferLayout = NULL;
 749   mPixelConstBufferLayout = NULL;
 750
 751   if( smD3DInclude == NULL )
 752      smD3DInclude = new gfxD3D11Include;
 753}
 754
 755//------------------------------------------------------------------------------
 756
 757GFXD3D11Shader::~GFXD3D11Shader()
 758{
 759   for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++)
 760      delete i->value;
 761
 762   // delete const buffer layouts
 763   SAFE_DELETE(mVertexConstBufferLayout);
 764   SAFE_DELETE(mPixelConstBufferLayout);
 765
 766   // release shaders
 767   SAFE_RELEASE(mVertShader);
 768   SAFE_RELEASE(mPixShader);
 769   //maybe add SAFE_RELEASE(mVertexCode) ?
 770}
 771
 772bool GFXD3D11Shader::_init()
 773{
 774   PROFILE_SCOPE( GFXD3D11Shader_Init );
 775
 776   SAFE_RELEASE(mVertShader);
 777   SAFE_RELEASE(mPixShader);
 778
 779   // Create the macro array including the system wide macros.
 780   const U32 macroCount = smGlobalMacros.size() + mMacros.size() + 2;
 781   FrameTemp<D3D_SHADER_MACRO> d3dMacros( macroCount );
 782
 783   for ( U32 i=0; i < smGlobalMacros.size(); i++ )
 784   {
 785      d3dMacros[i].Name = smGlobalMacros[i].name.c_str();
 786      d3dMacros[i].Definition = smGlobalMacros[i].value.c_str();
 787   }
 788
 789   for ( U32 i=0; i < mMacros.size(); i++ )
 790   {
 791      d3dMacros[i+smGlobalMacros.size()].Name = mMacros[i].name.c_str();
 792      d3dMacros[i+smGlobalMacros.size()].Definition = mMacros[i].value.c_str();
 793   }
 794
 795   //TODO support D3D_FEATURE_LEVEL properly with shaders instead of hard coding at hlsl 5
 796   d3dMacros[macroCount - 2].Name = "TORQUE_SM";
 797   d3dMacros[macroCount - 2].Definition = "50";
 798
 799   memset(&d3dMacros[macroCount - 1], 0, sizeof(D3D_SHADER_MACRO));
 800
 801   if ( !mVertexConstBufferLayout )
 802      mVertexConstBufferLayout = new GFXD3D11ConstBufferLayout();
 803   else
 804      mVertexConstBufferLayout->clear();
 805
 806   if ( !mPixelConstBufferLayout )
 807      mPixelConstBufferLayout = new GFXD3D11ConstBufferLayout();
 808   else
 809      mPixelConstBufferLayout->clear(); 
 810
 811   
 812   mSamplerDescriptions.clear();
 813   mShaderConsts.clear();
 814
 815   if ( !Con::getBoolVariable( "$shaders::forceLoadCSF", false ) )
 816   {
 817      if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, "vs_5_0", d3dMacros, mVertexConstBufferLayout, mSamplerDescriptions ) )
 818         return false;
 819
 820      if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, "ps_5_0", d3dMacros, mPixelConstBufferLayout, mSamplerDescriptions ) )
 821         return false;
 822
 823   } 
 824   else 
 825   {
 826      if ( !_loadCompiledOutput( mVertexFile, "vs_5_0", mVertexConstBufferLayout, mSamplerDescriptions ) )
 827      {
 828         if ( smLogErrors )
 829            Con::errorf( "GFXD3D11Shader::init - Unable to load precompiled vertex shader for '%s'.",  mVertexFile.getFullPath().c_str() );
 830
 831         return false;
 832      }
 833
 834      if ( !_loadCompiledOutput( mPixelFile, "ps_5_0", mPixelConstBufferLayout, mSamplerDescriptions ) )
 835      {
 836         if ( smLogErrors )
 837            Con::errorf( "GFXD3D11Shader::init - Unable to load precompiled pixel shader for '%s'.",  mPixelFile.getFullPath().c_str() );
 838
 839         return false;
 840      }
 841   }
 842
 843   // Existing handles are resored to an uninitialized state.
 844   // Those that are found when parsing the layout parameters
 845   // will then be re-initialized.
 846   HandleMap::Iterator iter = mHandles.begin();
 847   for ( ; iter != mHandles.end(); iter++ )        
 848      (iter->value)->clear();      
 849
 850   _buildShaderConstantHandles(mVertexConstBufferLayout, true);
 851   _buildShaderConstantHandles(mPixelConstBufferLayout, false);
 852
 853   _buildSamplerShaderConstantHandles( mSamplerDescriptions );
 854   _buildInstancingShaderConstantHandles();
 855
 856   // Notify any existing buffers that the buffer 
 857   // layouts have changed and they need to update.
 858   Vector<GFXShaderConstBuffer*>::iterator biter = mActiveBuffers.begin();
 859   for ( ; biter != mActiveBuffers.end(); biter++ )
 860      ((GFXD3D11ShaderConstBuffer*)(*biter))->onShaderReload( this );
 861
 862   return true;
 863}
 864
 865bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, 
 866                                    const String& target,                                  
 867                                    const D3D_SHADER_MACRO *defines, 
 868                                    GenericConstBufferLayout* bufferLayout,
 869                                    Vector<GFXShaderConstDesc> &samplerDescriptions )
 870{
 871   PROFILE_SCOPE( GFXD3D11Shader_CompileShader );
 872
 873   using namespace Torque;
 874
 875   HRESULT res = E_FAIL;
 876   ID3DBlob* code = NULL;
 877   ID3DBlob* errorBuff = NULL;
 878   ID3D11ShaderReflection* reflectionTable = NULL;
 879
 880#ifdef TORQUE_DEBUG
 881   U32 flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS;
 882#else
 883   U32 flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_OPTIMIZATION_LEVEL3; //TODO double check load times with D3DCOMPILE_OPTIMIZATION_LEVEL3
 884   //recommended flags for NSight, uncomment to use. NSight should be used in release mode only. *Still works with above flags however
 885   //flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PREFER_FLOW_CONTROL | D3DCOMPILE_SKIP_OPTIMIZATION;
 886#endif
 887
 888#ifdef D3D11_DEBUG_SPEW
 889   Con::printf( "Compiling Shader: '%s'", filePath.getFullPath().c_str() );
 890#endif
 891
 892   // Is it an HLSL shader?
 893   if(filePath.getExtension().equal("hlsl", String::NoCase))   
 894   {
 895      // Set this so that the D3DInclude::Open will have this 
 896      // information for relative paths.
 897      smD3DInclude->setPath(filePath.getRootAndPath());
 898
 899      FileStream s;
 900      if (!s.open(filePath, Torque::FS::File::Read))
 901      {
 902         AssertISV(false, avar("GFXD3D11Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str()));
 903
 904         if ( smLogErrors )
 905            Con::errorf( "GFXD3D11Shader::_compileShader - Failed to open shader file '%s'.", filePath.getFullPath().c_str() );
 906
 907         return false;
 908      }
 909
 910      // Convert the path which might have virtualized
 911      // mount paths to a real file system path.
 912      Torque::Path realPath;
 913      if (!FS::GetFSPath( filePath, realPath))
 914         realPath = filePath;
 915
 916      U32 bufSize = s.getStreamSize();
 917
 918      FrameAllocatorMarker fam;
 919      char *buffer = NULL;
 920
 921      buffer = (char*)fam.alloc(bufSize + 1);
 922      s.read(bufSize, buffer);
 923      buffer[bufSize] = 0;
 924
 925      res = D3DCompile(buffer, bufSize, realPath.getFullPath().c_str(), defines, smD3DInclude, "main", target, flags, 0, &code, &errorBuff);
 926      
 927   }
 928
 929   // Is it a precompiled obj shader?
 930   else if(filePath.getExtension().equal("obj", String::NoCase))
 931   {     
 932      FileStream  s;
 933      if(!s.open(filePath, Torque::FS::File::Read))
 934      {
 935         AssertISV(false, avar("GFXD3D11Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str()));
 936
 937         if ( smLogErrors )
 938            Con::errorf( "GFXD3D11Shader::_compileShader - Failed to open shader file '%s'.", filePath.getFullPath().c_str() );
 939
 940         return false;
 941      }
 942
 943     res = D3DCreateBlob(s.getStreamSize(), &code);
 944      AssertISV(SUCCEEDED(res), "Unable to create buffer!");
 945      s.read(s.getStreamSize(), code->GetBufferPointer());
 946   }
 947   else
 948   {
 949      if (smLogErrors)
 950         Con::errorf("GFXD3D11Shader::_compileShader - Unsupported shader file type '%s'.", filePath.getFullPath().c_str());
 951
 952      return false;
 953   }  
 954
 955   if(errorBuff)
 956   {
 957      // remove \n at end of buffer
 958      U8 *buffPtr = (U8*) errorBuff->GetBufferPointer();
 959      U32 len = dStrlen( (const char*) buffPtr );
 960      buffPtr[len-1] = '\0';
 961
 962      if(FAILED(res))
 963      {
 964         if(smLogErrors)
 965          Con::errorf("failed to compile shader: %s", buffPtr);
 966      }
 967      else
 968      {
 969         if(smLogWarnings)
 970            Con::errorf("shader compiled with warning(s): %s", buffPtr);
 971      }
 972   }
 973   else if (code == NULL && smLogErrors)
 974      Con::errorf( "GFXD3D11Shader::_compileShader - no compiled code produced; possibly missing file '%s'.", filePath.<a href="/coding/class/classtorque_1_1path/#classtorque_1_1path_1a08894ee3216bc5cf73c2eb349d5a1013">getFullPath</a>().<a href="/coding/class/classstring/#classstring_1a913f981aed18482b10eba444ae6193db">c_str</a>() );
 975
 976   AssertISV(SUCCEEDED(res), "Unable to compile shader!");
 977
 978   if(code != NULL)
 979   {
 980#ifndef TORQUE_SHIPPING         
 981
 982         if(gDisassembleAllShaders)
 983         {
 984            ID3DBlob* disassem = NULL;
 985            D3DDisassemble(code->GetBufferPointer(), code->GetBufferSize(), 0, NULL, &disassem);
 986            mDissasembly = (const char*)disassem->GetBufferPointer();
 987
 988            String filename = filePath.getFullPath();
 989            filename.replace( ".hlsl", "_dis.txt" );
 990
 991            FileStream *fstream = FileStream::createAndOpen( filename, Torque::FS::File::Write );
 992            if ( fstream )
 993            {            
 994               fstream->write( mDissasembly );
 995               fstream->close();
 996               delete fstream;   
 997            }
 998
 999            SAFE_RELEASE(disassem);
1000         }         
1001
1002#endif
1003
1004         if (target.compare("ps_", 3) == 0)      
1005            res = D3D11DEVICE->CreatePixelShader(code->GetBufferPointer(), code->GetBufferSize(), NULL,  &mPixShader);
1006         else if (target.compare("vs_", 3) == 0)
1007            res = D3D11DEVICE->CreateVertexShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mVertShader);
1008         
1009         if (FAILED(res))
1010         {
1011            AssertFatal(false, "D3D11Shader::_compilershader- failed to create shader");
1012         }
1013
1014         if(res == S_OK){
1015            HRESULT reflectionResult = D3DReflect(code->GetBufferPointer(), code->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflectionTable);
1016         if(FAILED(reflectionResult))
1017            AssertFatal(false, "D3D11Shader::_compilershader - Failed to get shader reflection table interface");
1018     }
1019
1020     if(res == S_OK)
1021      _getShaderConstants(reflectionTable, bufferLayout, samplerDescriptions);     
1022
1023#ifdef TORQUE_ENABLE_CSF_GENERATION
1024
1025      // Ok, we've got a valid shader and constants, let's write them all out.
1026      if (!_saveCompiledOutput(filePath, code, bufferLayout) && smLogErrors)
1027         Con::errorf( "GFXD3D11Shader::_compileShader - Unable to save shader compile output for: %s", 
1028            filePath.getFullPath().c_str());
1029#endif
1030
1031      if(FAILED(res) && smLogErrors)
1032         Con::errorf("GFXD3D11Shader::_compileShader - Unable to create shader for '%s'.", filePath.getFullPath().c_str());
1033   }
1034
1035   //bool result = code && SUCCEEDED(res) && HasValidConstants;
1036   bool result = code && SUCCEEDED(res);
1037
1038#ifdef TORQUE_DEBUG
1039   if (target.compare("vs_", 3) == 0)
1040   {
1041      String vertShader = mVertexFile.getFileName();
1042      mVertShader->SetPrivateData(WKPDID_D3DDebugObjectName, vertShader.size(), vertShader.c_str());
1043   }
1044   else if (target.compare("ps_", 3) == 0)
1045   {
1046      String pixelShader = mPixelFile.getFileName();
1047      mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, pixelShader.size(), pixelShader.c_str());
1048   }
1049#endif
1050  
1051   SAFE_RELEASE(code); 
1052   SAFE_RELEASE(reflectionTable);
1053   SAFE_RELEASE(errorBuff);
1054
1055   return result;
1056}
1057void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *table, 
1058                                         GenericConstBufferLayout *bufferLayoutIn,
1059                                         Vector<GFXShaderConstDesc> &samplerDescriptions )
1060{
1061   PROFILE_SCOPE( GFXD3D11Shader_GetShaderConstants );
1062
1063   AssertFatal(table, "NULL constant table not allowed, is this an assembly shader?");
1064
1065   GFXD3D11ConstBufferLayout *bufferLayout = (GFXD3D11ConstBufferLayout*)bufferLayoutIn;
1066   Vector<ConstSubBufferDesc> &subBuffers = bufferLayout->getSubBufferDesc();
1067   subBuffers.clear();
1068
1069   D3D11_SHADER_DESC tableDesc;
1070   HRESULT hr = table->GetDesc(&tableDesc);
1071   if (FAILED(hr))
1072   {
1073      AssertFatal(false, "Shader Reflection table unable to be created");
1074   }
1075   
1076   //offset for sub constant buffers
1077   U32 bufferOffset = 0;
1078   for (U32 i = 0; i < tableDesc.ConstantBuffers; i++)
1079   {
1080      ID3D11ShaderReflectionConstantBuffer* constantBuffer = table->GetConstantBufferByIndex(i);
1081      D3D11_SHADER_BUFFER_DESC constantBufferDesc;
1082
1083      if (constantBuffer->GetDesc(&constantBufferDesc) == S_OK)
1084      {
1085
1086   #ifdef TORQUE_DEBUG
1087         AssertFatal(constantBufferDesc.Type == D3D_CT_CBUFFER, "Only scalar cbuffers supported for now.");
1088
1089         if (dStrcmp(constantBufferDesc.Name, "$Globals") != 0 && dStrcmp(constantBufferDesc.Name, "$Params") != 0)
1090            AssertFatal(false, "Only $Global and $Params cbuffer supported for now.");
1091   #endif
1092   #ifdef D3D11_DEBUG_SPEW
1093         Con::printf("Constant Buffer Name: %s", constantBufferDesc.Name);
1094   #endif 
1095         
1096         for(U32 j =0; j< constantBufferDesc.Variables; j++)
1097         {
1098            GFXShaderConstDesc desc;
1099            ID3D11ShaderReflectionVariable* variable = constantBuffer->GetVariableByIndex(j); 
1100            D3D11_SHADER_VARIABLE_DESC variableDesc;
1101            D3D11_SHADER_TYPE_DESC variableTypeDesc;
1102
1103            variable->GetDesc(&variableDesc);
1104
1105            ID3D11ShaderReflectionType* variableType =variable->GetType();
1106
1107            variableType->GetDesc(&variableTypeDesc);
1108            desc.name = String(variableDesc.Name);
1109            // Prepend a "$" if it doesn't exist.  Just to make things consistent.
1110            if (desc.name.find("$") != 0)
1111               desc.name = String::ToString("$%s", desc.name.c_str());
1112
1113            bool unusedVar = variableDesc.uFlags & D3D_SVF_USED ? false : true;
1114
1115            if (variableTypeDesc.Elements == 0)
1116               desc.arraySize = 1;
1117            else
1118               desc.arraySize = variableTypeDesc.Elements;
1119
1120   #ifdef D3D11_DEBUG_SPEW
1121            Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", desc.name.c_str(), variableDesc.StartOffset, variableDesc.Size, desc.arraySize);
1122   #endif           
1123            if (_convertShaderVariable(variableTypeDesc, desc))
1124            {
1125               //The HLSL compiler for 4.0 and above doesn't strip out unused registered constants. We'll have to do it manually
1126               if (!unusedVar)
1127               {
1128                  mShaderConsts.push_back(desc);
1129                  U32 alignBytes = getAlignmentValue(desc.constType);
1130                  U32 paramSize = variableDesc.Size;
1131                  bufferLayout->addParameter(   desc.name,
1132                                                desc.constType,
1133                                                variableDesc.StartOffset + bufferOffset,
1134                                                paramSize,
1135                                                desc.arraySize,
1136                                                alignBytes);
1137
1138               } //unusedVar
1139            } //_convertShaderVariable
1140         } //constantBufferDesc.Variables
1141
1142         // fill out our const sub buffer sizes etc
1143         ConstSubBufferDesc subBufferDesc;
1144         subBufferDesc.size = constantBufferDesc.Size;
1145         subBufferDesc.start = bufferOffset;
1146         subBuffers.push_back(subBufferDesc);
1147         // increase our bufferOffset by the constant buffer size
1148         bufferOffset += constantBufferDesc.Size;
1149
1150      }
1151      else
1152         AssertFatal(false, "Unable to get shader constant description! (may need more elements of constantDesc");   
1153   }
1154
1155   // Set buffer size to the aligned size
1156   bufferLayout->setSize(bufferOffset);
1157
1158
1159   //get the sampler descriptions from the resource binding description
1160   U32 resourceCount = tableDesc.BoundResources;
1161   for (U32 i = 0; i < resourceCount; i++)
1162   {
1163      GFXShaderConstDesc desc;
1164      D3D11_SHADER_INPUT_BIND_DESC bindDesc;
1165      table->GetResourceBindingDesc(i, &bindDesc);
1166
1167      switch (bindDesc.Type)
1168      {
1169      case D3D_SIT_SAMPLER:
1170         // Prepend a "$" if it doesn't exist.  Just to make things consistent.
1171         desc.name = String(bindDesc.Name);
1172         if (desc.name.find("$") != 0)
1173            desc.name = String::ToString("$%s", desc.name.c_str());
1174         desc.constType = GFXSCT_Sampler;
1175         desc.arraySize = bindDesc.BindPoint;
1176         samplerDescriptions.push_back(desc);
1177         break;
1178
1179      }
1180   }
1181
1182}
1183
1184bool GFXD3D11Shader::_convertShaderVariable(const D3D11_SHADER_TYPE_DESC &typeDesc, GFXShaderConstDesc &desc)
1185{
1186   switch (typeDesc.Type)
1187   {
1188   case D3D_SVT_INT:
1189   {
1190      switch (typeDesc.Class)
1191      {
1192      case D3D_SVC_SCALAR:
1193         desc.constType = GFXSCT_Int;
1194         break;
1195      case D3D_SVC_VECTOR:
1196      {
1197         switch (typeDesc.Columns)
1198         {
1199         case 1:
1200            desc.constType = GFXSCT_Int;
1201            break;
1202         case 2:
1203            desc.constType = GFXSCT_Int2;
1204            break;
1205         case 3:
1206            desc.constType = GFXSCT_Int3;
1207            break;
1208         case 4:
1209            desc.constType = GFXSCT_Int4;
1210            break;
1211         }
1212      }
1213      break;
1214      }
1215      break;
1216   }   
1217   case D3D_SVT_FLOAT:
1218   {
1219      switch (typeDesc.Class)
1220      {
1221      case D3D_SVC_SCALAR:
1222         desc.constType = GFXSCT_Float;
1223         break;
1224      case D3D_SVC_VECTOR:
1225      {
1226         switch (typeDesc.Columns)
1227         {
1228         case 1:
1229            desc.constType = GFXSCT_Float;
1230            break;
1231         case 2:
1232            desc.constType = GFXSCT_Float2;
1233            break;
1234         case 3:
1235            desc.constType = GFXSCT_Float3;
1236            break;
1237         case 4:
1238            desc.constType = GFXSCT_Float4;
1239            break;
1240         }
1241      }
1242      break;
1243      case D3D_SVC_MATRIX_ROWS:
1244      case D3D_SVC_MATRIX_COLUMNS:
1245      {
1246         switch (typeDesc.Rows)
1247         {
1248         case 3:
1249            desc.constType = typeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3;
1250            break;
1251         case 4:
1252            desc.constType = typeDesc.Columns == 3 ? GFXSCT_Float4x3 : GFXSCT_Float4x4;
1253            break;
1254         }
1255      }
1256      break;
1257      case D3D_SVC_OBJECT:
1258      case D3D_SVC_STRUCT:
1259         return false;
1260      }
1261   }
1262   break;
1263
1264   default:
1265      AssertFatal(false, "Unknown shader constant class enum");
1266      break;
1267   }
1268
1269   return true;
1270}
1271
1272const U32 GFXD3D11Shader::smCompiledShaderTag = MakeFourCC('t','c','s','f');
1273
1274bool GFXD3D11Shader::_saveCompiledOutput( const Torque::Path &filePath, 
1275                                         ID3DBlob *buffer, 
1276                                         GenericConstBufferLayout *bufferLayout,
1277                                         Vector<GFXShaderConstDesc> &samplerDescriptions )
1278{
1279   Torque::Path outputPath(filePath);
1280   outputPath.setExtension("csf");     // "C"ompiled "S"hader "F"ile (fancy!)
1281
1282   FileStream f;
1283   if (!f.open(outputPath, Torque::FS::File::Write))
1284      return false;
1285   if (!f.write(smCompiledShaderTag))
1286      return false;
1287   // We could reverse engineer the structure in the compiled output, but this
1288   // is a bit easier because we can just read it into the struct that we want.
1289   if (!bufferLayout->write(&f))
1290      return false;
1291
1292   U32 bufferSize = buffer->GetBufferSize();
1293   if (!f.write(bufferSize))
1294      return false;
1295   if (!f.write(bufferSize, buffer->GetBufferPointer()))
1296      return false;
1297
1298   // Write out sampler descriptions.
1299
1300   f.write( samplerDescriptions.size() );   
1301
1302   for ( U32 i = 0; i < samplerDescriptions.size(); i++ )
1303   {
1304      f.write( samplerDescriptions[i].name );
1305      f.write( (U32)(samplerDescriptions[i].constType) );
1306      f.write( samplerDescriptions[i].arraySize );
1307   }
1308
1309   f.close();
1310
1311   return true;
1312}
1313
1314bool GFXD3D11Shader::_loadCompiledOutput( const Torque::Path &filePath, 
1315                                         const String &target, 
1316                                         GenericConstBufferLayout *bufferLayout,
1317                                         Vector<GFXShaderConstDesc> &samplerDescriptions )
1318{
1319   Torque::Path outputPath(filePath);
1320   outputPath.setExtension("csf");     // "C"ompiled "S"hader "F"ile (fancy!)
1321
1322   FileStream f;
1323   if (!f.open(outputPath, Torque::FS::File::Read))
1324      return false;
1325   U32 fileTag;
1326   if (!f.read(&fileTag))
1327      return false;
1328   if (fileTag != smCompiledShaderTag)
1329      return false;
1330   if (!bufferLayout->read(&f))
1331      return false;
1332   U32 bufferSize;
1333   if (!f.read(&bufferSize))
1334      return false;
1335   U32 waterMark = FrameAllocator::getWaterMark();
1336   DWORD* buffer = static_cast<DWORD*>(FrameAllocator::alloc(bufferSize));
1337   if (!f.read(bufferSize, buffer))
1338      return false;
1339
1340   // Read sampler descriptions.
1341
1342   U32 samplerCount;
1343   f.read( &samplerCount );   
1344
1345   for ( U32 i = 0; i < samplerCount; i++ )
1346   {
1347      GFXShaderConstDesc samplerDesc;
1348      f.read( &(samplerDesc.name) );
1349      f.read( (U32*)&(samplerDesc.constType) );
1350      f.read( &(samplerDesc.arraySize) );
1351
1352      samplerDescriptions.push_back( samplerDesc );
1353   }
1354
1355   f.close();
1356
1357   HRESULT res;
1358   if (target.compare("ps_", 3) == 0)      
1359      res = D3D11DEVICE->CreatePixelShader(buffer, bufferSize, NULL, &mPixShader);
1360   else
1361      res = D3D11DEVICE->CreateVertexShader(buffer, bufferSize, NULL, &mVertShader);
1362   AssertFatal(SUCCEEDED(res), "Unable to load shader!");
1363
1364   FrameAllocator::setWaterMark(waterMark);
1365   return SUCCEEDED(res);
1366}
1367
1368void GFXD3D11Shader::_buildShaderConstantHandles(GenericConstBufferLayout* layout, bool vertexConst)
1369{                     
1370   for (U32 i = 0; i < layout->getParameterCount(); i++)
1371   {
1372      GenericConstBufferLayout::ParamDesc pd;
1373      layout->getDesc(i, pd);
1374
1375      GFXD3D11ShaderConstHandle* handle;
1376      HandleMap::Iterator j = mHandles.find(pd.name);
1377
1378      if (j != mHandles.end())
1379      {
1380         handle = j->value;         
1381         handle->mShader = this;
1382         handle->setValid( true );
1383      } 
1384      else
1385      {
1386         handle = new GFXD3D11ShaderConstHandle();
1387         handle->mShader = this;
1388         mHandles[pd.name] = handle;
1389         handle->setValid( true );
1390      }
1391
1392      if (vertexConst)
1393      {
1394         handle->mVertexConstant = true;
1395         handle->mVertexHandle = pd;
1396      }
1397      else
1398      {
1399         handle->mPixelConstant = true;
1400         handle->mPixelHandle = pd;
1401      }
1402   }
1403}
1404
1405void GFXD3D11Shader::_buildSamplerShaderConstantHandles( Vector<GFXShaderConstDesc> &samplerDescriptions )
1406{                     
1407   Vector<GFXShaderConstDesc>::iterator iter = samplerDescriptions.begin();
1408   for ( ; iter != samplerDescriptions.end(); iter++ )
1409   {
1410      const GFXShaderConstDesc &desc = *iter;
1411
1412      AssertFatal(   desc.constType == GFXSCT_Sampler || 
1413                     desc.constType == GFXSCT_SamplerCube, 
1414                     "GFXD3D11Shader::_buildSamplerShaderConstantHandles - Invalid samplerDescription type!" );
1415
1416      GFXD3D11ShaderConstHandle *handle;
1417      HandleMap::Iterator j = mHandles.find(desc.name);
1418
1419      if ( j != mHandles.end() )
1420         handle = j->value;
1421      else
1422      {
1423         handle = new GFXD3D11ShaderConstHandle();
1424         mHandles[desc.name] = handle;         
1425      }
1426
1427      handle->mShader = this;         
1428      handle->setValid( true );         
1429      handle->mPixelConstant = true;
1430      handle->mPixelHandle.name = desc.name;
1431      handle->mPixelHandle.constType = desc.constType;
1432      handle->mPixelHandle.offset = desc.arraySize;         
1433   }
1434}
1435
1436void GFXD3D11Shader::_buildInstancingShaderConstantHandles()
1437{
1438   // If we have no instancing than just return
1439   if (!mInstancingFormat)
1440      return;
1441
1442   U32 offset = 0;
1443   for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ )
1444   {
1445      const GFXVertexElement &element = mInstancingFormat->getElement( i );
1446      
1447      String constName = String::ToString( "$%s", element.getSemantic().c_str() );
1448
1449      GFXD3D11ShaderConstHandle *handle;
1450      HandleMap::Iterator j = mHandles.find( constName );
1451
1452      if ( j != mHandles.end() )
1453         handle = j->value; 
1454      else
1455      {
1456         handle = new GFXD3D11ShaderConstHandle();
1457         mHandles[ constName ] = handle;         
1458      }
1459
1460      handle->mShader = this;
1461      handle->setValid( true );         
1462      handle->mInstancingConstant = true;
1463
1464      // We shouldn't have an instancing constant that is also 
1465      // a vertex or pixel constant!  This means the shader features
1466      // are confused as to what is instanced.
1467      //
1468      AssertFatal(   !handle->mVertexConstant &&
1469                     !handle->mPixelConstant,
1470                     "GFXD3D11Shader::_buildInstancingShaderConstantHandles - Bad instanced constant!" );
1471
1472      // HACK:  The GFXD3D11ShaderConstHandle will check mVertexConstant then
1473      // fall back to reading the mPixelHandle values.  We depend on this here
1474      // and store the data we need in the mPixelHandle constant although its
1475      // not a pixel shader constant.
1476      //
1477      handle->mPixelHandle.name = constName;
1478      handle->mPixelHandle.offset = offset;
1479
1480      // If this is a matrix we will have 2 or 3 more of these
1481      // semantics with the same name after it.
1482      for ( ; i < mInstancingFormat->getElementCount(); i++ )
1483      {
1484         const GFXVertexElement &nextElement = mInstancingFormat->getElement( i );
1485         if ( nextElement.getSemantic() != element.getSemantic() )
1486         {
1487            i--;
1488            break;
1489         }
1490         offset += nextElement.getSizeInBytes();
1491      }
1492   }
1493}
1494
1495GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer()
1496{
1497   if (mVertexConstBufferLayout && mPixelConstBufferLayout)
1498   {
1499      GFXD3D11ShaderConstBuffer* buffer = new GFXD3D11ShaderConstBuffer(this, mVertexConstBufferLayout, mPixelConstBufferLayout);
1500      mActiveBuffers.push_back( buffer );
1501      buffer->registerResourceWithDevice(getOwningDevice());
1502      return buffer;
1503   } 
1504
1505   return NULL;
1506}
1507
1508/// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned.
1509GFXShaderConstHandle* GFXD3D11Shader::getShaderConstHandle(const String& name)
1510{
1511   HandleMap::Iterator i = mHandles.find(name);   
1512   if ( i != mHandles.end() )
1513   {
1514      return i->value;
1515   } 
1516   else 
1517   {     
1518      GFXD3D11ShaderConstHandle *handle = new GFXD3D11ShaderConstHandle();
1519      handle->setValid( false );
1520      handle->mShader = this;
1521      mHandles[name] = handle;
1522
1523      return handle;      
1524   }      
1525}
1526
1527GFXShaderConstHandle* GFXD3D11Shader::findShaderConstHandle(const String& name)
1528{
1529   HandleMap::Iterator i = mHandles.find(name);
1530   if(i != mHandles.end())
1531      return i->value;
1532   else
1533   {
1534      return NULL;
1535   }
1536}
1537
1538const Vector<GFXShaderConstDesc>& GFXD3D11Shader::getShaderConstDesc() const
1539{
1540   return mShaderConsts;
1541}
1542
1543U32 GFXD3D11Shader::getAlignmentValue(const GFXShaderConstType constType) const
1544{   
1545   const U32 mRowSizeF = 16;
1546   const U32 mRowSizeI = 16;
1547
1548   switch (constType)
1549   {
1550      case GFXSCT_Float :
1551      case GFXSCT_Float2 :
1552      case GFXSCT_Float3 : 
1553      case GFXSCT_Float4 :
1554         return mRowSizeF;
1555         break;
1556         // Matrices
1557      case GFXSCT_Float2x2 :
1558         return mRowSizeF * 2;
1559         break;
1560      case GFXSCT_Float3x3 : 
1561         return mRowSizeF * 3;
1562         break;
1563      case GFXSCT_Float4x3:
1564         return mRowSizeF * 3;
1565         break;
1566      case GFXSCT_Float4x4 :
1567         return mRowSizeF * 4;
1568         break;   
1569      //// Scalar
1570      case GFXSCT_Int :
1571      case GFXSCT_Int2 :
1572      case GFXSCT_Int3 : 
1573      case GFXSCT_Int4 :
1574         return mRowSizeI;
1575         break;
1576      default:
1577         AssertFatal(false, "Unsupported type!");
1578         return 0;
1579         break;
1580   }
1581}
1582
1583void GFXD3D11Shader::zombify()
1584{
1585   // Shaders don't need zombification
1586}
1587
1588void GFXD3D11Shader::resurrect()
1589{
1590   // Shaders are never zombies, and therefore don't have to be brought back.
1591}
1592