genericConstBuffer.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "gfx/genericConstBuffer.h"
  24. #include "platform/profiler.h"
  25. #include "core/stream/stream.h"
  26. GenericConstBufferLayout::GenericConstBufferLayout()
  27. {
  28. VECTOR_SET_ASSOCIATION( mParams );
  29. mBufferSize = 0;
  30. mCurrentIndex = 0;
  31. mTimesCleared = 0;
  32. }
  33. void GenericConstBufferLayout::addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue)
  34. {
  35. #ifdef TORQUE_DEBUG
  36. // Make sure we don't have overlapping parameters
  37. S32 start = offset;
  38. S32 end = offset + size;
  39. for (Params::iterator i = mParams.begin(); i != mParams.end(); i++)
  40. {
  41. const ParamDesc& dp = *i;
  42. S32 pstart = dp.offset;
  43. S32 pend = pstart + dp.size;
  44. pstart -= start;
  45. pend -= end;
  46. // This is like a minkowski sum for two line segments, if the newly formed line contains
  47. // the origin, then they intersect
  48. bool intersect = ((pstart >= 0 && 0 >= pend) || ((pend >= 0 && 0 >= pstart)));
  49. AssertFatal(!intersect, "Overlapping shader parameter!");
  50. }
  51. #endif
  52. ParamDesc desc;
  53. desc.name = name;
  54. desc.constType = constType;
  55. desc.offset = offset;
  56. desc.size = size;
  57. desc.arraySize = arraySize;
  58. desc.alignValue = alignValue;
  59. desc.index = mCurrentIndex++;
  60. mParams.push_back(desc);
  61. mBufferSize = getMax(desc.offset + desc.size, mBufferSize);
  62. AssertFatal(mBufferSize, "Empty constant buffer!");
  63. }
  64. bool GenericConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
  65. {
  66. PROFILE_SCOPE(GenericConstBufferLayout_set);
  67. // Shader compilers like to optimize float4x4 uniforms into float3x3s.
  68. // So long as the real paramater is a matrix of-some-type and the data
  69. // passed in is a MatrixF ( which is will be ), we DO NOT have a
  70. // mismatched const type.
  71. AssertFatal( pd.constType == constType ||
  72. (
  73. ( pd.constType == GFXSCT_Float2x2 ||
  74. pd.constType == GFXSCT_Float3x3 ||
  75. pd.constType == GFXSCT_Float3x4 ||
  76. pd.constType == GFXSCT_Float4x3 ||
  77. pd.constType == GFXSCT_Float4x4 ) &&
  78. ( constType == GFXSCT_Float2x2 ||
  79. constType == GFXSCT_Float3x3 ||
  80. constType == GFXSCT_Float3x4 ||
  81. constType == GFXSCT_Float4x3 ||
  82. constType == GFXSCT_Float4x4 )
  83. ), "Mismatched const type!" );
  84. // 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
  85. switch (pd.constType)
  86. {
  87. case GFXSCT_Float2x2 :
  88. case GFXSCT_Float3x3 :
  89. case GFXSCT_Float4x3 :
  90. case GFXSCT_Float4x4 :
  91. return setMatrix(pd, constType, size, data, basePointer);
  92. break;
  93. default :
  94. break;
  95. }
  96. AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
  97. // 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
  98. // 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
  99. // renderInstMgr level, but we can check down here. -BTR
  100. if (dMemcmp(basePointer+pd.offset, data, size) != 0)
  101. {
  102. dMemcpy(basePointer+pd.offset, data, size);
  103. return true;
  104. }
  105. return false;
  106. }
  107. bool GenericConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
  108. {
  109. PROFILE_SCOPE(GenericConstBufferLayout_setMatrix);
  110. // We're generic, so just copy the full MatrixF in
  111. AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
  112. // 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.
  113. // 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
  114. // 4x4 matrix regardless of the target case.
  115. if (dMemcmp(basePointer+pd.offset, data, size) != 0)
  116. {
  117. dMemcpy(basePointer+pd.offset, data, size);
  118. return true;
  119. }
  120. return false;
  121. }
  122. bool GenericConstBufferLayout::getDesc(const String& name, ParamDesc& param) const
  123. {
  124. for (U32 i = 0; i < mParams.size(); i++)
  125. {
  126. if (mParams[i].name.equal(name))
  127. {
  128. param = mParams[i];
  129. return true;
  130. }
  131. }
  132. return false;
  133. }
  134. bool GenericConstBufferLayout::getDesc(const U32 index, ParamDesc& param) const
  135. {
  136. if ( index < mParams.size() )
  137. {
  138. param = mParams[index];
  139. return true;
  140. }
  141. return false;
  142. }
  143. bool GenericConstBufferLayout::write(Stream* s)
  144. {
  145. // Write out the size of the ParamDesc structure as a sanity check.
  146. if (!s->write((U32) sizeof(ParamDesc)))
  147. return false;
  148. // Next, write out the number of elements we've got.
  149. if (!s->write(mParams.size()))
  150. return false;
  151. for (U32 i = 0; i < mParams.size(); i++)
  152. {
  153. s->write(mParams[i].name);
  154. if (!s->write(mParams[i].offset))
  155. return false;
  156. if (!s->write(mParams[i].size))
  157. return false;
  158. U32 t = (U32) mParams[i].constType;
  159. if (!s->write(t))
  160. return false;
  161. if (!s->write(mParams[i].arraySize))
  162. return false;
  163. if (!s->write(mParams[i].alignValue))
  164. return false;
  165. if (!s->write(mParams[i].index))
  166. return false;
  167. }
  168. return true;
  169. }
  170. /// Load this layout from a stream
  171. bool GenericConstBufferLayout::read(Stream* s)
  172. {
  173. U32 structSize;
  174. if (!s->read(&structSize))
  175. return false;
  176. if (structSize != sizeof(ParamDesc))
  177. {
  178. AssertFatal(false, "Invalid shader layout structure size!");
  179. return false;
  180. }
  181. U32 numParams;
  182. if (!s->read(&numParams))
  183. return false;
  184. mParams.setSize(numParams);
  185. mBufferSize = 0;
  186. mCurrentIndex = 0;
  187. for (U32 i = 0; i < mParams.size(); i++)
  188. {
  189. s->read(&mParams[i].name);
  190. if (!s->read(&mParams[i].offset))
  191. return false;
  192. if (!s->read(&mParams[i].size))
  193. return false;
  194. U32 t;
  195. if (!s->read(&t))
  196. return false;
  197. mParams[i].constType = (GFXShaderConstType) t;
  198. if (!s->read(&mParams[i].arraySize))
  199. return false;
  200. if (!s->read(&mParams[i].alignValue))
  201. return false;
  202. if (!s->read(&mParams[i].index))
  203. return false;
  204. mBufferSize = getMax(mParams[i].offset + mParams[i].size, mBufferSize);
  205. mCurrentIndex = getMax(mParams[i].index, mCurrentIndex);
  206. }
  207. mCurrentIndex++;
  208. return true;
  209. }
  210. void GenericConstBufferLayout::clear()
  211. {
  212. mParams.clear();
  213. mBufferSize = 0;
  214. mCurrentIndex = 0;
  215. mTimesCleared++;
  216. }
  217. GenericConstBuffer::GenericConstBuffer(GenericConstBufferLayout* layout)
  218. : mLayout( layout ),
  219. mBuffer( NULL ),
  220. mDirtyStart( U32_MAX ),
  221. mDirtyEnd( 0 )
  222. {
  223. if ( layout && layout->getBufferSize() > 0 )
  224. {
  225. mBuffer = new U8[mLayout->getBufferSize()];
  226. // Always set a default value, that way our isEqual checks
  227. // will work in release as well.
  228. dMemset( mBuffer, 0xFFFF, mLayout->getBufferSize() );
  229. #ifdef TORQUE_DEBUG
  230. // Clear the debug assignment tracking.
  231. mWasAssigned.setSize( layout->getParameterCount() );
  232. dMemset( mWasAssigned.address(), 0, mWasAssigned.memSize() );
  233. #endif
  234. }
  235. }
  236. GenericConstBuffer::~GenericConstBuffer()
  237. {
  238. delete [] mBuffer;
  239. }
  240. #ifdef TORQUE_DEBUG
  241. void GenericConstBuffer::assertUnassignedConstants( const char *shaderName )
  242. {
  243. for ( U32 i=0; i < mWasAssigned.size(); i++ )
  244. {
  245. if ( mWasAssigned[i] )
  246. continue;
  247. GenericConstBufferLayout::ParamDesc pd;
  248. mLayout->getDesc( i, pd );
  249. // Assert on the unassigned constant.
  250. //AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!",
  251. // pd.name.c_str(), shaderName ) );
  252. }
  253. }
  254. #endif