ShaderProgramResource.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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/ShaderCompiler/ShaderProgramCompiler.h>
  8. #include <AnKi/Gr/Utils/Functions.h>
  9. #include <AnKi/Gr/ShaderProgram.h>
  10. #include <AnKi/Util/BitSet.h>
  11. #include <AnKi/Util/String.h>
  12. #include <AnKi/Util/HashMap.h>
  13. #include <AnKi/Util/WeakArray.h>
  14. #include <AnKi/Math.h>
  15. namespace anki
  16. {
  17. // Forward
  18. class ShaderProgramResourceVariantInitInfo;
  19. /// @addtogroup resource
  20. /// @{
  21. /// The means to mutate a shader program.
  22. /// @memberof ShaderProgramResource
  23. class ShaderProgramResourceMutator
  24. {
  25. public:
  26. CString m_name;
  27. ConstWeakArray<MutatorValue> m_values;
  28. ShaderProgramResourceMutator() = default;
  29. ShaderProgramResourceMutator(const ShaderProgramResourceMutator&) = delete; // Non-copyable
  30. ShaderProgramResourceMutator& operator=(const ShaderProgramResourceMutator&) = delete; // Non-copyable
  31. Bool valueExists(MutatorValue v) const
  32. {
  33. for(MutatorValue x : m_values)
  34. {
  35. if(v == x)
  36. {
  37. return true;
  38. }
  39. }
  40. return false;
  41. }
  42. };
  43. /// Shader program resource variant.
  44. class ShaderProgramResourceConstant
  45. {
  46. public:
  47. String m_name;
  48. ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
  49. U32 m_index = MAX_U32;
  50. };
  51. /// Shader program resource variant.
  52. class ShaderProgramResourceVariant
  53. {
  54. friend class ShaderProgramResource;
  55. public:
  56. ShaderProgramResourceVariant();
  57. ~ShaderProgramResourceVariant();
  58. /// @note On ray tracing program resources it points to the actual ray tracing program that contains everything.
  59. const ShaderProgramPtr& getProgram() const
  60. {
  61. return m_prog;
  62. }
  63. /// Return true if the the variable is active in this variant.
  64. Bool isConstantActive(const ShaderProgramResourceConstant& var) const
  65. {
  66. return m_activeConsts.get(var.m_index);
  67. }
  68. const ShaderProgramBinaryVariant& getBinaryVariant() const
  69. {
  70. ANKI_ASSERT(m_binaryVariant);
  71. return *m_binaryVariant;
  72. }
  73. const Array<U32, 3>& getWorkgroupSizes() const
  74. {
  75. ANKI_ASSERT(m_workgroupSizes[0] != MAX_U32 && m_workgroupSizes[0] != 0);
  76. ANKI_ASSERT(m_workgroupSizes[1] != MAX_U32 && m_workgroupSizes[1] != 0);
  77. ANKI_ASSERT(m_workgroupSizes[2] != MAX_U32 && m_workgroupSizes[2] != 0);
  78. return m_workgroupSizes;
  79. }
  80. /// Only for hit ray tracing programs.
  81. U32 getShaderGroupHandleIndex() const
  82. {
  83. ANKI_ASSERT(m_shaderGroupHandleIndex < MAX_U32);
  84. return m_shaderGroupHandleIndex;
  85. }
  86. private:
  87. ShaderProgramPtr m_prog;
  88. const ShaderProgramBinaryVariant* m_binaryVariant = nullptr;
  89. BitSet<128, U64> m_activeConsts = {false};
  90. Array<U32, 3> m_workgroupSizes;
  91. U32 m_shaderGroupHandleIndex = MAX_U32; ///< Cache the index of the handle here.
  92. };
  93. /// The value of a constant.
  94. class ShaderProgramResourceConstantValue
  95. {
  96. public:
  97. union
  98. {
  99. U32 m_uint;
  100. UVec2 m_uvec2;
  101. UVec3 m_uvec3;
  102. UVec4 m_uvec4;
  103. I32 m_int;
  104. IVec2 m_ivec2;
  105. IVec3 m_ivec3;
  106. IVec4 m_ivec4;
  107. F32 m_float;
  108. Vec2 m_vec2;
  109. Vec3 m_vec3;
  110. Vec4 m_vec4;
  111. };
  112. U32 m_constantIndex;
  113. U8 _m_padding[sizeof(Vec4) - sizeof(m_constantIndex)];
  114. ShaderProgramResourceConstantValue()
  115. {
  116. zeroMemory(*this);
  117. }
  118. };
  119. static_assert(sizeof(ShaderProgramResourceConstantValue) == sizeof(Vec4) * 2, "Need it to be packed");
  120. /// Smart initializer of multiple ShaderProgramResourceConstantValue.
  121. class ShaderProgramResourceVariantInitInfo
  122. {
  123. friend class ShaderProgramResource;
  124. public:
  125. ShaderProgramResourceVariantInitInfo()
  126. {
  127. }
  128. ShaderProgramResourceVariantInitInfo(const ShaderProgramResourcePtr& ptr)
  129. : m_ptr(ptr)
  130. {
  131. }
  132. ~ShaderProgramResourceVariantInitInfo()
  133. {
  134. }
  135. template<typename T>
  136. ShaderProgramResourceVariantInitInfo& addConstant(CString name, const T& value);
  137. ShaderProgramResourceVariantInitInfo& addMutation(CString name, MutatorValue t);
  138. private:
  139. static constexpr U32 MAX_CONSTANTS = 32;
  140. static constexpr U32 MAX_MUTATORS = 32;
  141. ShaderProgramResourcePtr m_ptr;
  142. Array<ShaderProgramResourceConstantValue, MAX_CONSTANTS> m_constantValues;
  143. BitSet<MAX_CONSTANTS> m_setConstants = {false};
  144. Array<MutatorValue, MAX_MUTATORS> m_mutation; ///< The order of storing the values is important. It will be hashed.
  145. BitSet<MAX_MUTATORS> m_setMutators = {false};
  146. };
  147. /// Shader program resource. It loads special AnKi programs.
  148. class ShaderProgramResource : public ResourceObject
  149. {
  150. public:
  151. ShaderProgramResource(ResourceManager* manager);
  152. ~ShaderProgramResource();
  153. /// Load the resource.
  154. ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
  155. /// Get the array of constants.
  156. ConstWeakArray<ShaderProgramResourceConstant> getConstants() const
  157. {
  158. return m_consts;
  159. }
  160. /// Try to find a constant.
  161. const ShaderProgramResourceConstant* tryFindConstant(CString name) const
  162. {
  163. for(const ShaderProgramResourceConstant& m : m_consts)
  164. {
  165. if(m.m_name == name)
  166. {
  167. return &m;
  168. }
  169. }
  170. return nullptr;
  171. }
  172. /// Get the array of mutators.
  173. ConstWeakArray<ShaderProgramResourceMutator> getMutators() const
  174. {
  175. return m_mutators;
  176. }
  177. /// Try to find a mutator.
  178. const ShaderProgramResourceMutator* tryFindMutator(CString name) const
  179. {
  180. for(const ShaderProgramResourceMutator& m : m_mutators)
  181. {
  182. if(m.m_name == name)
  183. {
  184. return &m;
  185. }
  186. }
  187. return nullptr;
  188. }
  189. ShaderTypeBit getStages() const
  190. {
  191. return m_shaderStages;
  192. }
  193. const ShaderProgramBinary& getBinary() const
  194. {
  195. return m_binary.getBinary();
  196. }
  197. /// Get or create a graphics shader program variant.
  198. /// @note It's thread-safe.
  199. void getOrCreateVariant(const ShaderProgramResourceVariantInitInfo& info,
  200. const ShaderProgramResourceVariant*& variant) const;
  201. /// @copydoc getOrCreateVariant
  202. void getOrCreateVariant(const ShaderProgramResourceVariant*& variant) const
  203. {
  204. getOrCreateVariant(ShaderProgramResourceVariantInitInfo(), variant);
  205. }
  206. private:
  207. using Mutator = ShaderProgramResourceMutator;
  208. using Const = ShaderProgramResourceConstant;
  209. ShaderProgramBinaryWrapper m_binary;
  210. DynamicArray<Const> m_consts;
  211. DynamicArray<Mutator> m_mutators;
  212. class ConstMapping
  213. {
  214. public:
  215. U32 m_component = 0;
  216. U32 m_constsIdx = 0; ///< Index in m_consts
  217. };
  218. DynamicArray<ConstMapping> m_constBinaryMapping;
  219. mutable HashMap<U64, ShaderProgramResourceVariant*> m_variants;
  220. mutable RWMutex m_mtx;
  221. ShaderTypeBit m_shaderStages = ShaderTypeBit::NONE;
  222. void initVariant(const ShaderProgramResourceVariantInitInfo& info, ShaderProgramResourceVariant& variant) const;
  223. static ANKI_USE_RESULT Error parseConst(CString constName, U32& componentIdx, U32& componentCount, CString& name);
  224. };
  225. template<typename T>
  226. inline ShaderProgramResourceVariantInitInfo& ShaderProgramResourceVariantInitInfo::addConstant(CString name,
  227. const T& value)
  228. {
  229. const ShaderProgramResourceConstant* in = m_ptr->tryFindConstant(name);
  230. if(in != nullptr)
  231. {
  232. ANKI_ASSERT(in->m_dataType == getShaderVariableTypeFromTypename<T>());
  233. const U32 constIdx = U32(in - m_ptr->getConstants().getBegin());
  234. m_constantValues[constIdx].m_constantIndex = constIdx;
  235. memcpy(&m_constantValues[constIdx].m_int, &value, sizeof(T));
  236. m_setConstants.set(constIdx);
  237. }
  238. else
  239. {
  240. ANKI_RESOURCE_LOGW("Constant not found: %s", name.cstr());
  241. }
  242. return *this;
  243. }
  244. inline ShaderProgramResourceVariantInitInfo& ShaderProgramResourceVariantInitInfo::addMutation(CString name,
  245. MutatorValue t)
  246. {
  247. const ShaderProgramResourceMutator* m = m_ptr->tryFindMutator(name);
  248. ANKI_ASSERT(m);
  249. ANKI_ASSERT(m->valueExists(t));
  250. const PtrSize mutatorIdx = m - m_ptr->getMutators().getBegin();
  251. m_mutation[mutatorIdx] = t;
  252. m_setMutators.set(mutatorIdx);
  253. return *this;
  254. }
  255. /// @}
  256. } // end namespace anki