MaterialResource.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright (C) 2009-present, 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. #include <AnKi/Shaders/Include/MaterialTypes.h>
  13. namespace anki {
  14. // Forward
  15. class XmlElement;
  16. /// @addtogroup resource
  17. /// @{
  18. /// The ID of builtin mutators.
  19. enum class BuiltinMutatorId : U8
  20. {
  21. kNone = 0,
  22. kBones,
  23. kVelocity,
  24. kCount,
  25. kFirst = 0
  26. };
  27. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BuiltinMutatorId)
  28. /// Holds the shader variables. It's a container for shader program variables that share the same name.
  29. class MaterialVariable
  30. {
  31. friend class MaterialVariant;
  32. friend class MaterialResource;
  33. public:
  34. MaterialVariable();
  35. MaterialVariable(const MaterialVariable&) = delete; // Non-copyable
  36. MaterialVariable(MaterialVariable&& b)
  37. {
  38. *this = std::move(b);
  39. }
  40. ~MaterialVariable();
  41. MaterialVariable& operator=(const MaterialVariable&) = delete; // Non-copyable
  42. MaterialVariable& operator=(MaterialVariable&& b)
  43. {
  44. m_name = std::move(b.m_name);
  45. m_offsetInLocalConstants = b.m_offsetInLocalConstants;
  46. m_dataType = b.m_dataType;
  47. m_Mat4 = b.m_Mat4;
  48. m_image = std::move(b.m_image);
  49. return *this;
  50. }
  51. CString getName() const
  52. {
  53. return m_name;
  54. }
  55. template<typename T>
  56. const T& getValue() const;
  57. ShaderVariableDataType getDataType() const
  58. {
  59. ANKI_ASSERT(m_dataType != ShaderVariableDataType::kNone);
  60. return m_dataType;
  61. }
  62. U32 getOffsetInLocalConstants() const
  63. {
  64. ANKI_ASSERT(m_offsetInLocalConstants != kMaxU32);
  65. return m_offsetInLocalConstants;
  66. }
  67. ImageResource* tryGetImageResource() const
  68. {
  69. return (m_image) ? m_image.get() : nullptr;
  70. }
  71. protected:
  72. ResourceString m_name;
  73. U32 m_offsetInLocalConstants = kMaxU32;
  74. ShaderVariableDataType m_dataType = ShaderVariableDataType::kNone;
  75. /// Values
  76. /// @{
  77. union
  78. {
  79. #define ANKI_SVDT_MACRO(type, baseType, rowCount, columnCount, isIntagralType) type ANKI_CONCATENATE(m_, type);
  80. #include <AnKi/Gr/ShaderVariableDataType.def.h>
  81. };
  82. ImageResourcePtr m_image;
  83. /// @}
  84. };
  85. // Specialize the MaterialVariable::getValue
  86. #define ANKI_SPECIALIZE_GET_VALUE(type, member) \
  87. template<> \
  88. inline const type& MaterialVariable::getValue<type>() const \
  89. { \
  90. ANKI_ASSERT(m_dataType == ShaderVariableDataType::k##type); \
  91. return member; \
  92. }
  93. #define ANKI_SVDT_MACRO(type, baseType, rowCount, columnCount, isIntagralType) ANKI_SPECIALIZE_GET_VALUE(type, ANKI_CONCATENATE(m_, type))
  94. #include <AnKi/Gr/ShaderVariableDataType.def.h>
  95. #undef ANKI_SPECIALIZE_GET_VALUE
  96. template<>
  97. inline const ImageResourcePtr& MaterialVariable::getValue() const
  98. {
  99. ANKI_ASSERT(m_image.get());
  100. return m_image;
  101. }
  102. /// Material variant.
  103. class MaterialVariant
  104. {
  105. friend class MaterialResource;
  106. public:
  107. MaterialVariant() = default;
  108. MaterialVariant(const MaterialVariant&) = delete; // Non-copyable
  109. MaterialVariant& operator=(const MaterialVariant&) = delete; // Non-copyable
  110. const ShaderProgramPtr& getShaderProgram() const
  111. {
  112. return m_prog;
  113. }
  114. U32 getRtShaderGroupHandleIndex() const
  115. {
  116. ANKI_ASSERT(m_rtShaderGroupHandleIndex != kMaxU32);
  117. return m_rtShaderGroupHandleIndex;
  118. }
  119. private:
  120. ShaderProgramPtr m_prog;
  121. U32 m_rtShaderGroupHandleIndex = kMaxU32;
  122. MaterialVariant(MaterialVariant&& b)
  123. {
  124. *this = std::move(b);
  125. }
  126. MaterialVariant& operator=(MaterialVariant&& b)
  127. {
  128. m_prog = std::move(b.m_prog);
  129. m_rtShaderGroupHandleIndex = b.m_rtShaderGroupHandleIndex;
  130. return *this;
  131. }
  132. };
  133. /// Material resource.
  134. ///
  135. /// Material XML file format:
  136. /// @code
  137. /// <material [shadows="0|1"]>
  138. /// <shaderProgram name="name of the shader" />
  139. /// [<mutation>
  140. /// <mutator name="str" value="value"/>
  141. /// </mutation>]
  142. /// </shaderProgram>
  143. ///
  144. /// [<inputs>
  145. /// <input name="name in AnKiLocalConstants struct" value="value(s)"/>
  146. /// </inputs>]
  147. /// </material>
  148. /// @endcode
  149. class MaterialResource : public ResourceObject
  150. {
  151. public:
  152. MaterialResource(CString fname, U32 uuid)
  153. : ResourceObject(fname, uuid)
  154. {
  155. }
  156. ~MaterialResource();
  157. /// Load a material file
  158. Error load(const ResourceFilename& filename, Bool async);
  159. Bool castsShadow() const
  160. {
  161. return !!(m_techniquesMask & (RenderingTechniqueBit::kDepth | RenderingTechniqueBit::kRtShadow));
  162. }
  163. ConstWeakArray<MaterialVariable> getVariables() const
  164. {
  165. return m_vars;
  166. }
  167. Bool supportsSkinning() const
  168. {
  169. return m_supportsSkinning;
  170. }
  171. RenderingTechniqueBit getRenderingTechniques() const
  172. {
  173. ANKI_ASSERT(!!m_techniquesMask);
  174. return m_techniquesMask;
  175. }
  176. /// @note It's thread-safe.
  177. const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
  178. /// Get a buffer with prefilled uniforms.
  179. ConstWeakArray<U8> getPrefilledLocalConstants() const
  180. {
  181. return ConstWeakArray<U8>(static_cast<const U8*>(m_prefilledLocalConstants), m_localConstantsSize);
  182. }
  183. Bool isLoaded() const;
  184. private:
  185. class PartialMutation
  186. {
  187. public:
  188. const ShaderBinaryMutator* m_mutator;
  189. MutatorValue m_value;
  190. };
  191. enum class ShaderTechniqueBit : U8
  192. {
  193. kNone = 0,
  194. kLegacy = 1 << 0,
  195. kMeshSaders = 1 << 1,
  196. kSwMeshletRendering = 1 << 2
  197. };
  198. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS_FRIEND(ShaderTechniqueBit)
  199. ShaderProgramResourcePtr m_prog;
  200. mutable Array4d<MaterialVariant, U(RenderingTechnique::kCount), 2, 2, 2> m_variantMatrix; ///< [technique][skinned][vel][meshletRendering]
  201. mutable RWMutex m_variantMatrixMtx;
  202. ResourceDynamicArray<PartialMutation> m_partialMutation; ///< Only with the non-builtins.
  203. ResourceDynamicArray<MaterialVariable> m_vars;
  204. void* m_prefilledLocalConstants = nullptr;
  205. U32 m_localConstantsSize = 0;
  206. U32 m_presentBuildinMutatorMask = 0;
  207. Bool m_supportsSkinning = false;
  208. RenderingTechniqueBit m_techniquesMask = RenderingTechniqueBit::kNone;
  209. ShaderTechniqueBit m_shaderTechniques = ShaderTechniqueBit::kNone;
  210. mutable Atomic<U32> m_loaded = {0};
  211. Error parseMutators(XmlElement mutatorsEl);
  212. Error parseShaderProgram(XmlElement techniqueEl, Bool async);
  213. Error parseInput(XmlElement inputEl, Bool async, BitSet<128>& varsSet);
  214. Error findBuiltinMutators();
  215. Error createVars();
  216. void prefillLocalConstants();
  217. const MaterialVariable* tryFindVariableInternal(CString name) const;
  218. const MaterialVariable* tryFindVariable(CString name) const
  219. {
  220. return tryFindVariableInternal(name);
  221. }
  222. MaterialVariable* tryFindVariable(CString name)
  223. {
  224. return const_cast<MaterialVariable*>(tryFindVariableInternal(name));
  225. }
  226. };
  227. /// @}
  228. } // end namespace anki