ShaderProgramParser.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. StringRaii m_name;
  36. DynamicArrayRaii<MutatorValue> m_values;
  37. };
  38. /// @memberof ShaderProgramParser
  39. class ShaderProgramParserMember
  40. {
  41. public:
  42. StringRaii m_name;
  43. ShaderVariableDataType m_type;
  44. U32 m_dependentMutator = kMaxU32;
  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. DynamicArrayRaii<ShaderProgramParserMember> m_members;
  56. StringRaii 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::kCount)> 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. 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. Error generateVariant(ConstWeakArray<MutatorValue> mutation, ShaderProgramParserVariant& variant) const;
  117. ConstWeakArray<ShaderProgramParserMutator> getMutators() const
  118. {
  119. return m_mutators;
  120. }
  121. ShaderTypeBit getShaderTypes() const
  122. {
  123. return m_shaderTypes;
  124. }
  125. U64 getHash() const
  126. {
  127. ANKI_ASSERT(m_codeSourceHash != 0);
  128. return m_codeSourceHash;
  129. }
  130. CString getLibraryName() const
  131. {
  132. return m_libName;
  133. }
  134. U32 getRayType() const
  135. {
  136. return m_rayType;
  137. }
  138. const StringListRaii& getSymbolsToReflect() const
  139. {
  140. return m_symbolsToReflect;
  141. }
  142. ConstWeakArray<ShaderProgramParserGhostStruct> getGhostStructs() const
  143. {
  144. return m_ghostStructs;
  145. }
  146. /// Generates the common header that will be used by all AnKi shaders.
  147. static void generateAnkiShaderHeader(ShaderType shaderType, const ShaderCompilerOptions& compilerOptions,
  148. StringRaii& header);
  149. private:
  150. using Mutator = ShaderProgramParserMutator;
  151. using Member = ShaderProgramParserMember;
  152. using GhostStruct = ShaderProgramParserGhostStruct;
  153. class PartialMutationSkip
  154. {
  155. public:
  156. DynamicArrayRaii<MutatorValue> m_partialMutation;
  157. PartialMutationSkip(const GenericMemoryPoolAllocator<U8>& alloc)
  158. : m_partialMutation(alloc)
  159. {
  160. }
  161. };
  162. static constexpr U32 MAX_INCLUDE_DEPTH = 8;
  163. GenericMemoryPoolAllocator<U8> m_alloc;
  164. StringRaii m_fname;
  165. ShaderProgramFilesystemInterface* m_fsystem = nullptr;
  166. StringListRaii m_codeLines = {m_alloc}; ///< The code.
  167. StringRaii m_codeSource = {m_alloc};
  168. U64 m_codeSourceHash = 0;
  169. DynamicArrayRaii<Mutator> m_mutators = {m_alloc};
  170. DynamicArrayRaii<PartialMutationSkip> m_skipMutations = {m_alloc};
  171. ShaderTypeBit m_shaderTypes = ShaderTypeBit::kNone;
  172. Bool m_insideShader = false;
  173. ShaderCompilerOptions m_compilerOptions;
  174. StringRaii m_libName = {m_alloc};
  175. U32 m_rayType = kMaxU32;
  176. StringListRaii m_symbolsToReflect = {m_alloc};
  177. DynamicArrayRaii<GhostStruct> m_ghostStructs = {m_alloc};
  178. Bool m_insideStruct = false;
  179. Error parseFile(CString fname, U32 depth);
  180. Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth);
  181. Error parseInclude(const StringRaii* begin, const StringRaii* end, CString line, CString fname, U32 depth);
  182. Error parsePragmaMutator(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  183. Error parsePragmaStart(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  184. Error parsePragmaEnd(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  185. Error parsePragmaSkipMutation(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  186. Error parsePragmaLibraryName(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  187. Error parsePragmaRayType(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  188. Error parsePragmaReflect(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  189. Error parsePragmaStructBegin(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  190. Error parsePragmaStructEnd(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  191. Error parsePragmaMember(const StringRaii* begin, const StringRaii* end, CString line, CString fname);
  192. void tokenizeLine(CString line, DynamicArrayRaii<StringRaii>& tokens) const;
  193. static Bool tokenIsComment(CString token)
  194. {
  195. return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
  196. }
  197. static Bool mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value);
  198. Error checkNoActiveStruct() const
  199. {
  200. if(m_insideStruct)
  201. {
  202. ANKI_SHADER_COMPILER_LOGE("Unsupported \"pragma anki\" inside \"pragma anki struct\"");
  203. return Error::kUserData;
  204. }
  205. return Error::kNone;
  206. }
  207. Error checkActiveStruct() const
  208. {
  209. if(!m_insideStruct)
  210. {
  211. ANKI_SHADER_COMPILER_LOGE("Expected a \"pragma anki struct\" to open");
  212. return Error::kUserData;
  213. }
  214. return Error::kNone;
  215. }
  216. };
  217. /// @}
  218. } // end namespace anki