genericConstBuffer.h
Engine/source/gfx/genericConstBuffer.h
Classes:
class
This class manages shader constant data in a system memory buffer.
class
This class defines the memory layout for a GenericConstBuffer.
class
Describes the parameters we contain.
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#ifndef _GENERICCONSTBUFFER_H_ 25#define _GENERICCONSTBUFFER_H_ 26 27#ifndef _TORQUE_STRING_H_ 28#include "core/util/str.h" 29#endif 30#ifndef _TDICTIONARY_H_ 31#include "core/util/tDictionary.h" 32#endif 33#ifndef _TVECTOR_H_ 34#include "core/util/tVector.h" 35#endif 36#ifndef _ALIGNEDARRAY_H_ 37#include "core/util/tAlignedArray.h" 38#endif 39#ifndef _COLOR_H_ 40#include "core/color.h" 41#endif 42#ifndef _MMATRIX_H_ 43#include "math/mMatrix.h" 44#endif 45#ifndef _MPOINT2_H_ 46#include "math/mPoint2.h" 47#endif 48#ifndef _GFXENUMS_H_ 49#include "gfx/gfxEnums.h" 50#endif 51 52class Stream; 53 54 55/// This class defines the memory layout for a GenericConstBuffer. 56class GenericConstBufferLayout 57{ 58public: 59 /// Describes the parameters we contain 60 struct ParamDesc 61 { 62 ParamDesc() 63 : name(), 64 offset( 0 ), 65 size( 0 ), 66 constType( GFXSCT_Float ), 67 arraySize( 0 ), 68 alignValue( 0 ), 69 index( 0 ) 70 { 71 } 72 73 void clear() 74 { 75 name = String::EmptyString; 76 offset = 0; 77 size = 0; 78 constType = GFXSCT_Float; 79 arraySize = 0; 80 alignValue = 0; 81 index = 0; 82 } 83 84 /// Parameter name 85 String name; 86 87 /// Offset into the memory block 88 U32 offset; 89 90 /// Size of the block 91 U32 size; 92 93 /// Type of data 94 GFXShaderConstType constType; 95 96 // For arrays, how many elements 97 U32 arraySize; 98 99 // Array element alignment value 100 U32 alignValue; 101 102 /// 0 based index of this param, in order of addParameter calls. 103 U32 index; 104 }; 105 106 GenericConstBufferLayout(); 107 virtual ~GenericConstBufferLayout() {} 108 109 /// Add a parameter to the buffer 110 virtual void addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue); 111 112 /// Get the size of the buffer 113 inline U32 getBufferSize() const { return mBufferSize; } 114 115 /// Get the number of parameters 116 inline U32 getParameterCount() const { return mParams.size(); } 117 118 /// Returns the ParamDesc of a parameter 119 bool getDesc(const String& name, ParamDesc& param) const; 120 121 /// Returns the ParamDesc of a parameter 122 bool getDesc(const U32 index, ParamDesc& param) const; 123 124 /// Set a parameter, given a base pointer 125 virtual bool set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer); 126 127 /// Save this layout to a stream 128 bool write(Stream* s); 129 130 /// Load this layout from a stream 131 bool read(Stream* s); 132 133 /// Restore to initial state. 134 void clear(); 135 136protected: 137 138 /// Set a matrix, given a base pointer. 139 virtual bool setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer); 140 141 /// Vector of parameter descriptions. 142 typedef Vector<ParamDesc> Params; 143 144 /// Vector of parameter descriptions. 145 Params mParams; 146 U32 mBufferSize; 147 U32 mCurrentIndex; 148 149 // This if for debugging shader reloading and can be removed later. 150 U32 mTimesCleared; 151}; 152 153 154/// This class manages shader constant data in a system memory buffer. It is 155/// used by device specific classes for batching together many constant changes 156/// which are then copied to the device thru a single API call. 157/// 158/// @see GenericConstBufferLayout 159/// 160class GenericConstBuffer 161{ 162public: 163 GenericConstBuffer(GenericConstBufferLayout* layout); 164 ~GenericConstBuffer(); 165 166 /// @name Set shader constant values 167 /// @{ 168 /// Actually set shader constant values 169 /// @param name Name of the constant, this should be a name contained in the array returned in getShaderConstDesc, 170 /// if an invalid name is used, its ignored, but it's not an error. 171 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const F32 f) { internalSet(pd, GFXSCT_Float, sizeof(F32), &f); } 172 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2F& fv) { internalSet(pd, GFXSCT_Float2, sizeof(Point2F), &fv); } 173 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3F& fv) { internalSet(pd, GFXSCT_Float3, sizeof(Point3F), &fv); } 174 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4F& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); } 175 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const PlaneF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(PlaneF), &fv); } 176 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const LinearColorF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); } 177 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const S32 f) { internalSet(pd, GFXSCT_Int, sizeof(S32), &f); } 178 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2I& fv) { internalSet(pd, GFXSCT_Int2, sizeof(Point2I), &fv); } 179 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3I& fv) { internalSet(pd, GFXSCT_Int3, sizeof(Point3I), &fv); } 180 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4I& fv) { internalSet(pd, GFXSCT_Int4, sizeof(Point4I), &fv); } 181 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<F32>& fv) { internalSet(pd, GFXSCT_Float, fv.getElementSize() * fv.size(), fv.getBuffer()); } 182 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point2F>& fv) { internalSet(pd, GFXSCT_Float2, fv.getElementSize() * fv.size(), fv.getBuffer()); } 183 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point3F>& fv) { internalSet(pd, GFXSCT_Float3, fv.getElementSize() * fv.size(), fv.getBuffer()); } 184 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point4F>& fv) { internalSet(pd, GFXSCT_Float4, fv.getElementSize() * fv.size(), fv.getBuffer()); } 185 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<S32>& fv) { internalSet(pd, GFXSCT_Int, fv.getElementSize() * fv.size(), fv.getBuffer()); } 186 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point2I>& fv) { internalSet(pd, GFXSCT_Int2, fv.getElementSize() * fv.size(), fv.getBuffer()); } 187 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point3I>& fv) { internalSet(pd, GFXSCT_Int3, fv.getElementSize() * fv.size(), fv.getBuffer()); } 188 inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point4I>& fv) { internalSet(pd, GFXSCT_Int4, fv.getElementSize() * fv.size(), fv.getBuffer()); } 189 190 inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF& mat, const GFXShaderConstType matrixType ) 191 { 192 AssertFatal( matrixType == GFXSCT_Float2x2 || 193 matrixType == GFXSCT_Float3x3 || 194 matrixType == GFXSCT_Float3x4 || 195 matrixType == GFXSCT_Float4x3 || 196 matrixType == GFXSCT_Float4x4, 197 "GenericConstBuffer::set() - Invalid matrix type!" ); 198 199 internalSet( pd, matrixType, sizeof(MatrixF), &mat ); 200 } 201 202 inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType ) 203 { 204 AssertFatal( matrixType == GFXSCT_Float2x2 || 205 matrixType == GFXSCT_Float3x3 || 206 matrixType == GFXSCT_Float3x4 || 207 matrixType == GFXSCT_Float4x3 || 208 matrixType == GFXSCT_Float4x4, 209 "GenericConstBuffer::set() - Invalid matrix type!" ); 210 211 internalSet( pd, matrixType, sizeof(MatrixF)*arraySize, mat ); 212 } 213 214 /// Gets the dirty buffer range and clears the dirty 215 /// state at the same time. 216 inline const U8* getDirtyBuffer( U32 *start, U32 *size ); 217 218 /// Gets the entire buffer ignoring dirty range 219 inline const U8* getEntireBuffer(); 220 221 /// Sets the entire buffer as dirty or clears the dirty state. 222 inline void setDirty( bool dirty ); 223 224 /// Returns true if the buffer has been modified since the 225 /// last call to getDirtyBuffer or setDirty. The buffer is 226 /// not dirty on initial creation. 227 /// 228 /// @see getDirtyBuffer 229 /// @see setDirty 230 inline bool isDirty() const { return mDirtyEnd != 0; } 231 232 /// Returns true if have the same layout and hold the same 233 /// data as the input buffer. 234 inline bool isEqual( const GenericConstBuffer *buffer ) const; 235 236 /// Returns our layout object. 237 inline GenericConstBufferLayout* getLayout() const { return mLayout; } 238 239 #ifdef TORQUE_DEBUG 240 241 /// Helper function used to assert on unset constants. 242 void assertUnassignedConstants( const char *shaderName ); 243 244 #endif 245 246protected: 247 248 /// Returns a pointer to the raw buffer 249 inline const U8* getBuffer() const { return mBuffer; } 250 251 /// Called by the inlined set functions above to do the 252 /// real dirty work of copying the data to the right location 253 /// within the buffer. 254 inline void internalSet( const GenericConstBufferLayout::ParamDesc &pd, 255 const GFXShaderConstType constType, 256 const U32 size, 257 const void *data ); 258 259 /// The buffer layout. 260 GenericConstBufferLayout *mLayout; 261 262 /// The pointer to the contant store or 263 /// NULL if the layout is empty. 264 U8 *mBuffer; 265 266 /// The byte offset to the start of the dirty 267 /// range within the buffer or U32_MAX if the 268 /// buffer is not dirty. 269 U32 mDirtyStart; 270 271 /// The btye offset to the end of the dirty 272 /// range within the buffer or 0 if the buffer 273 /// is not dirty. 274 U32 mDirtyEnd; 275 276 277 #ifdef TORQUE_DEBUG 278 279 /// A vector used to keep track if a constant 280 /// has beed assigned a value or not. 281 /// 282 /// @see assertUnassignedConstants 283 Vector<bool> mWasAssigned; 284 285 #endif 286}; 287 288 289// NOTE: These inlines below are here to get the very best possible 290// performance when setting the device shader constants and can be 291// called 4000-8000 times per frame or more. 292// 293// You need a very good reason to consider changing them. 294 295inline void GenericConstBuffer::internalSet( const GenericConstBufferLayout::ParamDesc &pd, 296 const GFXShaderConstType constType, 297 const U32 size, 298 const void *data ) 299{ 300 // NOTE: We should have never gotten here if the buffer 301 // was null as no valid shader constant could have been 302 // assigned. 303 // 304 // If this happens its a bug in another part of the code. 305 // 306 AssertFatal( mBuffer, "GenericConstBuffer::internalSet - The buffer is NULL!" ); 307 308 if ( mLayout->set( pd, constType, size, data, mBuffer ) ) 309 { 310 #ifdef TORQUE_DEBUG 311 312 // Update the debug assignment tracking. 313 mWasAssigned[ pd.index ] = true; 314 315 #endif 316 317 // Keep track of the dirty range so it can be queried 318 // later in GenericConstBuffer::getDirtyBuffer. 319 mDirtyStart = getMin( pd.offset, mDirtyStart ); 320 mDirtyEnd = getMax( pd.offset + pd.size, mDirtyEnd ); 321 } 322} 323 324inline void GenericConstBuffer::setDirty( bool dirty ) 325{ 326 if ( !mBuffer ) 327 return; 328 329 if ( dirty ) 330 { 331 mDirtyStart = 0; 332 mDirtyEnd = mLayout->getBufferSize(); 333 } 334 else if ( !dirty ) 335 { 336 mDirtyStart = U32_MAX; 337 mDirtyEnd = 0; 338 } 339} 340 341inline const U8* GenericConstBuffer::getDirtyBuffer( U32 *start, U32 *size ) 342{ 343 AssertFatal( isDirty(), "GenericConstBuffer::getDirtyBuffer() - Buffer is not dirty!" ); 344 AssertFatal( mDirtyEnd > mDirtyStart, "GenericConstBuffer::getDirtyBuffer() - Dirty range is invalid!" ); 345 AssertFatal( mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!" ); 346 347 // Use the area we calculated during internalSet. 348 *size = mDirtyEnd - mDirtyStart; 349 *start = mDirtyStart; 350 const U8 *buffer = mBuffer + mDirtyStart; 351 352 // Clear the dirty state while we're here. 353 mDirtyStart = U32_MAX; 354 mDirtyEnd = 0; 355 356 return buffer; 357} 358 359inline const U8* GenericConstBuffer::getEntireBuffer() 360{ 361 AssertFatal(mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!"); 362 363 return mBuffer; 364} 365 366inline bool GenericConstBuffer::isEqual( const GenericConstBuffer *buffer ) const 367{ 368 U32 bsize = mLayout->getBufferSize(); 369 if ( bsize != buffer->mLayout->getBufferSize() ) 370 return false; 371 372 return dMemcmp( mBuffer, buffer->getBuffer(), bsize ) == 0; 373} 374 375#endif // _GENERICCONSTBUFFER_H_ 376