ShaderProgramParser.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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/ShaderCompiler/Common.h>
  7. #include <AnKi/Util/StringList.h>
  8. #include <AnKi/Util/WeakArray.h>
  9. #include <AnKi/Util/DynamicArray.h>
  10. namespace anki {
  11. // Forward
  12. class ShaderProgramParser;
  13. class ShaderProgramParserVariant;
  14. /// @addtogroup shader_compiler
  15. /// @{
  16. /// @memberof ShaderProgramParser
  17. class ShaderProgramParserMutator
  18. {
  19. friend ShaderProgramParser;
  20. public:
  21. ShaderProgramParserMutator(GenericMemoryPoolAllocator<U8> alloc)
  22. : m_name(alloc)
  23. , m_values(alloc)
  24. {
  25. }
  26. CString getName() const
  27. {
  28. return m_name;
  29. }
  30. ConstWeakArray<MutatorValue> getValues() const
  31. {
  32. return m_values;
  33. }
  34. private:
  35. StringAuto m_name;
  36. DynamicArrayAuto<MutatorValue> m_values;
  37. };
  38. /// @memberof ShaderProgramParser
  39. class ShaderProgramParserMember
  40. {
  41. public:
  42. StringAuto m_name;
  43. ShaderVariableDataType m_type;
  44. U32 m_dependentMutator = MAX_U32;
  45. MutatorValue m_mutatorValue = 0;
  46. ShaderProgramParserMember(GenericMemoryPoolAllocator<U8> alloc)
  47. : m_name(alloc)
  48. {
  49. }
  50. };
  51. /// @memberof ShaderProgramParser
  52. class ShaderProgramParserGhostStruct
  53. {
  54. public:
  55. DynamicArrayAuto<ShaderProgramParserMember> m_members;
  56. StringAuto m_name;
  57. ShaderProgramParserGhostStruct(GenericMemoryPoolAllocator<U8> alloc)
  58. : m_members(alloc)
  59. , m_name(alloc)
  60. {
  61. }
  62. };
  63. /// @memberof ShaderProgramParser
  64. class ShaderProgramParserVariant
  65. {
  66. friend class ShaderProgramParser;
  67. public:
  68. ~ShaderProgramParserVariant()
  69. {
  70. for(String& s : m_sources)
  71. {
  72. s.destroy(m_alloc);
  73. }
  74. }
  75. CString getSource(ShaderType type) const
  76. {
  77. return m_sources[type];
  78. }
  79. private:
  80. GenericMemoryPoolAllocator<U8> m_alloc;
  81. Array<String, U32(ShaderType::COUNT)> m_sources;
  82. };
  83. /// This is a special preprocessor that run before the usual preprocessor. Its purpose is to add some meta information
  84. /// in the shader programs.
  85. ///
  86. /// It supports the following expressions:
  87. /// #include {<> | ""}
  88. /// #pragma once
  89. /// #pragma anki mutator NAME VALUE0 [VALUE1 [VALUE2] ...]
  90. /// #pragma anki start {vert | tessc | tesse | geom | frag | comp | rgen | ahit | chit | miss | int | call}
  91. /// #pragma anki end
  92. /// #pragma anki library "name"
  93. /// #pragma anki ray_type NUMBER
  94. /// #pragma anki reflect NAME
  95. /// #pragma anki skip_mutation MUTATOR0 VALUE0 MUTATOR1 VALUE1 [MUTATOR2 VALUE2 ...]
  96. ///
  97. /// #pragma anki struct NAME
  98. /// # pragma anki member [ANKI_RP] TYPE NAME [if MUTATOR_NAME is MUTATOR_VALUE]
  99. /// ...
  100. /// #pragma anki struct end
  101. ///
  102. /// None of the pragmas should be in an ifdef-like guard. It's ignored.
  103. class ShaderProgramParser
  104. {
  105. public:
  106. ShaderProgramParser(CString fname, ShaderProgramFilesystemInterface* fsystem, GenericMemoryPoolAllocator<U8> alloc,
  107. const ShaderCompilerOptions& compilerOptions);
  108. ShaderProgramParser(const ShaderProgramParser&) = delete; // Non-copyable
  109. ~ShaderProgramParser();
  110. ShaderProgramParser& operator=(const ShaderProgramParser&) = delete; // Non-copyable
  111. /// Parse the file and its includes.
  112. ANKI_USE_RESULT Error parse();
  113. /// Returns true if the mutation should be skipped.
  114. Bool skipMutation(ConstWeakArray<MutatorValue> mutation) const;
  115. /// Get the source (and a few more things) given a list of mutators.
  116. ANKI_USE_RESULT Error generateVariant(ConstWeakArray<MutatorValue> mutation,
  117. ShaderProgramParserVariant& variant) const;
  118. ConstWeakArray<ShaderProgramParserMutator> getMutators() const
  119. {
  120. return m_mutators;
  121. }
  122. ShaderTypeBit getShaderTypes() const
  123. {
  124. return m_shaderTypes;
  125. }
  126. U64 getHash() const
  127. {
  128. ANKI_ASSERT(m_codeSourceHash != 0);
  129. return m_codeSourceHash;
  130. }
  131. CString getLibraryName() const
  132. {
  133. return m_libName;
  134. }
  135. U32 getRayType() const
  136. {
  137. return m_rayType;
  138. }
  139. const StringListAuto& getSymbolsToReflect() const
  140. {
  141. return m_symbolsToReflect;
  142. }
  143. ConstWeakArray<ShaderProgramParserGhostStruct> getGhostStructs() const
  144. {
  145. return m_ghostStructs;
  146. }
  147. /// Generates the common header that will be used by all AnKi shaders.
  148. static void generateAnkiShaderHeader(ShaderType shaderType, const ShaderCompilerOptions& compilerOptions,
  149. StringAuto& header);
  150. private:
  151. using Mutator = ShaderProgramParserMutator;
  152. using Member = ShaderProgramParserMember;
  153. using GhostStruct = ShaderProgramParserGhostStruct;
  154. class PartialMutationSkip;
  155. static constexpr U32 MAX_INCLUDE_DEPTH = 8;
  156. GenericMemoryPoolAllocator<U8> m_alloc;
  157. StringAuto m_fname;
  158. ShaderProgramFilesystemInterface* m_fsystem = nullptr;
  159. StringListAuto m_codeLines = {m_alloc}; ///< The code.
  160. StringAuto m_codeSource = {m_alloc};
  161. U64 m_codeSourceHash = 0;
  162. DynamicArrayAuto<Mutator> m_mutators = {m_alloc};
  163. DynamicArrayAuto<PartialMutationSkip> m_skipMutations = {m_alloc};
  164. ShaderTypeBit m_shaderTypes = ShaderTypeBit::NONE;
  165. Bool m_insideShader = false;
  166. ShaderCompilerOptions m_compilerOptions;
  167. StringAuto m_libName = {m_alloc};
  168. U32 m_rayType = MAX_U32;
  169. StringListAuto m_symbolsToReflect = {m_alloc};
  170. DynamicArrayAuto<GhostStruct> m_ghostStructs = {m_alloc};
  171. Bool m_insideStruct = false;
  172. ANKI_USE_RESULT Error parseFile(CString fname, U32 depth);
  173. ANKI_USE_RESULT Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth);
  174. ANKI_USE_RESULT Error parseInclude(const StringAuto* begin, const StringAuto* end, CString line, CString fname,
  175. U32 depth);
  176. ANKI_USE_RESULT Error parsePragmaMutator(const StringAuto* begin, const StringAuto* end, CString line,
  177. CString fname);
  178. ANKI_USE_RESULT Error parsePragmaStart(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  179. ANKI_USE_RESULT Error parsePragmaEnd(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  180. ANKI_USE_RESULT Error parsePragmaSkipMutation(const StringAuto* begin, const StringAuto* end, CString line,
  181. CString fname);
  182. ANKI_USE_RESULT Error parsePragmaLibraryName(const StringAuto* begin, const StringAuto* end, CString line,
  183. CString fname);
  184. ANKI_USE_RESULT Error parsePragmaRayType(const StringAuto* begin, const StringAuto* end, CString line,
  185. CString fname);
  186. ANKI_USE_RESULT Error parsePragmaReflect(const StringAuto* begin, const StringAuto* end, CString line,
  187. CString fname);
  188. ANKI_USE_RESULT Error parsePragmaStructBegin(const StringAuto* begin, const StringAuto* end, CString line,
  189. CString fname);
  190. ANKI_USE_RESULT Error parsePragmaStructEnd(const StringAuto* begin, const StringAuto* end, CString line,
  191. CString fname);
  192. ANKI_USE_RESULT Error parsePragmaMember(const StringAuto* begin, const StringAuto* end, CString line,
  193. CString fname);
  194. void tokenizeLine(CString line, DynamicArrayAuto<StringAuto>& tokens) const;
  195. static Bool tokenIsComment(CString token)
  196. {
  197. return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
  198. }
  199. static Bool mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value);
  200. ANKI_USE_RESULT Error checkNoActiveStruct() const
  201. {
  202. if(m_insideStruct)
  203. {
  204. ANKI_SHADER_COMPILER_LOGE("Unsupported \"pragma anki\" inside \"pragma anki struct\"");
  205. return Error::USER_DATA;
  206. }
  207. return Error::NONE;
  208. }
  209. ANKI_USE_RESULT Error checkActiveStruct() const
  210. {
  211. if(!m_insideStruct)
  212. {
  213. ANKI_SHADER_COMPILER_LOGE("Expected a \"pragma anki struct\" to open");
  214. return Error::USER_DATA;
  215. }
  216. return Error::NONE;
  217. }
  218. };
  219. /// @}
  220. } // end namespace anki