Torque3D Documentation / _generateds / gfxGLShader.cpp

gfxGLShader.cpp

Engine/source/gfx/gl/gfxGLShader.cpp

More...

Classes:

Public Defines

define
CHECK_AARG(pos, name) static  attr_##name = ->insert(#name);  (argName == attr_##name) { glBindAttribLocation(mProgram, pos, attr_##name); continue; }

Detailed Description

Public Defines

CHECK_AARG(pos, name) static  attr_##name = ->insert(#name);  (argName == attr_##name) { glBindAttribLocation(mProgram, pos, attr_##name); continue; }

Public Functions

shaderConstTypeSize(GFXShaderConstType type)

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 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/gl/gfxGLShader.h"
  26#include "gfx/gl/gfxGLVertexAttribLocation.h"
  27#include "gfx/gl/gfxGLDevice.h"
  28
  29#include "core/frameAllocator.h"
  30#include "core/stream/fileStream.h"
  31#include "core/strings/stringFunctions.h"
  32#include "math/mPoint2.h"
  33#include "gfx/gfxStructs.h"
  34#include "console/console.h"
  35
  36#define CHECK_AARG(pos, name) static StringTableEntry attr_##name = StringTable->insert(#name); if (argName == attr_##name) { glBindAttribLocation(mProgram, pos, attr_##name); continue; }
  37
  38
  39class GFXGLShaderConstHandle : public GFXShaderConstHandle
  40{
  41   friend class GFXGLShader;
  42
  43public:  
  44   
  45   GFXGLShaderConstHandle( GFXGLShader *shader );
  46   GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum );
  47   virtual ~GFXGLShaderConstHandle();
  48   
  49   void reinit( const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum );
  50
  51   const String& getName() const { return mDesc.name; }
  52   GFXShaderConstType getType() const { return mDesc.constType; }
  53   U32 getArraySize() const { return mDesc.arraySize; }
  54
  55   U32 getSize() const;
  56   void setValid( bool valid ) { mValid = valid; }   
  57   /// @warning This will always return the value assigned when the shader was
  58   /// initialized.  If the value is later changed this method won't reflect that.
  59   S32 getSamplerRegister() const { return mSamplerNum; }
  60
  61   GFXShaderConstDesc mDesc;
  62   GFXGLShader* mShader;
  63   GLuint mLocation;
  64   U32 mOffset;
  65   U32 mSize;  
  66   S32 mSamplerNum; 
  67   bool mInstancingConstant;
  68};
  69
  70GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader )
  71 : mShader( shader ), mLocation(0), mOffset(0), mSize(0), mSamplerNum(-1), mInstancingConstant(false)
  72{
  73   dMemset(&mDesc, 0, sizeof(mDesc));
  74   mValid = false;
  75}
  76
  77static U32 shaderConstTypeSize(GFXShaderConstType type)
  78{
  79   switch(type) 
  80   {
  81   case GFXSCT_Float:
  82   case GFXSCT_Int:
  83   case GFXSCT_Sampler:
  84   case GFXSCT_SamplerCube:
  85   case GFXSCT_SamplerCubeArray:
  86   case GFXSCT_SamplerTextureArray:
  87      return 4;
  88   case GFXSCT_Float2:
  89   case GFXSCT_Int2:
  90      return 8;
  91   case GFXSCT_Float3:
  92   case GFXSCT_Int3:
  93      return 12;
  94   case GFXSCT_Float4:
  95   case GFXSCT_Int4:
  96      return 16;
  97   case GFXSCT_Float2x2:
  98      return 16;
  99   case GFXSCT_Float3x3:
 100      return 36;
 101   case GFXSCT_Float4x3:
 102      return 48;
 103   case GFXSCT_Float4x4:
 104      return 64;
 105   default:
 106      AssertFatal(false,"shaderConstTypeSize - Unrecognized constant type");
 107      return 0;
 108   }
 109}
 110
 111GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ) 
 112 : mShader(shader), mInstancingConstant(false)
 113{
 114   reinit(desc, loc, samplerNum);
 115}
 116
 117void GFXGLShaderConstHandle::reinit( const GFXShaderConstDesc& desc, GLuint loc, S32 samplerNum )
 118{
 119   mDesc = desc;
 120   mLocation = loc;
 121   mSamplerNum = samplerNum;
 122   mOffset = 0;
 123   mInstancingConstant = false;
 124   
 125   U32 elemSize = shaderConstTypeSize(mDesc.constType);
 126   AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0");
 127   mSize = mDesc.arraySize * elemSize;
 128   mValid = true;
 129}
 130
 131
 132U32 GFXGLShaderConstHandle::getSize() const
 133{
 134   return mSize;
 135}
 136
 137GFXGLShaderConstHandle::~GFXGLShaderConstHandle()
 138{
 139}
 140
 141GFXGLShaderConstBuffer::GFXGLShaderConstBuffer(GFXGLShader* shader, U32 bufSize, U8* existingConstants)
 142{
 143   mShader = shader;
 144   mBuffer = new U8[bufSize];
 145   mWasLost = true;
 146
 147   // Copy the existing constant buffer to preserve sampler numbers
 148   /// @warning This preserves a lot more than sampler numbers, obviously. If there
 149   /// is any code that assumes a new constant buffer will have everything set to
 150   /// 0, it will break.
 151   dMemcpy(mBuffer, existingConstants, bufSize);
 152}
 153
 154GFXGLShaderConstBuffer::~GFXGLShaderConstBuffer()
 155{
 156   delete[] mBuffer;
 157
 158   if ( mShader )
 159      mShader->_unlinkBuffer( this );
 160}
 161
 162template<typename ConstType>
 163void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const ConstType& param)
 164{
 165   AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!" );
 166   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!" );
 167   AssertFatal(dynamic_cast<GFXGLShaderConstHandle*>(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type");
 168
 169   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 170   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
 171   U8 *buf = mBuffer + _glHandle->mOffset;
 172
 173   if(_glHandle->mInstancingConstant)            
 174      buf = mInstPtr + _glHandle->mOffset;
 175
 176   dMemcpy(buf, &param, sizeof(ConstType));
 177}
 178
 179void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv)
 180{
 181   internalSet(handle, fv);
 182}
 183
 184void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv)
 185{
 186   internalSet(handle, fv);
 187}
 188
 189void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv)
 190{
 191   internalSet(handle, fv);
 192}
 193
 194void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv)
 195{
 196   internalSet(handle, fv);
 197}
 198
 199void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv)
 200{
 201   internalSet(handle, fv);
 202}
 203
 204void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearColorF& fv)
 205{
 206   internalSet(handle, fv);
 207}
 208 
 209void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 fv)
 210{
 211   internalSet(handle, fv);
 212}
 213
 214void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2I& fv)
 215{
 216   internalSet(handle, fv);
 217}
 218
 219void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3I& fv)
 220{
 221   internalSet(handle, fv);
 222}
 223
 224void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4I& fv)
 225{
 226   internalSet(handle, fv);
 227}
 228
 229template<typename ConstType>
 230void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AlignedArray<ConstType>& fv)
 231{
 232   AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!" );
 233   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!" );
 234   AssertFatal(dynamic_cast<GFXGLShaderConstHandle*>(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type");
 235
 236   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 237   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
 238   AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for array");
 239   const U8* fvBuffer = static_cast<const U8*>(fv.getBuffer());
 240   for(U32 i = 0; i < fv.size(); ++i)
 241   {
 242      dMemcpy(mBuffer + _glHandle->mOffset + i * sizeof(ConstType), fvBuffer, sizeof(ConstType));
 243      fvBuffer += fv.getElementSize();
 244   }
 245}
 246
 247void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv)
 248{
 249   internalSet(handle, fv);
 250}
 251
 252void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv)
 253{
 254   internalSet(handle, fv);
 255}
 256
 257void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv)
 258{
 259   internalSet(handle, fv);
 260}
 261
 262void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv)   
 263{
 264   internalSet(handle, fv);
 265}
 266
 267void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv)
 268{
 269   internalSet(handle, fv);
 270}
 271
 272void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv)
 273{
 274   internalSet(handle, fv);
 275}
 276
 277void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv)
 278{
 279   internalSet(handle, fv);
 280}
 281
 282void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv)
 283{
 284   internalSet(handle, fv);
 285}
 286
 287void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType)
 288{
 289   AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!" );
 290   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" );
 291   AssertFatal(dynamic_cast<GFXGLShaderConstHandle*>(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type");
 292
 293   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 294   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
 295   AssertFatal(!_glHandle->mInstancingConstant || matType == GFXSCT_Float4x4, "GFXGLShaderConstBuffer::set - Only support GFXSCT_Float4x4 for instancing");
 296   
 297   switch(matType)
 298   {
 299   case GFXSCT_Float2x2:
 300      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[0] = mat[0];
 301      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[1] = mat[1];
 302      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[2] = mat[4];
 303      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[3] = mat[5];
 304      break;
 305   case GFXSCT_Float3x3:
 306      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[0] = mat[0];
 307      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[1] = mat[1];
 308      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[2] = mat[2];
 309      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[3] = mat[4];
 310      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[4] = mat[5];
 311      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[5] = mat[6];
 312      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[6] = mat[8];
 313      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[7] = mat[9];
 314      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[8] = mat[10];
 315      break;
 316   case GFXSCT_Float4x3:
 317      dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, (sizeof(F32) * 12));// matrix with end row chopped off
 318      break;
 319   case GFXSCT_Float4x4:
 320   {      
 321      if(_glHandle->mInstancingConstant)
 322      {
 323         MatrixF transposed;   
 324         mat.transposeTo(transposed);
 325         dMemcpy( mInstPtr + _glHandle->mOffset, (const F32*)transposed, sizeof(MatrixF) );
 326         return;
 327      }
 328      
 329      dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, sizeof(MatrixF));
 330      break;
 331   }
 332   default:
 333      AssertFatal(false, "GFXGLShaderConstBuffer::set - Invalid matrix type");
 334      break;
 335   }
 336}
 337
 338void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType)
 339{
 340   AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!" );
 341   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" );
 342
 343   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 344   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");  
 345   AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for matrix arrays");
 346
 347   switch (matrixType) {
 348      case GFXSCT_Float4x3:
 349         // Copy each item with the last row chopped off
 350         for (int i = 0; i<arraySize; i++)
 351         {
 352            dMemcpy(mBuffer + _glHandle->mOffset + (i*(sizeof(F32) * 12)), (F32*)(mat + i), sizeof(F32) * 12);
 353         }
 354      break;
 355      case GFXSCT_Float4x4:
 356         dMemcpy(mBuffer + _glHandle->mOffset, (F32*)mat, _glHandle->getSize());
 357         break;
 358      default:
 359         AssertFatal(false, "GFXGLShaderConstBuffer::set - setting array of non 4x4 matrices!");
 360         break;
 361   }
 362}
 363
 364void GFXGLShaderConstBuffer::activate()
 365{
 366   PROFILE_SCOPE(GFXGLShaderConstBuffer_activate);
 367   mShader->setConstantsFromBuffer(this);
 368   mWasLost = false;
 369}
 370
 371const String GFXGLShaderConstBuffer::describeSelf() const
 372{
 373   return String();
 374}
 375
 376void GFXGLShaderConstBuffer::onShaderReload( GFXGLShader *shader )
 377{
 378   AssertFatal( shader == mShader, "GFXGLShaderConstBuffer::onShaderReload, mismatched shaders!" );
 379
 380   delete[] mBuffer;
 381   mBuffer = new U8[mShader->mConstBufferSize];
 382   dMemset(mBuffer, 0, mShader->mConstBufferSize);
 383   mWasLost = true;
 384}
 385
 386GFXGLShader::GFXGLShader() :
 387   mVertexShader(0),
 388   mPixelShader(0),
 389   mProgram(0),
 390   mConstBufferSize(0),
 391   mConstBuffer(NULL)
 392{
 393}
 394
 395GFXGLShader::~GFXGLShader()
 396{
 397   clearShaders();
 398   for(HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++)
 399      delete i->value;
 400   
 401   delete[] mConstBuffer;
 402}
 403
 404void GFXGLShader::clearShaders()
 405{
 406   glDeleteProgram(mProgram);
 407   glDeleteShader(mVertexShader);
 408   glDeleteShader(mPixelShader);
 409   
 410   mProgram = 0;
 411   mVertexShader = 0;
 412   mPixelShader = 0;
 413}
 414
 415bool GFXGLShader::_init()
 416{
 417   PROFILE_SCOPE(GFXGLShader_Init);
 418   // Don't initialize empty shaders.
 419   if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() )
 420      return false;
 421
 422   clearShaders();
 423
 424   mProgram = glCreateProgram();
 425   
 426   // Set the macros and add the global ones.
 427   Vector<GFXShaderMacro> macros;
 428   macros.merge( mMacros );
 429   macros.merge( smGlobalMacros );
 430   
 431   macros.increment();
 432   macros.last().name = "TORQUE_SM";
 433   macros.last().value = 40;
 434   macros.increment();
 435   macros.last().name = "TORQUE_VERTEX_SHADER";
 436   macros.last().value = "";
 437   
 438   // Default to true so we're "successful" if a vertex/pixel shader wasn't specified.
 439   bool compiledVertexShader = true;
 440   bool compiledPixelShader = true;
 441   
 442   // Compile the vertex and pixel shaders if specified.
 443   if(!mVertexFile.isEmpty())
 444      compiledVertexShader = initShader(mVertexFile, true, macros);
 445
 446   macros.last().name = "TORQUE_PIXEL_SHADER";
 447   if(!mPixelFile.isEmpty())
 448      compiledPixelShader = initShader(mPixelFile, false, macros);
 449      
 450   // If either shader was present and failed to compile, bail.
 451   if(!compiledVertexShader || !compiledPixelShader)
 452      return false;
 453  
 454   // Link it!
 455   glLinkProgram( mProgram );
 456   
 457   GLint activeAttribs  = 0;
 458   glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs );
 459   
 460   GLint maxLength;
 461   glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
 462   
 463   FrameTemp<GLchar> tempData(maxLength+1);
 464   *tempData.address() = '\0';
 465   // Check atributes
 466   for (U32 i=0; i<activeAttribs; i++)
 467   {
 468      GLint size;
 469      GLenum type;
 470      
 471      glGetActiveAttrib(mProgram, i, maxLength + 1, NULL, &size, &type, tempData.address());
 472      
 473      StringTableEntry argName = StringTable->insert(tempData.address());
 474      
 475      CHECK_AARG(Torque::GL_VertexAttrib_Position,    vPosition);
 476      CHECK_AARG(Torque::GL_VertexAttrib_Normal,      vNormal);
 477      CHECK_AARG(Torque::GL_VertexAttrib_Color,       vColor);
 478      CHECK_AARG(Torque::GL_VertexAttrib_Tangent,     vTangent);
 479      CHECK_AARG(Torque::GL_VertexAttrib_TangentW,    vTangentW);
 480      CHECK_AARG(Torque::GL_VertexAttrib_Binormal,    vBinormal);
 481      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord0,   vTexCoord0);
 482      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord1,   vTexCoord1);
 483      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord2,   vTexCoord2);
 484      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord3,   vTexCoord3);
 485      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord4,   vTexCoord4);
 486      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord5,   vTexCoord5);
 487      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord6,   vTexCoord6);
 488      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord7,   vTexCoord7);
 489      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord8,   vTexCoord8);
 490      CHECK_AARG(Torque::GL_VertexAttrib_TexCoord9,   vTexCoord9);
 491   }
 492
 493   //always have OUT_col
 494   glBindFragDataLocation(mProgram, 0, "OUT_col");
 495   // Check OUT_colN
 496   for(U32 i=1;i<4;i++)
 497   {
 498      char buffer[10];
 499      dSprintf(buffer, sizeof(buffer), "OUT_col%u",i);
 500      GLint location = glGetFragDataLocation(mProgram, buffer);
 501      if(location>0)
 502         glBindFragDataLocation(mProgram, i, buffer);
 503
 504   }
 505   
 506   // Link it again!
 507   glLinkProgram( mProgram );
 508   
 509   GLint linkStatus;
 510   glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus );
 511   
 512   // Dump the info log to the console
 513   U32 logLength = 0;
 514   glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, (GLint*)&logLength);
 515   if ( logLength )
 516   {
 517      FrameAllocatorMarker fam;
 518      char* log = (char*)fam.alloc( logLength );
 519      glGetProgramInfoLog( mProgram, logLength, NULL, log );
 520      
 521      if ( linkStatus == GL_FALSE )
 522      {
 523         if ( smLogErrors )
 524         {
 525            Con::errorf( "GFXGLShader::init - Error linking shader!" );
 526            Con::errorf( "Program %s / %s: %s",
 527               mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
 528         }
 529      }
 530      else if ( smLogWarnings )
 531      {
 532         Con::warnf( "Program %s / %s: %s",
 533            mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
 534      }
 535   }
 536
 537
 538   // If we failed to link, bail.
 539   if ( linkStatus == GL_FALSE )
 540      return false;
 541
 542   initConstantDescs();   
 543   initHandles();
 544   
 545   // Notify Buffers we might have changed in size. 
 546   // If this was our first init then we won't have any activeBuffers 
 547   // to worry about unnecessarily calling.
 548   Vector<GFXShaderConstBuffer*>::iterator biter = mActiveBuffers.begin();
 549   for ( ; biter != mActiveBuffers.end(); biter++ )   
 550      ((GFXGLShaderConstBuffer*)(*biter))->onShaderReload( this );
 551   
 552   return true;
 553}
 554
 555void GFXGLShader::initConstantDescs()
 556{
 557   mConstants.clear();
 558   GLint numUniforms;
 559   glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
 560   GLint maxNameLength;
 561   glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
 562
 563   if(!maxNameLength)
 564      return;
 565
 566   FrameTemp<GLchar> uniformName(maxNameLength);
 567   
 568   for(U32 i = 0; i < numUniforms; i++)
 569   {
 570      GLint size;
 571      GLenum type;
 572      glGetActiveUniform(mProgram, i, maxNameLength, NULL, &size, &type, uniformName);
 573      GFXShaderConstDesc desc;
 574      
 575      desc.name = String((char*)uniformName);
 576      
 577      // Remove array brackets from the name
 578      desc.name = desc.name.substr(0, desc.name.find('['));
 579      
 580      // Insert $ to match D3D behavior of having a $ prepended to parameters to main.
 581      desc.name.insert(0, '$');
 582      desc.arraySize = size;
 583      
 584      switch(type)
 585      {
 586         case GL_FLOAT:
 587            desc.constType = GFXSCT_Float;
 588            break;
 589         case GL_FLOAT_VEC2:
 590            desc.constType = GFXSCT_Float2;
 591            break;
 592         case GL_FLOAT_VEC3:
 593            desc.constType = GFXSCT_Float3;
 594            break;
 595         case GL_FLOAT_VEC4:
 596            desc.constType = GFXSCT_Float4;
 597            break;
 598         case GL_INT:
 599            desc.constType = GFXSCT_Int;
 600            break;
 601         case GL_INT_VEC2:
 602            desc.constType = GFXSCT_Int2;
 603            break;
 604         case GL_INT_VEC3:
 605            desc.constType = GFXSCT_Int3;
 606            break;
 607         case GL_INT_VEC4:
 608            desc.constType = GFXSCT_Int4;
 609            break;
 610         case GL_FLOAT_MAT2:
 611            desc.constType = GFXSCT_Float2x2;
 612            break;
 613         case GL_FLOAT_MAT3:
 614            desc.constType = GFXSCT_Float3x3;
 615            break;
 616         case GL_FLOAT_MAT4:
 617            desc.constType = GFXSCT_Float4x4;
 618            break;
 619         case GL_FLOAT_MAT4x3: // jamesu - columns, rows
 620            desc.constType = GFXSCT_Float4x3;
 621            break;
 622         case GL_SAMPLER_1D:
 623         case GL_SAMPLER_2D:
 624         case GL_SAMPLER_3D:
 625         case GL_SAMPLER_1D_SHADOW:
 626         case GL_SAMPLER_2D_SHADOW:
 627            desc.constType = GFXSCT_Sampler;
 628            break;
 629         case GL_SAMPLER_CUBE:
 630            desc.constType = GFXSCT_SamplerCube;
 631            break;
 632         case GL_SAMPLER_CUBE_MAP_ARRAY_ARB:
 633            desc.constType = GFXSCT_SamplerCubeArray;
 634            break;
 635         case GL_SAMPLER_2D_ARRAY:
 636            desc.constType = GFXSCT_SamplerTextureArray;
 637            break;
 638         default:
 639            AssertFatal(false, "GFXGLShader::initConstantDescs - unrecognized uniform type");
 640            // If we don't recognize the constant don't add its description.
 641            continue;
 642      }
 643      
 644      mConstants.push_back(desc);
 645   }
 646}
 647
 648void GFXGLShader::initHandles()
 649{      
 650   // Mark all existing handles as invalid.
 651   // Those that are found when parsing the descriptions will then be marked valid again.
 652   for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter )      
 653      (iter->value)->setValid( false );  
 654   mValidHandles.clear();
 655
 656   // Loop through all ConstantDescriptions, 
 657   // if they aren't in the HandleMap add them, if they are reinitialize them.
 658   for ( U32 i = 0; i < mConstants.size(); i++ )
 659   {
 660      GFXShaderConstDesc &desc = mConstants[i];            
 661
 662      // Index element 1 of the name to skip the '$' we inserted earier.
 663      GLint loc = glGetUniformLocation(mProgram, &desc.name.c_str()[1]);
 664
 665      AssertFatal(loc != -1, "");
 666
 667      HandleMap::Iterator handle = mHandles.find(desc.name);
 668      S32 sampler = -1;
 669      if(desc.constType == GFXSCT_Sampler ||
 670         desc.constType == GFXSCT_SamplerCube ||
 671         desc.constType == GFXSCT_SamplerCubeArray ||
 672         desc.constType == GFXSCT_SamplerTextureArray)
 673      {
 674         S32 idx = mSamplerNamesOrdered.find_next(desc.name);
 675         AssertFatal(idx != -1, "");
 676         sampler = idx; //assignedSamplerNum++;
 677      }
 678      if ( handle != mHandles.end() )
 679      {
 680         handle->value->reinit( desc, loc, sampler );         
 681      } 
 682      else 
 683      {
 684         mHandles[desc.name] = new GFXGLShaderConstHandle( this, desc, loc, sampler );      
 685      }
 686   }
 687
 688   // Loop through handles once more to set their offset and calculate our
 689   // constBuffer size.
 690
 691   if ( mConstBuffer )
 692      delete[] mConstBuffer;
 693   mConstBufferSize = 0;
 694
 695   for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter )
 696   {
 697      GFXGLShaderConstHandle* handle = iter->value;
 698      if ( handle->isValid() )
 699      {
 700         mValidHandles.push_back(handle);
 701         handle->mOffset = mConstBufferSize;
 702         mConstBufferSize += handle->getSize();
 703      }
 704   }
 705   
 706   mConstBuffer = new U8[mConstBufferSize];
 707   dMemset(mConstBuffer, 0, mConstBufferSize);
 708   
 709   // Set our program so uniforms are assigned properly.
 710   glUseProgram(mProgram);
 711   // Iterate through uniforms to set sampler numbers.
 712   for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter)
 713   {
 714      GFXGLShaderConstHandle* handle = iter->value;
 715      if(handle->isValid() &&
 716         (handle->getType() == GFXSCT_Sampler ||
 717            handle->getType() == GFXSCT_SamplerCube ||
 718            handle->getType() == GFXSCT_SamplerCubeArray ||
 719            handle->getType() == GFXSCT_SamplerTextureArray))
 720      {
 721         // Set sampler number on our program.
 722         glUniform1i(handle->mLocation, handle->mSamplerNum);
 723         // Set sampler in constant buffer so it does not get unset later.
 724         dMemcpy(mConstBuffer + handle->mOffset, &handle->mSamplerNum, handle->getSize());
 725      }
 726   }
 727   glUseProgram(0);
 728
 729   //instancing
 730   if (!mInstancingFormat)
 731      return;
 732
 733   U32 offset = 0;
 734
 735   for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ )
 736   {
 737      const GFXVertexElement &element = mInstancingFormat->getElement( i );
 738      
 739      String constName = String::ToString( "$%s", element.getSemantic().c_str() );
 740
 741      HandleMap::Iterator handle = mHandles.find(constName);      
 742      if ( handle != mHandles.end() )
 743      {          
 744         AssertFatal(0, "");
 745      } 
 746      else 
 747      {
 748         GFXShaderConstDesc desc;
 749         desc.name = constName;
 750         desc.arraySize = 1;
 751         switch(element.getType())
 752         {
 753         case GFXDeclType_Float4:
 754            desc.constType = GFXSCT_Float4;
 755            break;
 756
 757         default:
 758            desc.constType = GFXSCT_Float;
 759            break;
 760         }
 761         
 762         GFXGLShaderConstHandle *h = new GFXGLShaderConstHandle( this, desc, -1, -1 );
 763         h->mInstancingConstant = true;
 764         h->mOffset = offset;
 765         mHandles[constName] =  h;
 766
 767         offset += element.getSizeInBytes();
 768         ++i;
 769
 770         // If this is a matrix we will have 2 or 3 more of these
 771         // semantics with the same name after it.
 772         for ( ; i < mInstancingFormat->getElementCount(); i++ )
 773         {
 774            const GFXVertexElement &nextElement = mInstancingFormat->getElement( i );
 775            if ( nextElement.getSemantic() != element.getSemantic() )
 776            {
 777               i--;
 778               break;
 779            }
 780            ++desc.arraySize;
 781            if(desc.arraySize == 4 && desc.constType == GFXSCT_Float4)
 782            {
 783               desc.arraySize = 1;
 784               desc.constType = GFXSCT_Float4x4;
 785            }
 786            offset += nextElement.getSizeInBytes();
 787         }
 788      }
 789
 790   }
 791}
 792
 793GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name)
 794{
 795   HandleMap::Iterator i = mHandles.find(name);
 796   if(i != mHandles.end())
 797      return i->value;
 798   else
 799   {
 800      GFXGLShaderConstHandle* handle = new GFXGLShaderConstHandle( this );
 801      mHandles[ name ] = handle;
 802      
 803      return handle;
 804   }
 805}
 806
 807GFXShaderConstHandle* GFXGLShader::findShaderConstHandle(const String& name)
 808{
 809   HandleMap::Iterator i = mHandles.find(name);
 810   if(i != mHandles.end())
 811      return i->value;
 812   else
 813   {
 814      return NULL;
 815   }
 816}
 817
 818void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
 819{
 820   for(Vector<GFXGLShaderConstHandle*>::iterator i = mValidHandles.begin(); i != mValidHandles.end(); ++i)
 821   {
 822      GFXGLShaderConstHandle* handle = *i;
 823      AssertFatal(handle, "GFXGLShader::setConstantsFromBuffer - Null handle");
 824
 825      if(handle->mInstancingConstant)
 826         continue;
 827      
 828      // Don't set if the value has not be changed.
 829      if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0)
 830         continue;
 831         
 832      // Copy new value into our const buffer and set in GL.
 833      dMemcpy(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize());
 834      switch(handle->mDesc.constType)
 835      {
 836         case GFXSCT_Float:
 837            glUniform1fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 838            break;
 839         case GFXSCT_Float2:
 840            glUniform2fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 841            break;
 842         case GFXSCT_Float3:
 843            glUniform3fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 844            break;
 845         case GFXSCT_Float4:
 846            glUniform4fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 847            break;
 848         case GFXSCT_Int:
 849         case GFXSCT_Sampler:
 850         case GFXSCT_SamplerCube:
 851         case GFXSCT_SamplerCubeArray:
 852         case GFXSCT_SamplerTextureArray:
 853            glUniform1iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 854            break;
 855         case GFXSCT_Int2:
 856            glUniform2iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 857            break;
 858         case GFXSCT_Int3:
 859            glUniform3iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 860            break;
 861         case GFXSCT_Int4:
 862            glUniform4iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 863            break;
 864         case GFXSCT_Float2x2:
 865            glUniformMatrix2fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 866            break;
 867         case GFXSCT_Float3x3:
 868            glUniformMatrix3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 869            break;
 870         case GFXSCT_Float4x3:
 871            // NOTE: To save a transpose here we could store the matrix transposed (i.e. column major) in the constant buffer.
 872            // See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix. 
 873            glUniformMatrix4x3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 874            break;
 875         case GFXSCT_Float4x4:
 876            glUniformMatrix4fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 877            break;
 878         default:
 879            AssertFatal(0,"");
 880            break;
 881      }
 882   }
 883}
 884
 885GFXShaderConstBufferRef GFXGLShader::allocConstBuffer()
 886{
 887   GFXGLShaderConstBuffer* buffer = new GFXGLShaderConstBuffer(this, mConstBufferSize, mConstBuffer);
 888   buffer->registerResourceWithDevice(getOwningDevice());
 889   mActiveBuffers.push_back( buffer );
 890   return buffer;
 891}
 892
 893void GFXGLShader::useProgram()
 894{
 895   glUseProgram(mProgram);
 896}
 897
 898void GFXGLShader::zombify()
 899{
 900   clearShaders();
 901   dMemset(mConstBuffer, 0, mConstBufferSize);
 902}
 903
 904char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
 905{
 906   // TODO:  The #line pragma on GLSL takes something called a
 907   // "source-string-number" which it then never explains.
 908   //
 909   // Until i resolve this mystery i disabled this.
 910   //
 911   //String linePragma = String::ToString( "#line 1 \r\n");
 912   //U32 linePragmaLen = linePragma.length();
 913
 914   U32 shaderLen = s->getStreamSize();
 915   char* buffer = (char*)dMalloc(shaderLen + 1);
 916   //dStrncpy( buffer, linePragma.c_str(), linePragmaLen );
 917   s->read(shaderLen, buffer);
 918   buffer[shaderLen] = 0;
 919   
 920   char* p = dStrstr(buffer, "#include");
 921   while(p)
 922   {
 923      char* q = p;
 924      p += 8;
 925      if(dIsspace(*p))
 926      {
 927         U32 n = 0;
 928         while(dIsspace(*p)) ++p;
 929         AssertFatal(*p == '"', "Bad #include directive");
 930         ++p;
 931         static char includeFile[256];
 932         while(*p != '"')
 933         {
 934            AssertFatal(*p != 0, "Bad #include directive");
 935            includeFile[n++] = *p++;
 936            AssertFatal(n < sizeof(includeFile), "#include directive too long");
 937         }
 938         ++p;
 939         includeFile[n] = 0;
 940
 941         // First try it as a local file.
 942         Torque::Path includePath = Torque::Path::Join(path.getPath(), '/', includeFile);
 943         includePath = Torque::Path::CompressPath(includePath);
 944         
 945         FileStream includeStream;
 946
 947         if ( !includeStream.open( includePath, Torque::FS::File::Read ) )
 948         {
 949            // Try again assuming the path is absolute 
 950            // and/or relative.
 951            includePath = String( includeFile );
 952            includePath = Torque::Path::CompressPath(includePath);
 953            if ( !includeStream.open( includePath, Torque::FS::File::Read ) )
 954            {
 955               AssertISV(false, avar("failed to open include '%s'.", includePath.getFullPath().c_str()));
 956
 957               if ( smLogErrors )
 958                  Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.", 
 959                     includePath.getFullPath().c_str() );
 960
 961               // Fail... don't return the buffer.
 962               dFree(buffer);
 963               return NULL;
 964            }
 965         }
 966
 967         char* includedText = _handleIncludes(includePath, &includeStream);
 968         
 969         // If a sub-include fails... cleanup and return.
 970         if ( !includedText )
 971         {
 972            dFree(buffer);
 973            return NULL;
 974         }
 975         
 976         // TODO: Disabled till this is fixed correctly.
 977         //
 978         // Count the number of lines in the file 
 979         // before the include.
 980         /*
 981         U32 includeLine = 0;
 982         {
 983            char* nl = dStrstr( buffer, "\n" );
 984            while ( nl )
 985            {
 986               includeLine++;
 987               nl = dStrstr( nl, "\n" );
 988               if(nl) ++nl;
 989            }
 990         }
 991         */
 992
 993         String manip(buffer);
 994         manip.erase(q-buffer, p-q);
 995         String sItx(includedText);
 996
 997         // TODO: Disabled till this is fixed correctly.
 998         //
 999         // Add a new line pragma to restore the proper
1000         // file and line number after the include.
1001         //sItx += String::ToString( "\r\n#line %d \r\n", includeLine );
1002         
1003         dFree(includedText);
1004         manip.insert(q-buffer, sItx);
1005         char* manipBuf = dStrdup(manip.c_str());
1006         p = manipBuf + (q - buffer);
1007         dFree(buffer);
1008         buffer = manipBuf;
1009      }
1010      p = dStrstr(p, "#include");
1011   }
1012   
1013   return buffer;
1014}
1015
1016bool GFXGLShader::_loadShaderFromStream(  GLuint shader, 
1017                                          const Torque::Path &path, 
1018                                          FileStream *s, 
1019                                          const Vector<GFXShaderMacro> &macros )
1020{
1021   Vector<char*> buffers;
1022   Vector<U32> lengths;
1023   
1024   // The GLSL version declaration must go first!
1025   const char *versionDecl = "#version 330\n";
1026   buffers.push_back( dStrdup( versionDecl ) );
1027   lengths.push_back( dStrlen( versionDecl ) );
1028
1029   //Required extensions. These are already checked when creating the GFX adapter, if we make it this far it's supported
1030   const char* cubeArrayExt = "#extension GL_ARB_texture_cube_map_array : enable\n";
1031   buffers.push_back(dStrdup(cubeArrayExt));
1032   lengths.push_back(dStrlen(cubeArrayExt));
1033
1034   const char* gpuShader5Ext = "#extension GL_ARB_gpu_shader5 : enable\n";
1035   buffers.push_back(dStrdup(gpuShader5Ext));
1036   lengths.push_back(dStrlen(gpuShader5Ext));
1037
1038   const char* newLine = "\r\n";
1039   buffers.push_back(dStrdup(newLine));
1040   lengths.push_back(dStrlen(newLine));
1041
1042   // Now add all the macros.
1043   for( U32 i = 0; i < macros.size(); i++ )
1044   {
1045      if(macros[i].name.isEmpty())  // TODO OPENGL
1046         continue;
1047
1048      String define = String::ToString( "#define %s %s\n", macros[i].name.c_str(), macros[i].value.c_str() );
1049      buffers.push_back( dStrdup( define.c_str() ) );
1050      lengths.push_back( define.length() );
1051   }
1052   
1053   // Now finally add the shader source.
1054   U32 shaderLen = s->getStreamSize();
1055   char *buffer = _handleIncludes(path, s);
1056   if ( !buffer )
1057      return false;
1058   
1059   buffers.push_back(buffer);
1060   lengths.push_back(shaderLen);
1061   
1062   glShaderSource(shader, buffers.size(), (const GLchar**)const_cast<const char**>(buffers.address()), NULL);
1063
1064#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
1065   FileStream stream;
1066   if ( !stream.open( path.getFullPath()+"_DEBUG", Torque::FS::File::Write ) )
1067   {
1068      AssertISV(false, avar("GFXGLShader::initShader - failed to write debug shader '%s'.", path.getFullPath().c_str()));
1069   }
1070
1071   for(int i = 0; i < buffers.size(); ++i)
1072         stream.writeText(buffers[i]);
1073#endif
1074
1075   // Cleanup the shader source buffer.
1076   for ( U32 i=0; i < buffers.size(); i++ )
1077      dFree( buffers[i] );
1078
1079   glCompileShader(shader);
1080
1081   return true;
1082}
1083
1084bool GFXGLShader::initShader( const Torque::Path &file, 
1085                              bool isVertex, 
1086                              const Vector<GFXShaderMacro> &macros )
1087{
1088   PROFILE_SCOPE(GFXGLShader_CompileShader);
1089   GLuint activeShader = glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
1090   if(isVertex)
1091      mVertexShader = activeShader;
1092   else
1093      mPixelShader = activeShader;
1094   glAttachShader(mProgram, activeShader);
1095   
1096   
1097   // Ok it's not in the shader gen manager, so ask Torque for it
1098   FileStream stream;
1099   if ( !stream.open( file, Torque::FS::File::Read ) )
1100   {
1101      AssertISV(false, avar("GFXGLShader::initShader - failed to open shader '%s'.", file.getFullPath().c_str()));
1102
1103      if ( smLogErrors )
1104         Con::errorf( "GFXGLShader::initShader - Failed to open shader file '%s'.", 
1105            file.getFullPath().c_str() );
1106
1107      return false;
1108   }
1109   
1110   if ( !_loadShaderFromStream( activeShader, file, &stream, macros ) )
1111      return false;
1112   
1113   GLint compile;
1114   glGetShaderiv(activeShader, GL_COMPILE_STATUS, &compile);
1115
1116   // Dump the info log to the console
1117   U32 logLength = 0;
1118   glGetShaderiv(activeShader, GL_INFO_LOG_LENGTH, (GLint*)&logLength);
1119   
1120   GLint compileStatus = GL_TRUE;
1121   if ( logLength )
1122   {
1123      FrameAllocatorMarker fam;
1124      char* log = (char*)fam.alloc(logLength);
1125      glGetShaderInfoLog(activeShader, logLength, NULL, log);
1126
1127      // Always print errors
1128      glGetShaderiv( activeShader, GL_COMPILE_STATUS, &compileStatus );
1129
1130      if ( compileStatus == GL_FALSE )
1131      {
1132         if ( smLogErrors )
1133         {
1134            Con::errorf( "GFXGLShader::initShader - Error compiling shader!" );
1135            Con::errorf( "Program %s: %s", file.getFullPath().c_str(), log );
1136         }
1137      }
1138      else if ( smLogWarnings )
1139         Con::warnf( "Program %s: %s", file.getFullPath().c_str(), log );
1140   }
1141
1142   return compileStatus != GL_FALSE;
1143}
1144
1145/// Returns our list of shader constants, the material can get this and just set the constants it knows about
1146const Vector<GFXShaderConstDesc>& GFXGLShader::getShaderConstDesc() const
1147{
1148   PROFILE_SCOPE(GFXGLShader_GetShaderConstants);
1149   return mConstants;
1150}
1151
1152/// Returns the alignment value for constType
1153U32 GFXGLShader::getAlignmentValue(const GFXShaderConstType constType) const
1154{
1155   // Alignment is the same thing as size for us.
1156   return shaderConstTypeSize(constType);
1157}
1158
1159const String GFXGLShader::describeSelf() const
1160{
1161   String ret;
1162   ret = String::ToString("   Program: %i", mProgram);
1163   ret += String::ToString("   Vertex Path: %s", mVertexFile.getFullPath().c_str());
1164   ret += String::ToString("   Pixel Path: %s", mPixelFile.getFullPath().c_str());
1165   
1166   return ret;
1167}
1168