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