Torque3D Documentation / _generateds / genericConstBuffer.cpp

genericConstBuffer.cpp

Engine/source/gfx/genericConstBuffer.cpp

More...

Detailed Description

  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/genericConstBuffer.h"
 26
 27#include "platform/profiler.h"
 28#include "core/stream/stream.h"
 29
 30
 31GenericConstBufferLayout::GenericConstBufferLayout()
 32{
 33   VECTOR_SET_ASSOCIATION( mParams );
 34
 35   mBufferSize = 0;
 36   mCurrentIndex = 0;
 37   mTimesCleared = 0;
 38}
 39
 40void GenericConstBufferLayout::addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue)
 41{
 42#ifdef TORQUE_DEBUG
 43   // Make sure we don't have overlapping parameters
 44   S32 start = offset;
 45   S32 end = offset + size;
 46   for (Params::iterator i = mParams.begin(); i != mParams.end(); i++)
 47   {
 48      const ParamDesc& dp = *i;
 49      S32 pstart = dp.offset;
 50      S32 pend = pstart + dp.size;
 51      pstart -= start;
 52      pend -= end;
 53      // This is like a minkowski sum for two line segments, if the newly formed line contains
 54      // the origin, then they intersect
 55      bool intersect = ((pstart >= 0 && 0 >= pend) || ((pend >= 0 && 0 >= pstart)));
 56      AssertFatal(!intersect, "Overlapping shader parameter!");
 57   }
 58#endif
 59   ParamDesc desc;
 60   desc.name = name;
 61   desc.constType = constType;
 62   desc.offset = offset;
 63   desc.size = size;
 64   desc.arraySize = arraySize;
 65   desc.alignValue = alignValue;
 66   desc.index = mCurrentIndex++;
 67   mParams.push_back(desc);
 68   mBufferSize = getMax(desc.offset + desc.size, mBufferSize);
 69   AssertFatal(mBufferSize, "Empty constant buffer!");
 70}
 71
 72bool GenericConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
 73{
 74   PROFILE_SCOPE(GenericConstBufferLayout_set);
 75
 76   // Shader compilers like to optimize float4x4 uniforms into float3x3s.
 77   // So long as the real paramater is a matrix of-some-type and the data
 78   // passed in is a MatrixF ( which is will be ), we DO NOT have a
 79   // mismatched const type.
 80   AssertFatal( pd.constType == constType || 
 81               ( 
 82                 ( pd.constType == GFXSCT_Float2x2 || 
 83                   pd.constType == GFXSCT_Float3x3 || 
 84                   pd.constType == GFXSCT_Float3x4 ||  
 85                   pd.constType == GFXSCT_Float4x3 || 
 86                   pd.constType == GFXSCT_Float4x4 ) && 
 87                 ( constType == GFXSCT_Float2x2 || 
 88                   constType == GFXSCT_Float3x3 ||  
 89                   constType == GFXSCT_Float3x4 ||  
 90                   constType == GFXSCT_Float4x3 ||
 91                   constType == GFXSCT_Float4x4 )
 92               ), "Mismatched const type!" );
 93
 94   // 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
 95   switch (pd.constType)
 96   {
 97   case GFXSCT_Float2x2 :
 98   case GFXSCT_Float3x3 :
 99   case GFXSCT_Float4x3 :
100   case GFXSCT_Float4x4 :
101      return setMatrix(pd, constType, size, data, basePointer);
102      break;
103   default :
104      break;
105   }
106
107   AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
108
109   // 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 
110   // 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
111   // renderInstMgr level, but we can check down here. -BTR
112   if (dMemcmp(basePointer+pd.offset, data, size) != 0)      
113   {
114      dMemcpy(basePointer+pd.offset, data, size);      
115      return true;
116   }   
117   return false;
118}
119
120bool GenericConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
121{
122   PROFILE_SCOPE(GenericConstBufferLayout_setMatrix);
123
124   // We're generic, so just copy the full MatrixF in
125   AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
126
127   // 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.
128   // 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
129   // 4x4 matrix regardless of the target case.
130
131   if (dMemcmp(basePointer+pd.offset, data, size) != 0)
132   {      
133      dMemcpy(basePointer+pd.offset, data, size);         
134      return true;
135   }
136      
137   return false;
138}
139
140bool GenericConstBufferLayout::getDesc(const String& name, ParamDesc& param) const
141{
142   for (U32 i = 0; i < mParams.size(); i++)
143   {
144      if (mParams[i].name.equal(name))
145      {
146         param = mParams[i];
147         return true;
148      }
149   } 
150   return false;
151}
152
153bool GenericConstBufferLayout::getDesc(const U32 index, ParamDesc& param) const
154{
155   if ( index < mParams.size() )
156   {
157      param = mParams[index];
158      return true;
159   }
160
161   return false;
162}
163
164bool GenericConstBufferLayout::write(Stream* s)
165{
166   // Write out the size of the ParamDesc structure as a sanity check.
167   if (!s->write((U32) sizeof(ParamDesc)))
168      return false;
169   // Next, write out the number of elements we've got.
170   if (!s->write(mParams.size()))
171      return false;
172   for (U32 i = 0; i < mParams.size(); i++)
173   {
174      s->write(mParams[i].name);
175         
176      if (!s->write(mParams[i].offset))
177         return false;
178      if (!s->write(mParams[i].size))
179         return false;
180      U32 t = (U32) mParams[i].constType;
181      if (!s->write(t))
182         return false;
183      if (!s->write(mParams[i].arraySize))
184         return false;
185      if (!s->write(mParams[i].alignValue))
186         return false;
187      if (!s->write(mParams[i].index))
188         return false;
189   }
190   return true;
191}
192
193/// Load this layout from a stream
194bool GenericConstBufferLayout::read(Stream* s)
195{
196   U32 structSize;
197   if (!s->read(&structSize))
198      return false;
199   if (structSize != sizeof(ParamDesc))
200   {
201      AssertFatal(false, "Invalid shader layout structure size!");
202      return false;
203   }
204   U32 numParams;
205   if (!s->read(&numParams))
206      return false;
207   mParams.setSize(numParams);
208   mBufferSize = 0;
209   mCurrentIndex = 0;
210   for (U32 i = 0; i < mParams.size(); i++)
211   {
212      s->read(&mParams[i].name);         
213      if (!s->read(&mParams[i].offset))
214         return false;
215      if (!s->read(&mParams[i].size))
216         return false;
217      U32 t;
218      if (!s->read(&t))
219         return false;
220      mParams[i].constType = (GFXShaderConstType) t;
221      if (!s->read(&mParams[i].arraySize))
222         return false;
223      if (!s->read(&mParams[i].alignValue))
224         return false;
225      if (!s->read(&mParams[i].index))
226         return false;
227      mBufferSize = getMax(mParams[i].offset + mParams[i].size, mBufferSize);
228      mCurrentIndex = getMax(mParams[i].index, mCurrentIndex);
229   }
230   mCurrentIndex++;
231   return true;
232}
233
234void GenericConstBufferLayout::clear()
235{
236   mParams.clear();    
237   mBufferSize = 0;
238   mCurrentIndex = 0;
239   mTimesCleared++;
240}
241
242
243GenericConstBuffer::GenericConstBuffer(GenericConstBufferLayout* layout)
244   :  mLayout( layout ),
245      mBuffer( NULL ),
246      mDirtyStart( U32_MAX ),
247      mDirtyEnd( 0 )
248{
249   if ( layout && layout->getBufferSize() > 0 )
250   {
251      mBuffer = new U8[mLayout->getBufferSize()];   
252
253      // Always set a default value, that way our isEqual checks
254      // will work in release as well.
255      dMemset( mBuffer, 0xFFFF, mLayout->getBufferSize() );
256
257      #ifdef TORQUE_DEBUG
258      
259         // Clear the debug assignment tracking.
260         mWasAssigned.setSize( layout->getParameterCount() );
261         dMemset( mWasAssigned.address(), 0, mWasAssigned.memSize() );
262
263      #endif
264   }
265}
266
267GenericConstBuffer::~GenericConstBuffer() 
268{
269   delete [] mBuffer;
270}
271
272#ifdef TORQUE_DEBUG
273
274void GenericConstBuffer::assertUnassignedConstants( const char *shaderName )
275{
276   for ( U32 i=0; i < mWasAssigned.size(); i++ )
277   {
278      if ( mWasAssigned[i] )
279         continue;
280
281      GenericConstBufferLayout::ParamDesc pd;
282      mLayout->getDesc( i, pd );
283
284      // Assert on the unassigned constant.
285      //AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!",
286      //   pd.name.c_str(), shaderName ) );
287   }
288}
289
290#endif
291