BsMaterialParams.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "BsIReflectable.h"
  6. #include "BsStaticAlloc.h"
  7. #include "BsVector2.h"
  8. #include "BsVector3.h"
  9. #include "BsVector4.h"
  10. #include "BsVector2I.h"
  11. #include "BsVectorNI.h"
  12. #include "BsColor.h"
  13. #include "BsMatrix3.h"
  14. #include "BsMatrix4.h"
  15. #include "BsMatrixNxM.h"
  16. #include "BsGpuParams.h"
  17. namespace BansheeEngine
  18. {
  19. /** @addtogroup Material-Internal
  20. * @{
  21. */
  22. /**
  23. * Contains all parameter values set in a Material. This is similar to GpuParams which also stores parameter values,
  24. * however GpuParams are built for use on the GPU-side and don't store parameters that don't exist in a compiled GPU
  25. * program. This object on the other hand stores all parameters defined in a shader, regardless or not if they actually
  26. * exist in the GPU program. Additionally GpuParams are defined per-program (for example vertex, fragment) while this
  27. * object exists for the entire material.
  28. *
  29. * @note
  30. * This introduces redundancy as parameters stored by GpuParams and this object are duplicated. If this is an issue the
  31. * implementation can be modified to only store parameters not included in GpuParams.
  32. * @note
  33. * The reason why parameters in this class and GpuParams differ is most often compiler optimizations. If a compiler
  34. * optimizes out a variable in a GPU program we should still be able to store it, either for later when the variable
  35. * will be introduced, or for other techniques that might have that variable implemented.
  36. */
  37. class BS_CORE_EXPORT MaterialParams : public IReflectable
  38. {
  39. public:
  40. /** Type of material parameter. */
  41. enum class ParamType
  42. {
  43. Data, Texture, Sampler, Buffer
  44. };
  45. /** Result codes for getParam method. */
  46. enum class GetParamResult
  47. {
  48. Success,
  49. NotFound,
  50. InvalidType,
  51. IndexOutOfBounds
  52. };
  53. /** Meta-data about a parameter. */
  54. struct ParamData
  55. {
  56. ParamType type;
  57. GpuParamDataType dataType;
  58. UINT32 index;
  59. UINT32 arraySize;
  60. };
  61. /** Raw data for a single structure parameter. */
  62. class BS_CORE_EXPORT StructParamData : public IReflectable
  63. {
  64. public:
  65. UINT8* data;
  66. UINT32 dataSize;
  67. friend class StructParamDataRTTI;
  68. static RTTITypeBase* getRTTIStatic();
  69. RTTITypeBase* getRTTI() const override;
  70. };
  71. /** Data for a single texture parameter. */
  72. class BS_CORE_EXPORT TextureParamData : public IReflectable
  73. {
  74. public:
  75. HTexture value;
  76. bool isLoadStore;
  77. TextureSurface surface;
  78. friend class TextureParamDataRTTI;
  79. static RTTITypeBase* getRTTIStatic();
  80. RTTITypeBase* getRTTI() const override;
  81. };
  82. /** Creates a new material params object and initializes enough room for parameters from the provided shader. */
  83. MaterialParams(const HShader& shader);
  84. ~MaterialParams();
  85. /**
  86. * Returns the value of a shader data parameter with the specified name at the specified array index. If the
  87. * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
  88. *
  89. * @param[in] name Name of the shader parameter.
  90. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  91. * @param[out] output If successful, value of the parameter.
  92. *
  93. * @tparam T Native type of the parameter.
  94. */
  95. template <typename T>
  96. void getDataParam(const String& name, UINT32 arrayIdx, T& output) const
  97. {
  98. GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
  99. const ParamData* param = nullptr;
  100. auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
  101. if (result != GetParamResult::Success)
  102. return;
  103. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  104. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  105. output = *(T*)(mDataParamsBuffer[param->index + arrayIdx * paramTypeSize]);
  106. memcpy(output, &mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], sizeof(paramTypeSize));
  107. }
  108. /**
  109. * Sets the value of a shader data parameter with the specified name at the specified array index. If the
  110. * parameter name, index or type is not valid a warning will be logged and output value will not be set.
  111. *
  112. * @param[in] name Name of the shader parameter.
  113. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  114. * @param[in] input New value of the parameter.
  115. *
  116. * @tparam T Native type of the parameter.
  117. */
  118. template <typename T>
  119. void setDataParam(const String& name, UINT32 arrayIdx, const T& input) const
  120. {
  121. GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
  122. const ParamData* param = nullptr;
  123. auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
  124. if (result != GetParamResult::Success)
  125. return;
  126. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  127. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  128. memcpy(&mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], input, sizeof(paramTypeSize));
  129. }
  130. /**
  131. * Returns the value of a shader structure parameter with the specified name at the specified array index. If the
  132. * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
  133. *
  134. * @param[in] name Name of the shader parameter.
  135. * @param[out] value Pre-allocated buffer of @p size bytes where the value will be retrieved.
  136. * @param[in] size Size of the buffer into which to write the value. Must match parameter struct's size.
  137. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  138. */
  139. void getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const;
  140. /**
  141. * Sets the value of a shader structure parameter with the specified name at the specified array index. If the
  142. * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
  143. *
  144. * @param[in] name Name of the shader parameter.
  145. * @param[in] value Buffer of @p size bytes containing the new value of the structure.
  146. * @param[in] size Size of the buffer from which to retrieve the value. Must match parameter struct's size.
  147. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  148. */
  149. void setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx);
  150. /**
  151. * Returns the value of a shader texture parameter with the specified name. If the parameter name or type is not
  152. * valid a warning will be logged and output value will not be retrieved.
  153. *
  154. * @param[in] name Name of the shader parameter.
  155. * @param[out] value Output value of the parameter.
  156. */
  157. void getTexture(const String& name, HTexture& value) const;
  158. /**
  159. * Sets the value of a shader texture parameter with the specified name. If the parameter name or type is not
  160. * valid a warning will be logged and output value will not be set.
  161. *
  162. * @param[in] name Name of the shader parameter.
  163. * @param[in] value New value of the parameter.
  164. */
  165. void setTexture(const String& name, const HTexture& value);
  166. /**
  167. * Returns the value of a shader load/store texture parameter with the specified name. If the parameter name or
  168. * type is not valid a warning will be logged and output value will not be retrieved.
  169. *
  170. * @param[in] name Name of the shader parameter.
  171. * @param[out] value Output value of the parameter.
  172. * @param[out] surface Surface describing which part of the texture is being accessed.
  173. */
  174. void getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface) const;
  175. /**
  176. * Sets the value of a shader load/store texture parameter with the specified name. If the parameter name or
  177. * type is not valid a warning will be logged and the value will not be set.
  178. *
  179. * @param[in] name Name of the shader parameter.
  180. * @param[in] value New value of the parameter.
  181. * @param[in] surface Surface describing which part of the texture is being accessed.
  182. */
  183. void setLoadStoreTexture(const String& name, const HTexture& value, const TextureSurface& surface);
  184. /**
  185. * Returns the value of a shader buffer parameter with the specified name. If the parameter name or type is not
  186. * valid a warning will be logged and output value will not be retrieved.
  187. *
  188. * @param[in] name Name of the shader parameter.
  189. * @param[out] value Output value of the parameter.
  190. */
  191. void getBuffer(const String& name, SPtr<GpuBuffer>& value) const;
  192. /**
  193. * Sets the value of a shader buffer parameter with the specified name. If the parameter name or type is not
  194. * valid a warning will be logged and output value will not be set.
  195. *
  196. * @param[in] name Name of the shader parameter.
  197. * @param[in] value New value of the parameter.
  198. */
  199. void setBuffer(const String& name, const SPtr<GpuBuffer>& value);
  200. /**
  201. * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
  202. * valid a warning will be logged and output value will not be set.
  203. *
  204. * @param[in] name Name of the shader parameter.
  205. * @param[out] value Output value of the parameter.
  206. */
  207. void getSamplerState(const String& name, SPtr<SamplerState>& value) const;
  208. /**
  209. * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
  210. * valid a warning will be logged and output value will not be set.
  211. *
  212. * @param[in] name Name of the shader parameter.
  213. * @param[in] value New value of the parameter.
  214. */
  215. void setSamplerState(const String& name, const SPtr<SamplerState>& value);
  216. /**
  217. * Returns data about a parameter and reports an error if there is a type or size mismatch, or if the parameter
  218. * does exist.
  219. *
  220. * @param[in] name Name of the shader parameter.
  221. * @param[in] type Type of the parameter retrieve. Error will be logged if actual type of the parameter
  222. * doesn't match.
  223. * @param[in] dataType Only relevant if the parameter is a data type. Determines exact data type of the parameter
  224. * to retrieve.
  225. * @param[in] arrayIdx Array index of the entry to retrieve.
  226. * @param[out] output Object describing the parameter with an index to its data. If the parameter was not found
  227. * this value is undefined. This value will still be valid if parameter was found but
  228. * some other error was reported.
  229. *
  230. * @return Success or error state of the request.
  231. */
  232. GetParamResult getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx,
  233. const ParamData** output) const;
  234. /**
  235. * Logs an error that was reported by getParamData().
  236. *
  237. * @param[in] errorCode Information about the error.
  238. * @param[in] name Name of the shader parameter for which the error occurred.
  239. * @param[in] arrayIdx Array index for which the error occurred.
  240. */
  241. void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
  242. /**
  243. * Equivalent to getStructData(const String&, UINT32, T&) except it uses the internal parameter index
  244. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  245. */
  246. template <typename T>
  247. void getDataParam(UINT32 index, UINT32 arrayIdx, T& output) const
  248. {
  249. GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
  250. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  251. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  252. assert(sizeof(output) == paramTypeSize);
  253. memcpy(&output, &mDataParamsBuffer[index + arrayIdx * paramTypeSize], paramTypeSize);
  254. }
  255. /**
  256. * Equivalent to setDataParam(const String&, UINT32, T&) except it uses the internal parameter index
  257. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  258. */
  259. template <typename T>
  260. void setDataParam(UINT32 index, UINT32 arrayIdx, const T& input) const
  261. {
  262. GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
  263. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  264. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  265. assert(sizeof(input) == paramTypeSize);
  266. memcpy(&mDataParamsBuffer[index + arrayIdx * paramTypeSize], &input, paramTypeSize);
  267. }
  268. /**
  269. * Equivalent to getStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
  270. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  271. */
  272. void getStructData(UINT32 index, void* value, UINT32 size) const;
  273. /**
  274. * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
  275. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  276. */
  277. void setStructData(UINT32 index, const void* value, UINT32 size);
  278. /**
  279. * Returns a size of a struct parameter in bytes, using the internal parameter index. Caller must guarantee the
  280. * index is valid.
  281. */
  282. UINT32 getStructSize(UINT32 index) const;
  283. /**
  284. * Equivalent to getTexture(const String&, HTexture&) except it uses the internal parameter index directly,
  285. * avoiding the name lookup. Caller must guarantee the index is valid.
  286. */
  287. void getTexture(UINT32 index, HTexture& value) const;
  288. /**
  289. * Equivalent to setTexture(const String&, HTexture&) except it uses the internal parameter index directly,
  290. * avoiding the name lookup. Caller must guarantee the index is valid.
  291. */
  292. void setTexture(UINT32 index, const HTexture& value);
  293. /**
  294. * Equivalent to getBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
  295. * avoiding the name lookup. Caller must guarantee the index is valid.
  296. */
  297. void getBuffer(UINT32 index, SPtr<GpuBuffer>& value) const;
  298. /**
  299. * Equivalent to setBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
  300. * avoiding the name lookup. Caller must guarantee the index is valid.
  301. */
  302. void setBuffer(UINT32 index, const SPtr<GpuBuffer>& value);
  303. /**
  304. * Equivalent to getLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
  305. * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
  306. */
  307. void getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface) const;
  308. /**
  309. * Equivalent to setLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
  310. * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
  311. */
  312. void setLoadStoreTexture(UINT32 index, const HTexture& value, const TextureSurface& surface);
  313. /**
  314. * Checks is a texture with the specified index a load/store texture or a normal one. Caller must guarantee the
  315. * index is valid.
  316. */
  317. bool getIsTextureLoadStore(UINT32 index) const;
  318. /**
  319. * Equivalent to getSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
  320. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  321. */
  322. void getSamplerState(UINT32 index, SPtr<SamplerState>& value) const;
  323. /**
  324. * Equivalent to setSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
  325. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  326. */
  327. void setSamplerState(UINT32 index, const SPtr<SamplerState>& value);
  328. /**
  329. * Returns the default texture (one assigned when no other is provided), if available for the specified index.
  330. * Index is the internal parameter index and the caller must guarantee the index is valid.
  331. */
  332. void getDefaultTexture(UINT32 index, HTexture& value) const;
  333. /**
  334. * Returns the default sampler state (one assigned when no other is provided), if available for the specified index.
  335. * Index is the internal parameter index and the caller must guarantee the index is valid.
  336. */
  337. void getDefaultSamplerState(UINT32 index, SPtr<SamplerState>& value) const;
  338. private:
  339. const static UINT32 STATIC_BUFFER_SIZE = 256;
  340. UnorderedMap<String, ParamData> mParams;
  341. UINT8* mDataParamsBuffer = nullptr;
  342. StructParamData* mStructParams = nullptr;
  343. TextureParamData* mTextureParams = nullptr;
  344. SPtr<GpuBuffer>* mBufferParams = nullptr;
  345. SPtr<SamplerState>* mSamplerStateParams = nullptr;
  346. HTexture* mDefaultTextureParams = nullptr;
  347. SPtr<SamplerState>* mDefaultSamplerStateParams = nullptr;
  348. UINT32 mDataSize = 0;
  349. UINT32 mNumStructParams = 0;
  350. UINT32 mNumTextureParams = 0;
  351. UINT32 mNumBufferParams = 0;
  352. UINT32 mNumSamplerParams = 0;
  353. mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
  354. /************************************************************************/
  355. /* RTTI */
  356. /************************************************************************/
  357. public:
  358. MaterialParams() { } // Only for serialization
  359. friend class MaterialParamsRTTI;
  360. static RTTITypeBase* getRTTIStatic();
  361. virtual RTTITypeBase* getRTTI() const override;
  362. };
  363. /** @cond SPECIALIZATIONS */
  364. BS_ALLOW_MEMCPY_SERIALIZATION(MaterialParams::ParamData);
  365. /** @endcond */
  366. /** @} */
  367. }