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