| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 | //-----------------------------------------------------------------------------// Copyright (c) 2012 GarageGames, LLC//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS// IN THE SOFTWARE.//-----------------------------------------------------------------------------#include "platform/platform.h"#include "gfx/genericConstBuffer.h"#include "platform/profiler.h"#include "core/stream/stream.h"GenericConstBufferLayout::GenericConstBufferLayout(){   VECTOR_SET_ASSOCIATION( mParams );   mBufferSize = 0;   mCurrentIndex = 0;   mTimesCleared = 0;}void GenericConstBufferLayout::addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue){#ifdef TORQUE_DEBUG   // Make sure we don't have overlapping parameters   S32 start = offset;   S32 end = offset + size;   for (Params::iterator i = mParams.begin(); i != mParams.end(); i++)   {      const ParamDesc& dp = *i;      S32 pstart = dp.offset;      S32 pend = pstart + dp.size;      pstart -= start;      pend -= end;      // This is like a minkowski sum for two line segments, if the newly formed line contains      // the origin, then they intersect      bool intersect = ((pstart >= 0 && 0 >= pend) || ((pend >= 0 && 0 >= pstart)));      AssertFatal(!intersect, "Overlapping shader parameter!");   }#endif   ParamDesc desc;   desc.name = name;   desc.constType = constType;   desc.offset = offset;   desc.size = size;   desc.arraySize = arraySize;   desc.alignValue = alignValue;   desc.index = mCurrentIndex++;   mParams.push_back(desc);   mBufferSize = getMax(desc.offset + desc.size, mBufferSize);   AssertFatal(mBufferSize, "Empty constant buffer!");}bool GenericConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer){   PROFILE_SCOPE(GenericConstBufferLayout_set);   // Shader compilers like to optimize float4x4 uniforms into float3x3s.   // So long as the real paramater is a matrix of-some-type and the data   // passed in is a MatrixF ( which is will be ), we DO NOT have a   // mismatched const type.   AssertFatal( pd.constType == constType ||                (                  ( pd.constType == GFXSCT_Float2x2 ||                    pd.constType == GFXSCT_Float3x3 ||                    pd.constType == GFXSCT_Float3x4 ||                     pd.constType == GFXSCT_Float4x3 ||                    pd.constType == GFXSCT_Float4x4 ) &&                  ( constType == GFXSCT_Float2x2 ||                    constType == GFXSCT_Float3x3 ||                     constType == GFXSCT_Float3x4 ||                     constType == GFXSCT_Float4x3 ||                   constType == GFXSCT_Float4x4 )               ), "Mismatched const type!" );   // 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   switch (pd.constType)   {   case GFXSCT_Float2x2 :   case GFXSCT_Float3x3 :   case GFXSCT_Float4x3 :   case GFXSCT_Float4x4 :      return setMatrix(pd, constType, size, data, basePointer);      break;   default :      break;   }   AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");   // 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    // 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   // renderInstMgr level, but we can check down here. -BTR   if (dMemcmp(basePointer+pd.offset, data, size) != 0)         {      dMemcpy(basePointer+pd.offset, data, size);            return true;   }      return false;}bool GenericConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer){   PROFILE_SCOPE(GenericConstBufferLayout_setMatrix);   // We're generic, so just copy the full MatrixF in   AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");   // Matrices are an annoying case because of the alignment issues.  There are alignment issues in the matrix itself, and then potential inter matrices alignment issues.   // So GL and DX will need to derive their own GenericConstBufferLayout classes and override this method to deal with that stuff.  For GenericConstBuffer, copy the whole   // 4x4 matrix regardless of the target case.   if (dMemcmp(basePointer+pd.offset, data, size) != 0)   {            dMemcpy(basePointer+pd.offset, data, size);               return true;   }         return false;}bool GenericConstBufferLayout::getDesc(const String& name, ParamDesc& param) const{   for (U32 i = 0; i < mParams.size(); i++)   {      if (mParams[i].name.equal(name))      {         param = mParams[i];         return true;      }   }    return false;}bool GenericConstBufferLayout::getDesc(const U32 index, ParamDesc& param) const{   if ( index < mParams.size() )   {      param = mParams[index];      return true;   }   return false;}bool GenericConstBufferLayout::write(Stream* s){   // Write out the size of the ParamDesc structure as a sanity check.   if (!s->write((U32) sizeof(ParamDesc)))      return false;   // Next, write out the number of elements we've got.   if (!s->write(mParams.size()))      return false;   for (U32 i = 0; i < mParams.size(); i++)   {      s->write(mParams[i].name);               if (!s->write(mParams[i].offset))         return false;      if (!s->write(mParams[i].size))         return false;      U32 t = (U32) mParams[i].constType;      if (!s->write(t))         return false;      if (!s->write(mParams[i].arraySize))         return false;      if (!s->write(mParams[i].alignValue))         return false;      if (!s->write(mParams[i].index))         return false;   }   return true;}/// Load this layout from a streambool GenericConstBufferLayout::read(Stream* s){   U32 structSize;   if (!s->read(&structSize))      return false;   if (structSize != sizeof(ParamDesc))   {      AssertFatal(false, "Invalid shader layout structure size!");      return false;   }   U32 numParams;   if (!s->read(&numParams))      return false;   mParams.setSize(numParams);   mBufferSize = 0;   mCurrentIndex = 0;   for (U32 i = 0; i < mParams.size(); i++)   {      s->read(&mParams[i].name);               if (!s->read(&mParams[i].offset))         return false;      if (!s->read(&mParams[i].size))         return false;      U32 t;      if (!s->read(&t))         return false;      mParams[i].constType = (GFXShaderConstType) t;      if (!s->read(&mParams[i].arraySize))         return false;      if (!s->read(&mParams[i].alignValue))         return false;      if (!s->read(&mParams[i].index))         return false;      mBufferSize = getMax(mParams[i].offset + mParams[i].size, mBufferSize);      mCurrentIndex = getMax(mParams[i].index, mCurrentIndex);   }   mCurrentIndex++;   return true;}void GenericConstBufferLayout::clear(){   mParams.clear();       mBufferSize = 0;   mCurrentIndex = 0;   mTimesCleared++;}GenericConstBuffer::GenericConstBuffer(GenericConstBufferLayout* layout)   :  mBuffer( NULL ),      mLayout( layout ),      mDirtyStart( U32_MAX ),      mDirtyEnd( 0 ){   if ( layout && layout->getBufferSize() > 0 )   {      mBuffer = new U8[mLayout->getBufferSize()];         // Always set a default value, that way our isEqual checks      // will work in release as well.      dMemset( mBuffer, 0xFFFF, mLayout->getBufferSize() );      #ifdef TORQUE_DEBUG               // Clear the debug assignment tracking.         mWasAssigned.setSize( layout->getParameterCount() );         dMemset( mWasAssigned.address(), 0, mWasAssigned.memSize() );      #endif   }}GenericConstBuffer::~GenericConstBuffer() {   delete [] mBuffer;}#ifdef TORQUE_DEBUGvoid GenericConstBuffer::assertUnassignedConstants( const char *shaderName ){   for ( U32 i=0; i < mWasAssigned.size(); i++ )   {      if ( mWasAssigned[i] )         continue;      GenericConstBufferLayout::ParamDesc pd;      mLayout->getDesc( i, pd );      // Assert on the unassigned constant.      AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!",         pd.name.c_str(), shaderName ) );   }}#endif
 |