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   mValid = false;
  74}
  75
  76static U32 shaderConstTypeSize(GFXShaderConstType type)
  77{
  78   switch(type) 
  79   {
  80   case GFXSCT_Float:
  81   case GFXSCT_Int:
  82   case GFXSCT_Sampler:
  83   case GFXSCT_SamplerCube:
  84      return 4;
  85   case GFXSCT_Float2:
  86   case GFXSCT_Int2:
  87      return 8;
  88   case GFXSCT_Float3:
  89   case GFXSCT_Int3:
  90      return 12;
  91   case GFXSCT_Float4:
  92   case GFXSCT_Int4:
  93      return 16;
  94   case GFXSCT_Float2x2:
  95      return 16;
  96   case GFXSCT_Float3x3:
  97      return 36;
  98   case GFXSCT_Float4x3:
  99      return 48;
 100   case GFXSCT_Float4x4:
 101      return 64;
 102   default:
 103      AssertFatal(false,"shaderConstTypeSize - Unrecognized constant type");
 104      return 0;
 105   }
 106}
 107
 108GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ) 
 109 : mShader(shader), mInstancingConstant(false)
 110{
 111   reinit(desc, loc, samplerNum);
 112}
 113
 114void GFXGLShaderConstHandle::reinit( const GFXShaderConstDesc& desc, GLuint loc, S32 samplerNum )
 115{
 116   mDesc = desc;
 117   mLocation = loc;
 118   mSamplerNum = samplerNum;
 119   mOffset = 0;
 120   mInstancingConstant = false;
 121   
 122   U32 elemSize = shaderConstTypeSize(mDesc.constType);
 123   AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0");
 124   mSize = mDesc.arraySize * elemSize;
 125   mValid = true;
 126}
 127
 128
 129U32 GFXGLShaderConstHandle::getSize() const
 130{
 131   return mSize;
 132}
 133
 134GFXGLShaderConstHandle::~GFXGLShaderConstHandle()
 135{
 136}
 137
 138GFXGLShaderConstBuffer::GFXGLShaderConstBuffer(GFXGLShader* shader, U32 bufSize, U8* existingConstants)
 139{
 140   mShader = shader;
 141   mBuffer = new U8[bufSize];
 142   mWasLost = true;
 143
 144   // Copy the existing constant buffer to preserve sampler numbers
 145   /// @warning This preserves a lot more than sampler numbers, obviously. If there
 146   /// is any code that assumes a new constant buffer will have everything set to
 147   /// 0, it will break.
 148   dMemcpy(mBuffer, existingConstants, bufSize);
 149}
 150
 151GFXGLShaderConstBuffer::~GFXGLShaderConstBuffer()
 152{
 153   delete[] mBuffer;
 154
 155   if ( mShader )
 156      mShader->_unlinkBuffer( this );
 157}
 158
 159template<typename ConstType>
 160void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const ConstType& param)
 161{
 162   AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!" );
 163   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!" );
 164   AssertFatal(dynamic_cast<GFXGLShaderConstHandle*>(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type");
 165
 166   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 167   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
 168   U8 *buf = mBuffer + _glHandle->mOffset;
 169
 170   if(_glHandle->mInstancingConstant)            
 171      buf = mInstPtr + _glHandle->mOffset;
 172
 173   dMemcpy(buf, &param, sizeof(ConstType));
 174}
 175
 176void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv)
 177{
 178   internalSet(handle, fv);
 179}
 180
 181void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv)
 182{
 183   internalSet(handle, fv);
 184}
 185
 186void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv)
 187{
 188   internalSet(handle, fv);
 189}
 190
 191void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv)
 192{
 193   internalSet(handle, fv);
 194}
 195
 196void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv)
 197{
 198   internalSet(handle, fv);
 199}
 200
 201void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const ColorF& fv)
 202{
 203   internalSet(handle, fv);
 204}
 205 
 206void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 fv)
 207{
 208   internalSet(handle, fv);
 209}
 210
 211void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2I& fv)
 212{
 213   internalSet(handle, fv);
 214}
 215
 216void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3I& fv)
 217{
 218   internalSet(handle, fv);
 219}
 220
 221void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4I& fv)
 222{
 223   internalSet(handle, fv);
 224}
 225
 226template<typename ConstType>
 227void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AlignedArray<ConstType>& fv)
 228{
 229   AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!" );
 230   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!" );
 231   AssertFatal(dynamic_cast<GFXGLShaderConstHandle*>(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type");
 232
 233   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 234   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
 235   AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for array");
 236   const U8* fvBuffer = static_cast<const U8*>(fv.getBuffer());
 237   for(U32 i = 0; i < fv.size(); ++i)
 238   {
 239      dMemcpy(mBuffer + _glHandle->mOffset + i * sizeof(ConstType), fvBuffer, sizeof(ConstType));
 240      fvBuffer += fv.getElementSize();
 241   }
 242}
 243
 244void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv)
 245{
 246   internalSet(handle, fv);
 247}
 248
 249void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv)
 250{
 251   internalSet(handle, fv);
 252}
 253
 254void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv)
 255{
 256   internalSet(handle, fv);
 257}
 258
 259void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv)   
 260{
 261   internalSet(handle, fv);
 262}
 263
 264void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv)
 265{
 266   internalSet(handle, fv);
 267}
 268
 269void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv)
 270{
 271   internalSet(handle, fv);
 272}
 273
 274void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv)
 275{
 276   internalSet(handle, fv);
 277}
 278
 279void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv)
 280{
 281   internalSet(handle, fv);
 282}
 283
 284void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType)
 285{
 286   AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!" );
 287   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" );
 288   AssertFatal(dynamic_cast<GFXGLShaderConstHandle*>(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type");
 289
 290   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 291   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
 292   AssertFatal(!_glHandle->mInstancingConstant || matType == GFXSCT_Float4x4, "GFXGLShaderConstBuffer::set - Only support GFXSCT_Float4x4 for instancing");
 293   
 294   switch(matType)
 295   {
 296   case GFXSCT_Float2x2:
 297      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[0] = mat[0];
 298      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[1] = mat[1];
 299      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[2] = mat[4];
 300      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[3] = mat[5];
 301      break;
 302   case GFXSCT_Float3x3:
 303      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[0] = mat[0];
 304      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[1] = mat[1];
 305      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[2] = mat[2];
 306      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[3] = mat[4];
 307      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[4] = mat[5];
 308      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[5] = mat[6];
 309      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[6] = mat[8];
 310      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[7] = mat[9];
 311      reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[8] = mat[10];
 312      break;
 313   case GFXSCT_Float4x3:
 314      dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, (sizeof(F32) * 12));// matrix with end row chopped off
 315      break;
 316   case GFXSCT_Float4x4:
 317   {      
 318      if(_glHandle->mInstancingConstant)
 319      {
 320         MatrixF transposed;   
 321         mat.transposeTo(transposed);
 322         dMemcpy( mInstPtr + _glHandle->mOffset, (const F32*)transposed, sizeof(MatrixF) );
 323         return;
 324      }
 325      
 326      dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, sizeof(MatrixF));
 327      break;
 328   }
 329   default:
 330      AssertFatal(false, "GFXGLShaderConstBuffer::set - Invalid matrix type");
 331      break;
 332   }
 333}
 334
 335void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType)
 336{
 337   AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!" );
 338   AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" );
 339
 340   GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
 341   AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");  
 342   AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for matrix arrays");
 343
 344   switch (matrixType) {
 345      case GFXSCT_Float4x3:
 346         // Copy each item with the last row chopped off
 347         for (int i = 0; i<arraySize; i++)
 348         {
 349            dMemcpy(mBuffer + _glHandle->mOffset + (i*(sizeof(F32) * 12)), (F32*)(mat + i), sizeof(F32) * 12);
 350         }
 351      break;
 352      case GFXSCT_Float4x4:
 353         dMemcpy(mBuffer + _glHandle->mOffset, (F32*)mat, _glHandle->getSize());
 354         break;
 355      default:
 356         AssertFatal(false, "GFXGLShaderConstBuffer::set - setting array of non 4x4 matrices!");
 357         break;
 358   }
 359}
 360
 361void GFXGLShaderConstBuffer::activate()
 362{
 363   PROFILE_SCOPE(GFXGLShaderConstBuffer_activate);
 364   mShader->setConstantsFromBuffer(this);
 365   mWasLost = false;
 366}
 367
 368const String GFXGLShaderConstBuffer::describeSelf() const
 369{
 370   return String();
 371}
 372
 373void GFXGLShaderConstBuffer::onShaderReload( GFXGLShader *shader )
 374{
 375   AssertFatal( shader == mShader, "GFXGLShaderConstBuffer::onShaderReload, mismatched shaders!" );
 376
 377   delete[] mBuffer;
 378   mBuffer = new U8[mShader->mConstBufferSize];
 379   dMemset(mBuffer, 0, mShader->mConstBufferSize);
 380   mWasLost = true;
 381}
 382
 383GFXGLShader::GFXGLShader() :
 384   mVertexShader(0),
 385   mPixelShader(0),
 386   mProgram(0),
 387   mConstBufferSize(0),
 388   mConstBuffer(NULL)
 389{
 390}
 391
 392GFXGLShader::~GFXGLShader()
 393{
 394   clearShaders();
 395   for(HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++)
 396      delete i->value;
 397   
 398   delete[] mConstBuffer;
 399}
 400
 401void GFXGLShader::clearShaders()
 402{
 403   glDeleteProgram(mProgram);
 404   glDeleteShader(mVertexShader);
 405   glDeleteShader(mPixelShader);
 406   
 407   mProgram = 0;
 408   mVertexShader = 0;
 409   mPixelShader = 0;
 410}
 411
 412bool GFXGLShader::_init()
 413{
 414   PROFILE_SCOPE(GFXGLShader_Init);
 415   // Don't initialize empty shaders.
 416   if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() )
 417      return false;
 418
 419   clearShaders();
 420
 421   mProgram = glCreateProgram();
 422   
 423   // Set the macros and add the global ones.
 424   Vector<GFXShaderMacro> macros;
 425   macros.merge( mMacros );
 426   macros.merge( smGlobalMacros );
 427
 428   // Add the shader version to the macros.
 429   const U32 mjVer = (U32)mFloor( mPixVersion );
 430   const U32 mnVer = (U32)( ( mPixVersion - F32( mjVer ) ) * 10.01f );
 431   macros.increment();
 432   macros.last().name = "TORQUE_SM";
 433   macros.last().value = String::ToString( mjVer * 10 + mnVer );
 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         default:
 633            AssertFatal(false, "GFXGLShader::initConstantDescs - unrecognized uniform type");
 634            // If we don't recognize the constant don't add its description.
 635            continue;
 636      }
 637      
 638      mConstants.push_back(desc);
 639   }
 640}
 641
 642void GFXGLShader::initHandles()
 643{      
 644   // Mark all existing handles as invalid.
 645   // Those that are found when parsing the descriptions will then be marked valid again.
 646   for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter )      
 647      (iter->value)->setValid( false );  
 648   mValidHandles.clear();
 649
 650   // Loop through all ConstantDescriptions, 
 651   // if they aren't in the HandleMap add them, if they are reinitialize them.
 652   for ( U32 i = 0; i < mConstants.size(); i++ )
 653   {
 654      GFXShaderConstDesc &desc = mConstants[i];            
 655
 656      // Index element 1 of the name to skip the '$' we inserted earier.
 657      GLint loc = glGetUniformLocation(mProgram, &desc.name.c_str()[1]);
 658
 659      AssertFatal(loc != -1, "");
 660
 661      HandleMap::Iterator handle = mHandles.find(desc.name);
 662      S32 sampler = -1;
 663      if(desc.constType == GFXSCT_Sampler || desc.constType == GFXSCT_SamplerCube)
 664      {
 665         S32 idx = mSamplerNamesOrdered.find_next(desc.name);
 666         AssertFatal(idx != -1, "");
 667         sampler = idx; //assignedSamplerNum++;
 668      }
 669      if ( handle != mHandles.end() )
 670      {
 671         handle->value->reinit( desc, loc, sampler );         
 672      } 
 673      else 
 674      {
 675         mHandles[desc.name] = new GFXGLShaderConstHandle( this, desc, loc, sampler );      
 676      }
 677   }
 678
 679   // Loop through handles once more to set their offset and calculate our
 680   // constBuffer size.
 681
 682   if ( mConstBuffer )
 683      delete[] mConstBuffer;
 684   mConstBufferSize = 0;
 685
 686   for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter )
 687   {
 688      GFXGLShaderConstHandle* handle = iter->value;
 689      if ( handle->isValid() )
 690      {
 691         mValidHandles.push_back(handle);
 692         handle->mOffset = mConstBufferSize;
 693         mConstBufferSize += handle->getSize();
 694      }
 695   }
 696   
 697   mConstBuffer = new U8[mConstBufferSize];
 698   dMemset(mConstBuffer, 0, mConstBufferSize);
 699   
 700   // Set our program so uniforms are assigned properly.
 701   glUseProgram(mProgram);
 702   // Iterate through uniforms to set sampler numbers.
 703   for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter)
 704   {
 705      GFXGLShaderConstHandle* handle = iter->value;
 706      if(handle->isValid() && (handle->getType() == GFXSCT_Sampler || handle->getType() == GFXSCT_SamplerCube))
 707      {
 708         // Set sampler number on our program.
 709         glUniform1i(handle->mLocation, handle->mSamplerNum);
 710         // Set sampler in constant buffer so it does not get unset later.
 711         dMemcpy(mConstBuffer + handle->mOffset, &handle->mSamplerNum, handle->getSize());
 712      }
 713   }
 714   glUseProgram(0);
 715
 716   //instancing
 717   if (!mInstancingFormat)
 718      return;
 719
 720   U32 offset = 0;
 721
 722   for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ )
 723   {
 724      const GFXVertexElement &element = mInstancingFormat->getElement( i );
 725      
 726      String constName = String::ToString( "$%s", element.getSemantic().c_str() );
 727
 728      HandleMap::Iterator handle = mHandles.find(constName);      
 729      if ( handle != mHandles.end() )
 730      {          
 731         AssertFatal(0, "");
 732      } 
 733      else 
 734      {
 735         GFXShaderConstDesc desc;
 736         desc.name = constName;
 737         desc.arraySize = 1;
 738         switch(element.getType())
 739         {
 740         case GFXDeclType_Float4:
 741            desc.constType = GFXSCT_Float4;
 742            break;
 743
 744         default:
 745            desc.constType = GFXSCT_Float;
 746            break;
 747         }
 748         
 749         GFXGLShaderConstHandle *h = new GFXGLShaderConstHandle( this, desc, -1, -1 );
 750         h->mInstancingConstant = true;
 751         h->mOffset = offset;
 752         mHandles[constName] =  h;
 753
 754         offset += element.getSizeInBytes();
 755         ++i;
 756
 757         // If this is a matrix we will have 2 or 3 more of these
 758         // semantics with the same name after it.
 759         for ( ; i < mInstancingFormat->getElementCount(); i++ )
 760         {
 761            const GFXVertexElement &nextElement = mInstancingFormat->getElement( i );
 762            if ( nextElement.getSemantic() != element.getSemantic() )
 763            {
 764               i--;
 765               break;
 766            }
 767            ++desc.arraySize;
 768            if(desc.arraySize == 4 && desc.constType == GFXSCT_Float4)
 769            {
 770               desc.arraySize = 1;
 771               desc.constType = GFXSCT_Float4x4;
 772            }
 773            offset += nextElement.getSizeInBytes();
 774         }
 775      }
 776
 777   }
 778}
 779
 780GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name)
 781{
 782   HandleMap::Iterator i = mHandles.find(name);
 783   if(i != mHandles.end())
 784      return i->value;
 785   else
 786   {
 787      GFXGLShaderConstHandle* handle = new GFXGLShaderConstHandle( this );
 788      mHandles[ name ] = handle;
 789      
 790      return handle;
 791   }
 792}
 793
 794GFXShaderConstHandle* GFXGLShader::findShaderConstHandle(const String& name)
 795{
 796   HandleMap::Iterator i = mHandles.find(name);
 797   if(i != mHandles.end())
 798      return i->value;
 799   else
 800   {
 801      return NULL;
 802   }
 803}
 804
 805void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
 806{
 807   for(Vector<GFXGLShaderConstHandle*>::iterator i = mValidHandles.begin(); i != mValidHandles.end(); ++i)
 808   {
 809      GFXGLShaderConstHandle* handle = *i;
 810      AssertFatal(handle, "GFXGLShader::setConstantsFromBuffer - Null handle");
 811
 812      if(handle->mInstancingConstant)
 813         continue;
 814      
 815      // Don't set if the value has not be changed.
 816      if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0)
 817         continue;
 818         
 819      // Copy new value into our const buffer and set in GL.
 820      dMemcpy(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize());
 821      switch(handle->mDesc.constType)
 822      {
 823         case GFXSCT_Float:
 824            glUniform1fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 825            break;
 826         case GFXSCT_Float2:
 827            glUniform2fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 828            break;
 829         case GFXSCT_Float3:
 830            glUniform3fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 831            break;
 832         case GFXSCT_Float4:
 833            glUniform4fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset));
 834            break;
 835         case GFXSCT_Int:
 836         case GFXSCT_Sampler:
 837         case GFXSCT_SamplerCube:
 838            glUniform1iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 839            break;
 840         case GFXSCT_Int2:
 841            glUniform2iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 842            break;
 843         case GFXSCT_Int3:
 844            glUniform3iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 845            break;
 846         case GFXSCT_Int4:
 847            glUniform4iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
 848            break;
 849         case GFXSCT_Float2x2:
 850            glUniformMatrix2fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 851            break;
 852         case GFXSCT_Float3x3:
 853            glUniformMatrix3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 854            break;
 855         case GFXSCT_Float4x3:
 856            // NOTE: To save a transpose here we could store the matrix transposed (i.e. column major) in the constant buffer.
 857            // See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix. 
 858            glUniformMatrix4x3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 859            break;
 860         case GFXSCT_Float4x4:
 861            glUniformMatrix4fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
 862            break;
 863         default:
 864            AssertFatal(0,"");
 865            break;
 866      }
 867   }
 868}
 869
 870GFXShaderConstBufferRef GFXGLShader::allocConstBuffer()
 871{
 872   GFXGLShaderConstBuffer* buffer = new GFXGLShaderConstBuffer(this, mConstBufferSize, mConstBuffer);
 873   buffer->registerResourceWithDevice(getOwningDevice());
 874   mActiveBuffers.push_back( buffer );
 875   return buffer;
 876}
 877
 878void GFXGLShader::useProgram()
 879{
 880   glUseProgram(mProgram);
 881}
 882
 883void GFXGLShader::zombify()
 884{
 885   clearShaders();
 886   dMemset(mConstBuffer, 0, mConstBufferSize);
 887}
 888
 889char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
 890{
 891   // TODO:  The #line pragma on GLSL takes something called a
 892   // "source-string-number" which it then never explains.
 893   //
 894   // Until i resolve this mystery i disabled this.
 895   //
 896   //String linePragma = String::ToString( "#line 1 \r\n");
 897   //U32 linePragmaLen = linePragma.length();
 898
 899   U32 shaderLen = s->getStreamSize();
 900   char* buffer = (char*)dMalloc(shaderLen + 1);
 901   //dStrncpy( buffer, linePragma.c_str(), linePragmaLen );
 902   s->read(shaderLen, buffer);
 903   buffer[shaderLen] = 0;
 904   
 905   char* p = dStrstr(buffer, "#include");
 906   while(p)
 907   {
 908      char* q = p;
 909      p += 8;
 910      if(dIsspace(*p))
 911      {
 912         U32 n = 0;
 913         while(dIsspace(*p)) ++p;
 914         AssertFatal(*p == '"', "Bad #include directive");
 915         ++p;
 916         static char includeFile[256];
 917         while(*p != '"')
 918         {
 919            AssertFatal(*p != 0, "Bad #include directive");
 920            includeFile[n++] = *p++;
 921            AssertFatal(n < sizeof(includeFile), "#include directive too long");
 922         }
 923         ++p;
 924         includeFile[n] = 0;
 925
 926         // First try it as a local file.
 927         Torque::Path includePath = Torque::Path::Join(path.getPath(), '/', includeFile);
 928         includePath = Torque::Path::CompressPath(includePath);
 929         
 930         FileStream includeStream;
 931
 932         if ( !includeStream.open( includePath, Torque::FS::File::Read ) )
 933         {
 934            // Try again assuming the path is absolute 
 935            // and/or relative.
 936            includePath = String( includeFile );
 937            includePath = Torque::Path::CompressPath(includePath);
 938            if ( !includeStream.open( includePath, Torque::FS::File::Read ) )
 939            {
 940               AssertISV(false, avar("failed to open include '%s'.", includePath.getFullPath().c_str()));
 941
 942               if ( smLogErrors )
 943                  Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.", 
 944                     includePath.getFullPath().c_str() );
 945
 946               // Fail... don't return the buffer.
 947               dFree(buffer);
 948               return NULL;
 949            }
 950         }
 951
 952         char* includedText = _handleIncludes(includePath, &includeStream);
 953         
 954         // If a sub-include fails... cleanup and return.
 955         if ( !includedText )
 956         {
 957            dFree(buffer);
 958            return NULL;
 959         }
 960         
 961         // TODO: Disabled till this is fixed correctly.
 962         //
 963         // Count the number of lines in the file 
 964         // before the include.
 965         /*
 966         U32 includeLine = 0;
 967         {
 968            char* nl = dStrstr( buffer, "\n" );
 969            while ( nl )
 970            {
 971               includeLine++;
 972               nl = dStrstr( nl, "\n" );
 973               if(nl) ++nl;
 974            }
 975         }
 976         */
 977
 978         String manip(buffer);
 979         manip.erase(q-buffer, p-q);
 980         String sItx(includedText);
 981
 982         // TODO: Disabled till this is fixed correctly.
 983         //
 984         // Add a new line pragma to restore the proper
 985         // file and line number after the include.
 986         //sItx += String::ToString( "\r\n#line %d \r\n", includeLine );
 987         
 988         dFree(includedText);
 989         manip.insert(q-buffer, sItx);
 990         char* manipBuf = dStrdup(manip.c_str());
 991         p = manipBuf + (q - buffer);
 992         dFree(buffer);
 993         buffer = manipBuf;
 994      }
 995      p = dStrstr(p, "#include");
 996   }
 997   
 998   return buffer;
 999}
1000
1001bool GFXGLShader::_loadShaderFromStream(  GLuint shader, 
1002                                          const Torque::Path &path, 
1003                                          FileStream *s, 
1004                                          const Vector<GFXShaderMacro> &macros )
1005{
1006   Vector<char*> buffers;
1007   Vector<U32> lengths;
1008   
1009   // The GLSL version declaration must go first!
1010   const char *versionDecl = "#version 150\r\n";
1011   buffers.push_back( dStrdup( versionDecl ) );
1012   lengths.push_back( dStrlen( versionDecl ) );
1013
1014   if(GFXGL->mCapabilities.shaderModel5)
1015   {
1016      const char *extension = "#extension GL_ARB_gpu_shader5 : enable\r\n";
1017      buffers.push_back( dStrdup( extension ) );
1018      lengths.push_back( dStrlen( extension ) );
1019   }
1020
1021   const char *newLine = "\r\n";
1022   buffers.push_back( dStrdup( newLine ) );
1023   lengths.push_back( dStrlen( newLine ) );
1024
1025   // Now add all the macros.
1026   for( U32 i = 0; i < macros.size(); i++ )
1027   {
1028      if(macros[i].name.isEmpty())  // TODO OPENGL
1029         continue;
1030
1031      String define = String::ToString( "#define %s %s\n", macros[i].name.c_str(), macros[i].value.c_str() );
1032      buffers.push_back( dStrdup( define.c_str() ) );
1033      lengths.push_back( define.length() );
1034   }
1035   
1036   // Now finally add the shader source.
1037   U32 shaderLen = s->getStreamSize();
1038   char *buffer = _handleIncludes(path, s);
1039   if ( !buffer )
1040      return false;
1041   
1042   buffers.push_back(buffer);
1043   lengths.push_back(shaderLen);
1044   
1045   glShaderSource(shader, buffers.size(), (const GLchar**)const_cast<const char**>(buffers.address()), NULL);
1046
1047#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
1048   FileStream stream;
1049   if ( !stream.open( path.getFullPath()+"_DEBUG", Torque::FS::File::Write ) )
1050   {
1051      AssertISV(false, avar("GFXGLShader::initShader - failed to write debug shader '%s'.", path.getFullPath().c_str()));
1052   }
1053
1054   for(int i = 0; i < buffers.size(); ++i)
1055         stream.writeText(buffers[i]);
1056#endif
1057
1058   // Cleanup the shader source buffer.
1059   for ( U32 i=0; i < buffers.size(); i++ )
1060      dFree( buffers[i] );
1061
1062   glCompileShader(shader);
1063
1064   return true;
1065}
1066
1067bool GFXGLShader::initShader( const Torque::Path &file, 
1068                              bool isVertex, 
1069                              const Vector<GFXShaderMacro> &macros )
1070{
1071   PROFILE_SCOPE(GFXGLShader_CompileShader);
1072   GLuint activeShader = glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
1073   if(isVertex)
1074      mVertexShader = activeShader;
1075   else
1076      mPixelShader = activeShader;
1077   glAttachShader(mProgram, activeShader);
1078   
1079   
1080   // Ok it's not in the shader gen manager, so ask Torque for it
1081   FileStream stream;
1082   if ( !stream.open( file, Torque::FS::File::Read ) )
1083   {
1084      AssertISV(false, avar("GFXGLShader::initShader - failed to open shader '%s'.", file.getFullPath().c_str()));
1085
1086      if ( smLogErrors )
1087         Con::errorf( "GFXGLShader::initShader - Failed to open shader file '%s'.", 
1088            file.getFullPath().c_str() );
1089
1090      return false;
1091   }
1092   
1093   if ( !_loadShaderFromStream( activeShader, file, &stream, macros ) )
1094      return false;
1095   
1096   GLint compile;
1097   glGetShaderiv(activeShader, GL_COMPILE_STATUS, &compile);
1098
1099   // Dump the info log to the console
1100   U32 logLength = 0;
1101   glGetShaderiv(activeShader, GL_INFO_LOG_LENGTH, (GLint*)&logLength);
1102   
1103   GLint compileStatus = GL_TRUE;
1104   if ( logLength )
1105   {
1106      FrameAllocatorMarker fam;
1107      char* log = (char*)fam.alloc(logLength);
1108      glGetShaderInfoLog(activeShader, logLength, NULL, log);
1109
1110      // Always print errors
1111      glGetShaderiv( activeShader, GL_COMPILE_STATUS, &compileStatus );
1112
1113      if ( compileStatus == GL_FALSE )
1114      {
1115         if ( smLogErrors )
1116         {
1117            Con::errorf( "GFXGLShader::initShader - Error compiling shader!" );
1118            Con::errorf( "Program %s: %s", file.getFullPath().c_str(), log );
1119         }
1120      }
1121      else if ( smLogWarnings )
1122         Con::warnf( "Program %s: %s", file.getFullPath().c_str(), log );
1123   }
1124
1125   return compileStatus != GL_FALSE;
1126}
1127
1128/// Returns our list of shader constants, the material can get this and just set the constants it knows about
1129const Vector<GFXShaderConstDesc>& GFXGLShader::getShaderConstDesc() const
1130{
1131   PROFILE_SCOPE(GFXGLShader_GetShaderConstants);
1132   return mConstants;
1133}
1134
1135/// Returns the alignment value for constType
1136U32 GFXGLShader::getAlignmentValue(const GFXShaderConstType constType) const
1137{
1138   // Alignment is the same thing as size for us.
1139   return shaderConstTypeSize(constType);
1140}
1141
1142const String GFXGLShader::describeSelf() const
1143{
1144   String ret;
1145   ret = String::ToString("   Program: %i", mProgram);
1146   ret += String::ToString("   Vertex Path: %s", mVertexFile.getFullPath().c_str());
1147   ret += String::ToString("   Pixel Path: %s", mPixelFile.getFullPath().c_str());
1148   
1149   return ret;
1150}
1151