2
0

MaterialResource.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright (C) 2009-2022, 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. NONE = 0,
  22. TECHNIQUE,
  23. LOD,
  24. BONES,
  25. VELOCITY,
  26. COUNT,
  27. FIRST = 0
  28. };
  29. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BuiltinMutatorId)
  30. /// Holds the shader variables. It's a container for shader program variables that share the same name.
  31. class MaterialVariable
  32. {
  33. friend class MaterialVariant;
  34. friend class MaterialResource;
  35. public:
  36. MaterialVariable();
  37. MaterialVariable(const MaterialVariable&) = delete; // Non-copyable
  38. MaterialVariable(MaterialVariable&& b)
  39. {
  40. *this = std::move(b);
  41. }
  42. ~MaterialVariable();
  43. MaterialVariable& operator=(const MaterialVariable&) = delete; // Non-copyable
  44. MaterialVariable& operator=(MaterialVariable&& b)
  45. {
  46. m_name = std::move(b.m_name);
  47. m_offsetInLocalUniforms = b.m_offsetInLocalUniforms;
  48. m_opaqueBinding = b.m_opaqueBinding;
  49. m_dataType = b.m_dataType;
  50. m_Mat4 = b.m_Mat4;
  51. m_image = std::move(b.m_image);
  52. return *this;
  53. }
  54. CString getName() const
  55. {
  56. return m_name;
  57. }
  58. template<typename T>
  59. const T& getValue() const;
  60. Bool isBoundableTexture() const
  61. {
  62. return m_dataType >= ShaderVariableDataType::TEXTURE_FIRST
  63. && m_dataType <= ShaderVariableDataType::TEXTURE_LAST;
  64. }
  65. Bool isBindlessTexture() const
  66. {
  67. return m_dataType == ShaderVariableDataType::U32 && m_image.get();
  68. }
  69. Bool isUniform() const
  70. {
  71. return !isBoundableTexture();
  72. }
  73. ShaderVariableDataType getDataType() const
  74. {
  75. ANKI_ASSERT(m_dataType != ShaderVariableDataType::NONE);
  76. return m_dataType;
  77. }
  78. /// Get the binding of a texture or a sampler type of material variable.
  79. U32 getTextureBinding() const
  80. {
  81. ANKI_ASSERT(m_opaqueBinding != MAX_U32 && isBoundableTexture());
  82. return m_opaqueBinding;
  83. }
  84. U32 getOffsetInLocalUniforms() const
  85. {
  86. ANKI_ASSERT(m_offsetInLocalUniforms != MAX_U32);
  87. return m_offsetInLocalUniforms;
  88. }
  89. protected:
  90. String m_name;
  91. U32 m_offsetInLocalUniforms = MAX_U32;
  92. U32 m_opaqueBinding = MAX_U32; ///< Binding for textures and samplers.
  93. ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
  94. /// Values
  95. /// @{
  96. union
  97. {
  98. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) type ANKI_CONCATENATE(m_, type);
  99. #include <AnKi/Gr/ShaderVariableDataType.defs.h>
  100. #undef ANKI_SVDT_MACRO
  101. };
  102. ImageResourcePtr m_image;
  103. /// @}
  104. };
  105. // Specialize the MaterialVariable::getValue
  106. #define ANKI_SPECIALIZE_GET_VALUE(t_, var_, shaderType_) \
  107. template<> \
  108. inline const t_& MaterialVariable::getValue<t_>() const \
  109. { \
  110. ANKI_ASSERT(m_dataType == ShaderVariableDataType::shaderType_); \
  111. return var_; \
  112. }
  113. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) \
  114. ANKI_SPECIALIZE_GET_VALUE(type, ANKI_CONCATENATE(m_, type), capital)
  115. #include <AnKi/Gr/ShaderVariableDataType.defs.h>
  116. #undef ANKI_SVDT_MACRO
  117. #undef ANKI_SPECIALIZE_GET_VALUE
  118. template<>
  119. inline const ImageResourcePtr& MaterialVariable::getValue() const
  120. {
  121. ANKI_ASSERT(m_image.get());
  122. return m_image;
  123. }
  124. /// Material variant.
  125. class MaterialVariant
  126. {
  127. friend class MaterialResource;
  128. public:
  129. MaterialVariant() = default;
  130. MaterialVariant(const MaterialVariant&) = delete; // Non-copyable
  131. MaterialVariant& operator=(const MaterialVariant&) = delete; // Non-copyable
  132. const ShaderProgramPtr& getShaderProgram() const
  133. {
  134. return m_prog;
  135. }
  136. U32 getRtShaderGroupHandleIndex() const
  137. {
  138. ANKI_ASSERT(m_rtShaderGroupHandleIndex != MAX_U32);
  139. return m_rtShaderGroupHandleIndex;
  140. }
  141. private:
  142. ShaderProgramPtr m_prog;
  143. U32 m_rtShaderGroupHandleIndex = MAX_U32;
  144. MaterialVariant(MaterialVariant&& b)
  145. {
  146. *this = std::move(b);
  147. }
  148. MaterialVariant& operator=(MaterialVariant&& b)
  149. {
  150. m_prog = std::move(b.m_prog);
  151. m_rtShaderGroupHandleIndex = b.m_rtShaderGroupHandleIndex;
  152. return *this;
  153. }
  154. };
  155. /// Material resource.
  156. ///
  157. /// Material XML file format:
  158. /// @code
  159. /// <material [shadows="0|1"]>
  160. /// <shaderPrograms>
  161. /// <shaderProgram name="name of the shader">
  162. /// [<mutation>
  163. /// <mutator name="str" value="value"/>
  164. /// </mutation>]
  165. /// </shaderProgram>
  166. ///
  167. /// [<shaderProgram ...>
  168. /// ...
  169. /// </shaderProgram>]
  170. /// </shaderPrograms>
  171. ///
  172. /// [<inputs>
  173. /// <input name="name in AnKiMaterialUniforms struct or opaque type" value="value(s)"/> (1)
  174. /// </inputs>]
  175. /// </material>
  176. /// @endcode
  177. ///
  178. /// (1): Only for non-builtins.
  179. class MaterialResource : public ResourceObject
  180. {
  181. public:
  182. MaterialResource(ResourceManager* manager);
  183. ~MaterialResource();
  184. /// Load a material file
  185. ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
  186. Bool castsShadow() const
  187. {
  188. return !!(m_techniquesMask & (RenderingTechniqueBit::SHADOW | RenderingTechniqueBit::RT_SHADOW));
  189. }
  190. ConstWeakArray<MaterialVariable> getVariables() const
  191. {
  192. return m_vars;
  193. }
  194. Bool supportsSkinning() const
  195. {
  196. return m_supportsSkinning;
  197. }
  198. RenderingTechniqueBit getRenderingTechniques() const
  199. {
  200. ANKI_ASSERT(!!m_techniquesMask);
  201. return m_techniquesMask;
  202. }
  203. /// Get all GPU resources of this material. Will be used for GPU refcounting.
  204. ConstWeakArray<TexturePtr> getAllTextures() const
  205. {
  206. return m_textures;
  207. }
  208. /// @note It's thread-safe.
  209. const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
  210. /// Get a buffer with prefilled uniforms.
  211. ConstWeakArray<U8> getPrefilledLocalUniforms() const
  212. {
  213. return ConstWeakArray<U8>(static_cast<const U8*>(m_prefilledLocalUniforms), m_localUniformsSize);
  214. }
  215. private:
  216. class PartialMutation
  217. {
  218. public:
  219. const ShaderProgramResourceMutator* m_mutator;
  220. MutatorValue m_value;
  221. };
  222. class Program;
  223. DynamicArray<Program> m_programs;
  224. Array<U8, U(RenderingTechnique::COUNT)> m_techniqueToProgram;
  225. RenderingTechniqueBit m_techniquesMask = RenderingTechniqueBit::NONE;
  226. DynamicArray<MaterialVariable> m_vars;
  227. Bool m_supportsSkinning = false;
  228. DynamicArray<TexturePtr> m_textures;
  229. void* m_prefilledLocalUniforms = nullptr;
  230. U32 m_localUniformsSize = 0;
  231. ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl, Program& prog);
  232. ANKI_USE_RESULT Error parseShaderProgram(XmlElement techniqueEl, Bool async);
  233. ANKI_USE_RESULT Error parseInput(XmlElement inputEl, Bool async, BitSet<128>& varsSet);
  234. ANKI_USE_RESULT Error findBuiltinMutators(Program& prog);
  235. ANKI_USE_RESULT Error createVars(Program& prog);
  236. void prefillLocalUniforms();
  237. const MaterialVariable* tryFindVariableInternal(CString name) const;
  238. const MaterialVariable* tryFindVariable(CString name) const
  239. {
  240. return tryFindVariableInternal(name);
  241. }
  242. MaterialVariable* tryFindVariable(CString name)
  243. {
  244. return const_cast<MaterialVariable*>(tryFindVariableInternal(name));
  245. }
  246. };
  247. /// @}
  248. } // end namespace anki