BsMaterialParams.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  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. struct SHADER_DATA_PARAM_DESC;
  23. struct SHADER_OBJECT_PARAM_DESC;
  24. /** Common functionality for MaterialParams and MaterialParamsCore. */
  25. class BS_CORE_EXPORT MaterialParamsBase
  26. {
  27. public:
  28. /** Type of material parameter. */
  29. enum class ParamType
  30. {
  31. Data, Texture, Sampler, Buffer
  32. };
  33. /** Result codes for getParam method. */
  34. enum class GetParamResult
  35. {
  36. Success,
  37. NotFound,
  38. InvalidType,
  39. IndexOutOfBounds
  40. };
  41. /** Meta-data about a parameter. */
  42. struct ParamData
  43. {
  44. ParamType type;
  45. GpuParamDataType dataType;
  46. UINT32 index;
  47. UINT32 arraySize;
  48. };
  49. /**
  50. * Creates a new material params object and initializes enough room for parameters from the provided parameter data.
  51. */
  52. MaterialParamsBase(
  53. const Map<String, SHADER_DATA_PARAM_DESC>& dataParams,
  54. const Map<String, SHADER_OBJECT_PARAM_DESC>& textureParams,
  55. const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferParams,
  56. const Map<String, SHADER_OBJECT_PARAM_DESC>& samplerParams);
  57. /** Constructor for serialization use only. */
  58. MaterialParamsBase() { }
  59. virtual ~MaterialParamsBase();
  60. /**
  61. * Returns the value of a shader data parameter with the specified name at the specified array index. If the
  62. * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
  63. *
  64. * @param[in] name Name of the shader parameter.
  65. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  66. * @param[out] output If successful, value of the parameter.
  67. *
  68. * @tparam T Native type of the parameter.
  69. */
  70. template <typename T>
  71. void getDataParam(const String& name, UINT32 arrayIdx, T& output) const
  72. {
  73. GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
  74. const ParamData* param = nullptr;
  75. auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
  76. if (result != GetParamResult::Success)
  77. return;
  78. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  79. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  80. output = *(T*)(mDataParamsBuffer[param->index + arrayIdx * paramTypeSize]);
  81. memcpy(output, &mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], sizeof(paramTypeSize));
  82. }
  83. /**
  84. * Sets the value of a shader data parameter with the specified name at the specified array index. If the
  85. * parameter name, index or type is not valid a warning will be logged and output value will not be set.
  86. *
  87. * @param[in] name Name of the shader parameter.
  88. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  89. * @param[in] input New value of the parameter.
  90. *
  91. * @tparam T Native type of the parameter.
  92. */
  93. template <typename T>
  94. void setDataParam(const String& name, UINT32 arrayIdx, const T& input) const
  95. {
  96. GpuParamDataType dataType = TGpuDataParamInfo<T>::TypeId;
  97. const ParamData* param = nullptr;
  98. auto result = getParamData(name, ParamType::Data, dataType, arrayIdx, &param);
  99. if (result != GetParamResult::Success)
  100. return;
  101. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  102. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  103. memcpy(&mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], input, sizeof(paramTypeSize));
  104. }
  105. /**
  106. * Returns data about a parameter and reports an error if there is a type or size mismatch, or if the parameter
  107. * does exist.
  108. *
  109. * @param[in] name Name of the shader parameter.
  110. * @param[in] type Type of the parameter retrieve. Error will be logged if actual type of the parameter
  111. * doesn't match.
  112. * @param[in] dataType Only relevant if the parameter is a data type. Determines exact data type of the parameter
  113. * to retrieve.
  114. * @param[in] arrayIdx Array index of the entry to retrieve.
  115. * @param[out] output Object describing the parameter with an index to its data. If the parameter was not found
  116. * this value is undefined. This value will still be valid if parameter was found but
  117. * some other error was reported.
  118. *
  119. * @return Success or error state of the request.
  120. */
  121. GetParamResult getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx,
  122. const ParamData** output) const;
  123. /**
  124. * Logs an error that was reported by getParamData().
  125. *
  126. * @param[in] errorCode Information about the error.
  127. * @param[in] name Name of the shader parameter for which the error occurred.
  128. * @param[in] arrayIdx Array index for which the error occurred.
  129. */
  130. void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
  131. /**
  132. * Equivalent to getStructData(const String&, UINT32, T&) except it uses the internal parameter index
  133. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  134. */
  135. template <typename T>
  136. void getDataParam(UINT32 index, UINT32 arrayIdx, T& output) const
  137. {
  138. GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
  139. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  140. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  141. assert(sizeof(output) == paramTypeSize);
  142. memcpy(&output, &mDataParamsBuffer[index + arrayIdx * paramTypeSize], paramTypeSize);
  143. }
  144. /**
  145. * Equivalent to setDataParam(const String&, UINT32, T&) except it uses the internal parameter index
  146. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  147. */
  148. template <typename T>
  149. void setDataParam(UINT32 index, UINT32 arrayIdx, const T& input) const
  150. {
  151. GpuParamDataType dataType = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
  152. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
  153. UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
  154. assert(sizeof(input) == paramTypeSize);
  155. memcpy(&mDataParamsBuffer[index + arrayIdx * paramTypeSize], &input, paramTypeSize);
  156. }
  157. protected:
  158. const static UINT32 STATIC_BUFFER_SIZE = 256;
  159. UnorderedMap<String, ParamData> mParams;
  160. UINT8* mDataParamsBuffer = nullptr;
  161. UINT32 mDataSize = 0;
  162. UINT32 mNumStructParams = 0;
  163. UINT32 mNumTextureParams = 0;
  164. UINT32 mNumBufferParams = 0;
  165. UINT32 mNumSamplerParams = 0;
  166. mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
  167. };
  168. /** Raw data for a single structure parameter. */
  169. class BS_CORE_EXPORT MaterialParamStructDataCore
  170. {
  171. public:
  172. UINT8* data;
  173. UINT32 dataSize;
  174. };
  175. /** Raw data for a single structure parameter. */
  176. class BS_CORE_EXPORT MaterialParamStructData : public IReflectable
  177. {
  178. public:
  179. UINT8* data;
  180. UINT32 dataSize;
  181. friend class MaterialParamStructDataRTTI;
  182. static RTTITypeBase* getRTTIStatic();
  183. RTTITypeBase* getRTTI() const override;
  184. };
  185. /** Data for a single texture parameter. */
  186. class BS_CORE_EXPORT MaterialParamTextureDataCore
  187. {
  188. public:
  189. SPtr<TextureCore> value;
  190. bool isLoadStore;
  191. TextureSurface surface;
  192. };
  193. /** Data for a single texture parameter. */
  194. class BS_CORE_EXPORT MaterialParamTextureData : public IReflectable
  195. {
  196. public:
  197. HTexture value;
  198. bool isLoadStore;
  199. TextureSurface surface;
  200. friend class MaterialParamTextureDataRTTI;
  201. static RTTITypeBase* getRTTIStatic();
  202. RTTITypeBase* getRTTI() const override;
  203. };
  204. /** Helper typedefs that reference types used by either core or sim thread implementation of TMaterialParams<Core>. */
  205. template<bool Core> struct TMaterialParamsTypes { };
  206. template<> struct TMaterialParamsTypes < false >
  207. {
  208. typedef GpuParams GpuParamsType;
  209. typedef HTexture TextureType;
  210. typedef SPtr<GpuBuffer> BufferType;
  211. typedef SPtr<SamplerState> SamplerType;
  212. typedef SPtr<GpuParamBlockBuffer> ParamsBufferType;
  213. typedef MaterialParamStructData StructParamDataType;
  214. typedef MaterialParamTextureData TextureParamDataType;
  215. typedef HShader ShaderType;
  216. };
  217. template<> struct TMaterialParamsTypes < true >
  218. {
  219. typedef GpuParamsCore GpuParamsType;
  220. typedef SPtr<TextureCore> TextureType;
  221. typedef SPtr<GpuBufferCore> BufferType;
  222. typedef SPtr<SamplerStateCore> SamplerType;
  223. typedef SPtr<GpuParamBlockBufferCore> ParamsBufferType;
  224. typedef MaterialParamStructDataCore StructParamDataType;
  225. typedef MaterialParamTextureDataCore TextureParamDataType;
  226. typedef SPtr<ShaderCore> ShaderType;
  227. };
  228. /** Common code that may be specialized for both MaterialParams and MaterialParamsCore. */
  229. template<bool Core>
  230. class BS_CORE_EXPORT TMaterialParams : public MaterialParamsBase
  231. {
  232. public:
  233. typedef typename TMaterialParamsTypes<Core>::GpuParamsType GpuParamsType;
  234. typedef typename TMaterialParamsTypes<Core>::TextureType TextureType;
  235. typedef typename TMaterialParamsTypes<Core>::BufferType BufferType;
  236. typedef typename TMaterialParamsTypes<Core>::SamplerType SamplerType;
  237. typedef typename TMaterialParamsTypes<Core>::ParamsBufferType ParamsBufferType;
  238. typedef typename TMaterialParamsTypes<Core>::ShaderType ShaderType;
  239. typedef typename TMaterialParamsTypes<Core>::StructParamDataType ParamStructDataType;
  240. typedef typename TMaterialParamsTypes<Core>::TextureParamDataType ParamTextureDataType;
  241. /** Creates a new material params object and initializes enough room for parameters from the provided shader. */
  242. TMaterialParams(const ShaderType& shader);
  243. /** Constructor for serialization use only. */
  244. TMaterialParams() { }
  245. virtual ~TMaterialParams();
  246. /**
  247. * Returns the value of a shader structure parameter with the specified name at the specified array index. If the
  248. * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
  249. *
  250. * @param[in] name Name of the shader parameter.
  251. * @param[out] value Pre-allocated buffer of @p size bytes where the value will be retrieved.
  252. * @param[in] size Size of the buffer into which to write the value. Must match parameter struct's size.
  253. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  254. */
  255. void getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const;
  256. /**
  257. * Sets the value of a shader structure parameter with the specified name at the specified array index. If the
  258. * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
  259. *
  260. * @param[in] name Name of the shader parameter.
  261. * @param[in] value Buffer of @p size bytes containing the new value of the structure.
  262. * @param[in] size Size of the buffer from which to retrieve the value. Must match parameter struct's size.
  263. * @param[in] arrayIdx If the parameter is an array, index of the entry to access.
  264. */
  265. void setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx);
  266. /**
  267. * Returns the value of a shader texture parameter with the specified name. If the parameter name or type is not
  268. * valid a warning will be logged and output value will not be retrieved.
  269. *
  270. * @param[in] name Name of the shader parameter.
  271. * @param[out] value Output value of the parameter.
  272. */
  273. void getTexture(const String& name, TextureType& value) const;
  274. /**
  275. * Sets the value of a shader texture parameter with the specified name. If the parameter name or type is not
  276. * valid a warning will be logged and output value will not be set.
  277. *
  278. * @param[in] name Name of the shader parameter.
  279. * @param[in] value New value of the parameter.
  280. */
  281. void setTexture(const String& name, const TextureType& value);
  282. /**
  283. * Returns the value of a shader load/store texture parameter with the specified name. If the parameter name or
  284. * type is not valid a warning will be logged and output value will not be retrieved.
  285. *
  286. * @param[in] name Name of the shader parameter.
  287. * @param[out] value Output value of the parameter.
  288. * @param[out] surface Surface describing which part of the texture is being accessed.
  289. */
  290. void getLoadStoreTexture(const String& name, TextureType& value, TextureSurface& surface) const;
  291. /**
  292. * Sets the value of a shader load/store texture parameter with the specified name. If the parameter name or
  293. * type is not valid a warning will be logged and the value will not be set.
  294. *
  295. * @param[in] name Name of the shader parameter.
  296. * @param[in] value New value of the parameter.
  297. * @param[in] surface Surface describing which part of the texture is being accessed.
  298. */
  299. void setLoadStoreTexture(const String& name, const TextureType& value, const TextureSurface& surface);
  300. /**
  301. * Returns the value of a shader buffer parameter with the specified name. If the parameter name or type is not
  302. * valid a warning will be logged and output value will not be retrieved.
  303. *
  304. * @param[in] name Name of the shader parameter.
  305. * @param[out] value Output value of the parameter.
  306. */
  307. void getBuffer(const String& name, BufferType& value) const;
  308. /**
  309. * Sets the value of a shader buffer parameter with the specified name. If the parameter name or type is not
  310. * valid a warning will be logged and output value will not be set.
  311. *
  312. * @param[in] name Name of the shader parameter.
  313. * @param[in] value New value of the parameter.
  314. */
  315. void setBuffer(const String& name, const BufferType& value);
  316. /**
  317. * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
  318. * valid a warning will be logged and output value will not be set.
  319. *
  320. * @param[in] name Name of the shader parameter.
  321. * @param[out] value Output value of the parameter.
  322. */
  323. void getSamplerState(const String& name, SamplerType& value) const;
  324. /**
  325. * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
  326. * valid a warning will be logged and output value will not be set.
  327. *
  328. * @param[in] name Name of the shader parameter.
  329. * @param[in] value New value of the parameter.
  330. */
  331. void setSamplerState(const String& name, const SamplerType& value);
  332. /**
  333. * Equivalent to getStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
  334. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  335. */
  336. void getStructData(UINT32 index, void* value, UINT32 size) const;
  337. /**
  338. * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
  339. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  340. */
  341. void setStructData(UINT32 index, const void* value, UINT32 size);
  342. /**
  343. * Returns a size of a struct parameter in bytes, using the internal parameter index. Caller must guarantee the
  344. * index is valid.
  345. */
  346. UINT32 getStructSize(UINT32 index) const;
  347. /**
  348. * Equivalent to getTexture(const String&, HTexture&) except it uses the internal parameter index directly,
  349. * avoiding the name lookup. Caller must guarantee the index is valid.
  350. */
  351. void getTexture(UINT32 index, TextureType& value) const;
  352. /**
  353. * Equivalent to setTexture(const String&, HTexture&) except it uses the internal parameter index directly,
  354. * avoiding the name lookup. Caller must guarantee the index is valid.
  355. */
  356. void setTexture(UINT32 index, const TextureType& value);
  357. /**
  358. * Equivalent to getBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
  359. * avoiding the name lookup. Caller must guarantee the index is valid.
  360. */
  361. void getBuffer(UINT32 index, BufferType& value) const;
  362. /**
  363. * Equivalent to setBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
  364. * avoiding the name lookup. Caller must guarantee the index is valid.
  365. */
  366. void setBuffer(UINT32 index, const BufferType& value);
  367. /**
  368. * Equivalent to getLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
  369. * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
  370. */
  371. void getLoadStoreTexture(UINT32 index, TextureType& value, TextureSurface& surface) const;
  372. /**
  373. * Equivalent to setLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
  374. * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
  375. */
  376. void setLoadStoreTexture(UINT32 index, const TextureType& value, const TextureSurface& surface);
  377. /**
  378. * Checks is a texture with the specified index a load/store texture or a normal one. Caller must guarantee the
  379. * index is valid.
  380. */
  381. bool getIsTextureLoadStore(UINT32 index) const;
  382. /**
  383. * Equivalent to getSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
  384. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  385. */
  386. void getSamplerState(UINT32 index, SamplerType& value) const;
  387. /**
  388. * Equivalent to setSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
  389. * directly, avoiding the name lookup. Caller must guarantee the index is valid.
  390. */
  391. void setSamplerState(UINT32 index, const SamplerType& value);
  392. /**
  393. * Returns the default texture (one assigned when no other is provided), if available for the specified index.
  394. * Index is the internal parameter index and the caller must guarantee the index is valid.
  395. */
  396. void getDefaultTexture(UINT32 index, TextureType& value) const;
  397. /**
  398. * Returns the default sampler state (one assigned when no other is provided), if available for the specified index.
  399. * Index is the internal parameter index and the caller must guarantee the index is valid.
  400. */
  401. void getDefaultSamplerState(UINT32 index, SamplerType& value) const;
  402. protected:
  403. ParamStructDataType* mStructParams = nullptr;
  404. ParamTextureDataType* mTextureParams = nullptr;
  405. BufferType* mBufferParams = nullptr;
  406. SamplerType* mSamplerStateParams = nullptr;
  407. TextureType* mDefaultTextureParams = nullptr;
  408. SamplerType* mDefaultSamplerStateParams = nullptr;
  409. };
  410. /** Core thread version of MaterialParams. */
  411. class BS_CORE_EXPORT MaterialParamsCore : public TMaterialParams<true>
  412. {
  413. public:
  414. /** @copydoc TMaterialParams<Core>::TMaterialParams */
  415. MaterialParamsCore(const SPtr<ShaderCore>& shader);
  416. };
  417. /**
  418. * Contains all parameter values set in a Material. This is similar to GpuParams which also stores parameter values,
  419. * however GpuParams are built for use on the GPU-side and don't store parameters that don't exist in a compiled GPU
  420. * program. This object on the other hand stores all parameters defined in a shader, regardless or not if they actually
  421. * exist in the GPU program. Additionally GpuParams are defined per-program (for example vertex, fragment) while this
  422. * object exists for the entire material.
  423. *
  424. * @note
  425. * This introduces redundancy as parameters stored by GpuParams and this object are duplicated. If this is an issue the
  426. * implementation can be modified to only store parameters not included in GpuParams.
  427. * @note
  428. * The reason why parameters in this class and GpuParams differ is most often compiler optimizations. If a compiler
  429. * optimizes out a variable in a GPU program we should still be able to store it, either for later when the variable
  430. * will be introduced, or for other techniques that might have that variable implemented.
  431. */
  432. class BS_CORE_EXPORT MaterialParams : public IReflectable, public TMaterialParams<false>
  433. {
  434. public:
  435. /** @copydoc TMaterialParams<Core>::TMaterialParams */
  436. MaterialParams(const HShader& shader);
  437. /************************************************************************/
  438. /* RTTI */
  439. /************************************************************************/
  440. public:
  441. MaterialParams() { } // Only for serialization
  442. friend class MaterialParamsRTTI;
  443. static RTTITypeBase* getRTTIStatic();
  444. RTTITypeBase* getRTTI() const override;
  445. };
  446. /** @cond SPECIALIZATIONS */
  447. BS_ALLOW_MEMCPY_SERIALIZATION(MaterialParamsBase::ParamData);
  448. /** @endcond */
  449. /** @} */
  450. }