MaterialResource.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Resource/ResourceObject.h>
  7. #include <AnKi/Resource/RenderingKey.h>
  8. #include <AnKi/Resource/ShaderProgramResource.h>
  9. #include <AnKi/Resource/ImageResource.h>
  10. #include <AnKi/Math.h>
  11. #include <AnKi/Util/Enum.h>
  12. namespace anki
  13. {
  14. // Forward
  15. class XmlElement;
  16. /// @addtogroup resource
  17. /// @{
  18. /// The ID of a buildin material variable.
  19. enum class BuiltinMaterialVariableId : U8
  20. {
  21. NONE = 0,
  22. MODEL_MATRIX,
  23. PREVIOUS_MODEL_MATRIX,
  24. BONE_TRANSFORMS_ADDRESS,
  25. PREVIOUS_BONE_TRANSFORMS_ADDRESS,
  26. POSITIONS_VERTEX_BUFFER_ADDRESSES,
  27. OTHERS_VERTEX_BUFFER_ADDRESSES,
  28. BONE_WEIGHTS_VERTEX_BUFFER_ADDRESSES,
  29. COUNT,
  30. FIRST = 0,
  31. };
  32. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BuiltinMaterialVariableId)
  33. /// The ID of builtin mutators.
  34. enum class BuiltinMutatorId : U8
  35. {
  36. NONE = 0,
  37. SUB_TECHNIQUE,
  38. LOD,
  39. BONES,
  40. VELOCITY,
  41. COUNT,
  42. FIRST = 0
  43. };
  44. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BuiltinMutatorId)
  45. /// Holds the shader variables. It's a container for shader program variables that share the same name.
  46. class MaterialVariable
  47. {
  48. friend class MaterialResource;
  49. public:
  50. MaterialVariable();
  51. MaterialVariable(const MaterialVariable&) = delete; // Non-copyable
  52. MaterialVariable(MaterialVariable&& b)
  53. {
  54. *this = std::move(b);
  55. }
  56. ~MaterialVariable();
  57. MaterialVariable& operator=(const MaterialVariable&) = delete; // Non-copyable
  58. MaterialVariable& operator=(MaterialVariable&& b)
  59. {
  60. m_name = std::move(b.m_name);
  61. m_numericValueIsSet = b.m_numericValueIsSet;
  62. m_dataType = b.m_dataType;
  63. m_builtin = b.m_builtin;
  64. m_offsetInStruct = b.m_offsetInStruct;
  65. m_Mat4 = b.m_Mat4;
  66. m_image = std::move(b.m_image);
  67. return *this;
  68. }
  69. /// Get the builtin info.
  70. BuiltinMaterialVariableId getBuiltin() const
  71. {
  72. return m_builtin;
  73. }
  74. CString getName() const
  75. {
  76. return m_name;
  77. }
  78. template<typename T>
  79. const T& getValue() const;
  80. Bool isTexture() const
  81. {
  82. return m_image.isCreated();
  83. }
  84. Bool isNumeric() const
  85. {
  86. return !isTexture();
  87. }
  88. Bool isBuiltin() const
  89. {
  90. return m_builtin != BuiltinMaterialVariableId::NONE;
  91. }
  92. ShaderVariableDataType getDataType() const
  93. {
  94. ANKI_ASSERT(m_dataType != ShaderVariableDataType::NONE);
  95. return m_dataType;
  96. }
  97. protected:
  98. // !!WARNING!! Don't forget to update the move operator
  99. String m_name;
  100. Bool m_numericValueIsSet = false; ///< Is numeric and the unamed union bellow is set.
  101. ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
  102. BuiltinMaterialVariableId m_builtin = BuiltinMaterialVariableId::NONE;
  103. U32 m_offsetInStruct = MAX_U32; ///< Offset in the AnKiGpuSceneDescriptor.
  104. /// Values for non-builtins
  105. /// @{
  106. union
  107. {
  108. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) type ANKI_CONCATENATE(m_, type);
  109. #include <AnKi/Gr/ShaderVariableDataTypeDefs.h>
  110. #undef ANKI_SVDT_MACRO
  111. U16 m_bindlessTextureIndex;
  112. };
  113. ImageResourcePtr m_image;
  114. /// @}
  115. Bool valueSetByMaterial() const
  116. {
  117. return m_image.isCreated() || m_numericValueIsSet;
  118. }
  119. };
  120. // Specialize the MaterialVariable::getValue
  121. #define ANKI_SPECIALIZE_GET_VALUE(type, var, shaderType) \
  122. template<> \
  123. inline const type& MaterialVariable::getValue<type>() const \
  124. { \
  125. ANKI_ASSERT(m_dataType == ShaderVariableDataType::shaderType); \
  126. ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId::NONE); \
  127. return var; \
  128. }
  129. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  130. ANKI_SPECIALIZE_GET_VALUE(type, ANKI_CONCATENATE(m_, type), capital)
  131. #include <AnKi/Gr/ShaderVariableDataTypeDefs.h>
  132. #undef ANKI_SVDT_MACRO
  133. #undef ANKI_SPECIALIZE_GET_VALUE
  134. template<>
  135. inline const ImageResourcePtr& MaterialVariable::getValue() const
  136. {
  137. ANKI_ASSERT(isTexture());
  138. ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId::NONE);
  139. return m_image;
  140. }
  141. /// Material variant.
  142. class MaterialVariant
  143. {
  144. friend class MaterialResource;
  145. public:
  146. MaterialVariant() = default;
  147. MaterialVariant(const MaterialVariant&) = delete; // Non-copyable
  148. MaterialVariant& operator=(const MaterialVariant&) = delete; // Non-copyable
  149. const ShaderProgramPtr& getShaderProgram() const
  150. {
  151. return m_prog;
  152. }
  153. private:
  154. ShaderProgramPtr m_prog;
  155. };
  156. /// Material resource.
  157. ///
  158. /// Material XML file format:
  159. /// @code
  160. /// <material [shadows="0|1"]>
  161. /// <technique name="str" shaderProgram="filename">
  162. /// [<mutation>
  163. /// <mutator name="str" value="value"/>
  164. /// </mutation>]
  165. /// </technique>
  166. ///
  167. /// [<inputs>
  168. /// <input name="name in GpuSceneMaterialDescription" value="values" [arrayIndex="number"]/> (1)
  169. /// </inputs>]
  170. ///
  171. /// [<technique ...>
  172. /// ...
  173. /// </technique>]
  174. /// </material>
  175. /// @endcode
  176. ///
  177. /// (1): Only for non-builtins.
  178. class MaterialResource : public ResourceObject
  179. {
  180. public:
  181. MaterialResource(ResourceManager* manager);
  182. ~MaterialResource();
  183. /// Load a material file
  184. ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
  185. Bool castsShadow() const
  186. {
  187. return m_shadow;
  188. }
  189. ConstWeakArray<MaterialVariable> getVariables() const
  190. {
  191. return m_vars;
  192. }
  193. Bool supportsSkinning() const
  194. {
  195. return m_supportSkinning;
  196. }
  197. const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
  198. RenderingTechniqueBit getPresentRenderingTechniques() const
  199. {
  200. ANKI_ASSERT(m_presentTechniques != RenderingTechniqueBit::NONE);
  201. return m_presentTechniques;
  202. }
  203. private:
  204. class SubMutation
  205. {
  206. public:
  207. const ShaderProgramResourceMutator* m_mutator;
  208. MutatorValue m_value;
  209. };
  210. class Technique
  211. {
  212. public:
  213. ShaderProgramResourcePtr m_prog;
  214. U8 m_lodCount = 1;
  215. U32 m_perDrawUboBinding = MAX_U32;
  216. U32 m_perInstanceUboBinding = MAX_U32;
  217. U32 m_boneTrfsBinding = MAX_U32;
  218. U32 m_prevFrameBoneTrfsBinding = MAX_U32;
  219. U32 m_rtShaderGroupHandleIndex = MAX_U32;
  220. /// Matrix of variants.
  221. mutable Array4d<MaterialVariant, U(RenderingSubTechnique::COUNT), MAX_LOD_COUNT, 2, 2> m_variantMatrix;
  222. mutable RWMutex m_variantMatrixMtx;
  223. Array<const ShaderProgramResourceMutator*, U32(BuiltinMutatorId::COUNT)> m_builtinMutators = {};
  224. DynamicArray<SubMutation> m_nonBuiltinsMutation;
  225. };
  226. DynamicArray<MaterialVariable> m_vars;
  227. Array<Technique, U32(RenderingTechnique::COUNT)> m_techniques;
  228. U32 m_gpuSceneDescriptionStructSize = 0;
  229. Bool m_shadow = true;
  230. Bool m_supportSkinning = false;
  231. RenderingTechniqueBit m_presentTechniques = RenderingTechniqueBit::NONE;
  232. /// Parse whatever is inside the <inputs> tag.
  233. ANKI_USE_RESULT Error parseInputs(XmlElement inputsEl, Bool async);
  234. ANKI_USE_RESULT Error parseTechnique(XmlElement techniqueEl, Bool async);
  235. ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl, Technique& technique);
  236. ANKI_USE_RESULT Error createVars(const ShaderProgramBinary& binary);
  237. ANKI_USE_RESULT Error findBuiltinMutators(Technique& technique);
  238. const MaterialVariable* tryFindVariableInternal(CString name) const
  239. {
  240. for(const MaterialVariable& v : m_vars)
  241. {
  242. if(v.m_name == name)
  243. {
  244. return &v;
  245. }
  246. }
  247. return nullptr;
  248. }
  249. const MaterialVariable* tryFindVariable(CString name) const
  250. {
  251. return tryFindVariableInternal(name);
  252. }
  253. MaterialVariable* tryFindVariable(CString name)
  254. {
  255. return const_cast<MaterialVariable*>(tryFindVariableInternal(name));
  256. }
  257. };
  258. /// @}
  259. } // end namespace anki