BsGpuParam.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #pragma once
  2. #include "BsCorePrerequisites.h"
  3. #include "BsGpuParamDesc.h"
  4. #include "BsGpuParamBlock.h"
  5. #include "BsDebug.h"
  6. #include "BsException.h"
  7. #include "BsMatrix3.h"
  8. #include "BsMatrix4.h"
  9. namespace BansheeEngine
  10. {
  11. /**
  12. * @brief A handle that allows you to set a GpuProgram parameter. Internally keeps a reference to the
  13. * GPU parameter buffer and the necessary offsets. You should specialize this type for specific
  14. * parameter types.
  15. *
  16. * Object of this type must be returned by a Material. Setting/Getting parameter values will internally
  17. * access a GPU parameter buffer attached to the Material this parameter was created from. Anything
  18. * rendered with that material will then use those set values.
  19. *
  20. * @note Normally you can set a GpuProgram parameter by calling various set/get methods on a Material.
  21. * This class primarily used an as optimization in performance critical bits of code
  22. * where it is important to locate and set parameters quickly without any lookups
  23. * (Mentioned set/get methods expect a parameter name). You just retrieve the handle
  24. * once and then set the parameter value many times with minimal performance impact.
  25. *
  26. * @see Material
  27. *
  28. * @note Sim thread only.
  29. */
  30. template<class T>
  31. class BS_CORE_EXPORT GpuDataParamBase
  32. {
  33. private:
  34. friend class GpuParams;
  35. /**
  36. * @brief Internal data that is shared between GpuDataParam instances.
  37. */
  38. struct InternalData
  39. {
  40. InternalData(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks, bool transpose)
  41. :paramDesc(paramDesc), paramBlocks(paramBlocks), transpose(transpose), isDestroyed(false)
  42. { }
  43. InternalData()
  44. :paramDesc(nullptr), paramBlocks(nullptr), transpose(false), isDestroyed(true)
  45. { }
  46. ~InternalData()
  47. { }
  48. GpuParamDataDesc* paramDesc;
  49. GpuParamBlock** paramBlocks;
  50. bool transpose;
  51. bool isDestroyed;
  52. };
  53. /**
  54. * @brief Policy class that allows us to re-use this template class for matrices which might
  55. * need transposing, and other types which do not. Matrix needs to be transposed for
  56. * certain render systems depending on how they store them in memory.
  57. */
  58. template<class Type>
  59. struct TransposePolicy
  60. {
  61. static Type transpose(const Type& value) { return value; }
  62. static bool transposeEnabled(bool enabled) { return false; }
  63. };
  64. /**
  65. * @brief Transpose policy for 3x3 matrix.
  66. */
  67. template<>
  68. struct TransposePolicy<Matrix3>
  69. {
  70. static Matrix3 transpose(const Matrix3& value) { return value.transpose(); }
  71. static bool transposeEnabled(bool enabled) { return enabled; }
  72. };
  73. /**
  74. * @brief Transpose policy for 4x4 matrix.
  75. */
  76. template<>
  77. struct TransposePolicy<Matrix4>
  78. {
  79. static Matrix4 transpose(const Matrix4& value) { return value.transpose(); }
  80. static bool transposeEnabled(bool enabled) { return enabled; }
  81. };
  82. public:
  83. GpuDataParamBase()
  84. :mData(bs_shared_ptr<InternalData>())
  85. { }
  86. /**
  87. * @brief Sets a parameter value at the specified array index. If parameter does not
  88. * contain an array leave the index at 0.
  89. *
  90. * @note Like with all GPU parameters, the actual GPU buffer will not be updated until rendering
  91. * with material this parameter was created from starts on the core thread.
  92. */
  93. void set(const T& value, UINT32 arrayIdx = 0)
  94. {
  95. if(mData->isDestroyed)
  96. BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
  97. GpuParamDataDesc* paramDesc = mData->paramDesc;
  98. #if BS_DEBUG_MODE
  99. if(arrayIdx >= paramDesc->arraySize)
  100. {
  101. BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
  102. toString(paramDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
  103. }
  104. #endif
  105. UINT32 elementSizeBytes = paramDesc->elementSize * sizeof(UINT32);
  106. UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T)); // Truncate if it doesn't fit within parameter size
  107. GpuParamBlock* paramBlock = mData->paramBlocks[paramDesc->paramBlockSlot];
  108. if(TransposePolicy<T>::transposeEnabled(mData->transpose))
  109. {
  110. T transposed = TransposePolicy<T>::transpose(value);
  111. paramBlock->write((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), &transposed, sizeBytes);
  112. }
  113. else
  114. paramBlock->write((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
  115. // Set unused bytes to 0
  116. if(sizeBytes < elementSizeBytes)
  117. {
  118. UINT32 diffSize = elementSizeBytes - sizeBytes;
  119. paramBlock->zeroOut((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32) + sizeBytes, diffSize);
  120. }
  121. }
  122. /**
  123. * @brief Returns a value of a parameter at the specified array index. If parameter does not
  124. * contain an array leave the index at 0.
  125. *
  126. * @note No GPU reads are done. Data returned was cached when it was written.
  127. */
  128. T get(UINT32 arrayIdx = 0)
  129. {
  130. if(mData->isDestroyed)
  131. BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
  132. GpuParamDataDesc* paramDesc = mData->paramDesc;
  133. #if BS_DEBUG_MODE
  134. if(arrayIdx >= paramDesc->arraySize)
  135. {
  136. BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
  137. toString(paramDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
  138. }
  139. #endif
  140. UINT32 elementSizeBytes = paramDesc->elementSize * sizeof(UINT32);
  141. UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T));
  142. GpuParamBlock* paramBlock = mData->paramBlocks[paramDesc->paramBlockSlot];
  143. T value;
  144. paramBlock->read((paramDesc->cpuMemOffset + arrayIdx * paramDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
  145. if(TransposePolicy<T>::transposeEnabled(mData->transpose))
  146. return TransposePolicy<T>::transpose(value);
  147. else
  148. return value;
  149. }
  150. /**
  151. * @brief Called by the material when this handle is no longer valid (shader changed or material
  152. * got destroyed).
  153. */
  154. void _destroy()
  155. {
  156. mData->isDestroyed = true;
  157. }
  158. private:
  159. GpuDataParamBase(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks, bool transpose)
  160. :mData(bs_shared_ptr<InternalData>(paramDesc, paramBlocks, transpose))
  161. { }
  162. private:
  163. std::shared_ptr<InternalData> mData;
  164. };
  165. typedef GpuDataParamBase<float> GpuParamFloat;
  166. typedef GpuDataParamBase<Vector2> GpuParamVec2;
  167. typedef GpuDataParamBase<Vector3> GpuParamVec3;
  168. typedef GpuDataParamBase<Vector4> GpuParamVec4;
  169. typedef GpuDataParamBase<Matrix3> GpuParamMat3;
  170. typedef GpuDataParamBase<Matrix4> GpuParamMat4;
  171. /**
  172. * @copydoc GpuDataParamBase
  173. */
  174. class BS_CORE_EXPORT GpuParamStruct
  175. {
  176. private:
  177. friend class GpuParams;
  178. struct InternalData
  179. {
  180. InternalData(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks);
  181. InternalData();
  182. ~InternalData();
  183. GpuParamDataDesc* paramDesc;
  184. GpuParamBlock** paramBlocks;
  185. bool isDestroyed;
  186. };
  187. public:
  188. GpuParamStruct();
  189. /**
  190. * @copydoc GpuDataParamBase::set
  191. */
  192. void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
  193. /**
  194. * @copydoc GpuDataParamBase::get
  195. */
  196. void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
  197. /**
  198. * @brief Returns the size of the struct in bytes.
  199. */
  200. UINT32 getElementSize() const;
  201. /**
  202. * @copydoc GpuDataParamBase::_destroy
  203. */
  204. void _destroy();
  205. private:
  206. GpuParamStruct(GpuParamDataDesc* paramDesc, GpuParamBlock** paramBlocks);
  207. private:
  208. std::shared_ptr<InternalData> mData;
  209. };
  210. /**
  211. * @copydoc GpuDataParamBase
  212. */
  213. class BS_CORE_EXPORT GpuParamTexture
  214. {
  215. private:
  216. friend class GpuParams;
  217. struct InternalData
  218. {
  219. InternalData(GpuParamObjectDesc* paramDesc, HTexture* textures);
  220. InternalData();
  221. ~InternalData();
  222. GpuParamObjectDesc* paramDesc;
  223. HTexture* textures;
  224. bool isDestroyed;
  225. };
  226. public:
  227. GpuParamTexture();
  228. /**
  229. * @copydoc GpuDataParamBase::set
  230. */
  231. void set(const HTexture& texture);
  232. /**
  233. * @copydoc GpuDataParamBase::get
  234. */
  235. HTexture get();
  236. /**
  237. * @copydoc GpuDataParamBase::_destroy
  238. */
  239. void _destroy();
  240. private:
  241. GpuParamTexture(GpuParamObjectDesc* paramDesc, HTexture* textures);
  242. private:
  243. std::shared_ptr<InternalData> mData;
  244. };
  245. /**
  246. * @copydoc GpuDataParamBase
  247. */
  248. class BS_CORE_EXPORT GpuParamSampState
  249. {
  250. private:
  251. friend class GpuParams;
  252. struct InternalData
  253. {
  254. InternalData(GpuParamObjectDesc* paramDesc, HSamplerState* samplerStates);
  255. InternalData();
  256. ~InternalData();
  257. GpuParamObjectDesc* paramDesc;
  258. HSamplerState* samplerStates;
  259. bool isDestroyed;
  260. };
  261. public:
  262. GpuParamSampState();
  263. /**
  264. * @copydoc GpuDataParamBase::set
  265. */
  266. void set(const HSamplerState& texture);
  267. /**
  268. * @copydoc GpuDataParamBase::get
  269. */
  270. HSamplerState get();
  271. /**
  272. * @copydoc GpuDataParamBase::_destroy
  273. */
  274. void _destroy();
  275. private:
  276. GpuParamSampState(GpuParamObjectDesc* paramDesc, HSamplerState* samplerStates);
  277. private:
  278. std::shared_ptr<InternalData> mData;
  279. };
  280. }