ShaderProgramParser.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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/ShaderCompiler/Common.h>
  7. #include <AnKi/Util/StringList.h>
  8. #include <AnKi/Util/WeakArray.h>
  9. #include <AnKi/Util/DynamicArray.h>
  10. #include <AnKi/Gr/Utils/Functions.h>
  11. namespace anki
  12. {
  13. // Forward
  14. class ShaderProgramParser;
  15. class ShaderProgramParserVariant;
  16. /// @addtogroup shader_compiler
  17. /// @{
  18. /// @memberof ShaderProgramParser
  19. class ShaderProgramParserMutator
  20. {
  21. friend ShaderProgramParser;
  22. public:
  23. ShaderProgramParserMutator(GenericMemoryPoolAllocator<U8> alloc)
  24. : m_name(alloc)
  25. , m_values(alloc)
  26. {
  27. }
  28. CString getName() const
  29. {
  30. return m_name;
  31. }
  32. ConstWeakArray<MutatorValue> getValues() const
  33. {
  34. return m_values;
  35. }
  36. private:
  37. StringAuto m_name;
  38. DynamicArrayAuto<MutatorValue> m_values;
  39. };
  40. /// @memberof ShaderProgramParser
  41. class ShaderProgramParserVariant
  42. {
  43. friend class ShaderProgramParser;
  44. public:
  45. ~ShaderProgramParserVariant()
  46. {
  47. for(String& s : m_sources)
  48. {
  49. s.destroy(m_alloc);
  50. }
  51. }
  52. CString getSource(ShaderType type) const
  53. {
  54. return m_sources[type];
  55. }
  56. private:
  57. GenericMemoryPoolAllocator<U8> m_alloc;
  58. Array<String, U32(ShaderType::COUNT)> m_sources;
  59. };
  60. /// This is a special preprocessor that run before the usual preprocessor. Its purpose is to add some meta information
  61. /// in the shader programs.
  62. ///
  63. /// It supports the following expressions:
  64. /// #include {<> | ""}
  65. /// #pragma once
  66. /// #pragma anki mutator NAME VALUE0 [VALUE1 [VALUE2] ...]
  67. /// #pragma anki rewrite_mutation NAME_A VALUE0 NAME_B VALUE1 [NAME_C VALUE3...] to
  68. /// NAME_A VALUE4 NAME_B VALUE5 [NAME_C VALUE6...]
  69. /// #pragma anki start {vert | tessc | tesse | geom | frag | comp | rgen | ahit | chit | miss | int | call}
  70. /// #pragma anki end
  71. /// #pragma anki library "name"
  72. /// #pragma anki ray_type NUMBER
  73. /// #pragma anki reflect NAME
  74. ///
  75. /// Only the "anki input" should be in an ifdef-like guard. For everything else it's ignored.
  76. class ShaderProgramParser
  77. {
  78. public:
  79. ShaderProgramParser(CString fname, ShaderProgramFilesystemInterface* fsystem, GenericMemoryPoolAllocator<U8> alloc,
  80. const ShaderCompilerOptions& compilerOptions);
  81. ShaderProgramParser(const ShaderProgramParser&) = delete; // Non-copyable
  82. ~ShaderProgramParser();
  83. ShaderProgramParser& operator=(const ShaderProgramParser&) = delete; // Non-copyable
  84. /// Parse the file and its includes.
  85. ANKI_USE_RESULT Error parse();
  86. /// Given a mutation convert it to something acceptable. This will reduce the variants.
  87. /// @return true if the mutation was rewritten.
  88. Bool rewriteMutation(WeakArray<MutatorValue> mutation) const;
  89. /// Get the source (and a few more things) given a list of mutators.
  90. ANKI_USE_RESULT Error generateVariant(ConstWeakArray<MutatorValue> mutation,
  91. ShaderProgramParserVariant& variant) const;
  92. ConstWeakArray<ShaderProgramParserMutator> getMutators() const
  93. {
  94. return m_mutators;
  95. }
  96. ShaderTypeBit getShaderTypes() const
  97. {
  98. return m_shaderTypes;
  99. }
  100. U64 getHash() const
  101. {
  102. ANKI_ASSERT(m_codeSourceHash != 0);
  103. return m_codeSourceHash;
  104. }
  105. CString getLibraryName() const
  106. {
  107. return m_libName;
  108. }
  109. U32 getRayType() const
  110. {
  111. return m_rayType;
  112. }
  113. const StringListAuto& getSymbolsToReflect() const
  114. {
  115. return m_symbolsToReflect;
  116. }
  117. /// Generates the common header that will be used by all AnKi shaders.
  118. static void generateAnkiShaderHeader(ShaderType shaderType, const ShaderCompilerOptions& compilerOptions,
  119. StringAuto& header);
  120. private:
  121. using Mutator = ShaderProgramParserMutator;
  122. class MutationRewrite
  123. {
  124. public:
  125. class Record
  126. {
  127. public:
  128. U32 m_mutatorIndex = MAX_U32;
  129. MutatorValue m_valueFrom = getMaxNumericLimit<MutatorValue>();
  130. MutatorValue m_valueTo = getMaxNumericLimit<MutatorValue>();
  131. Bool operator!=(const Record& b) const
  132. {
  133. return !(m_mutatorIndex == b.m_mutatorIndex && m_valueFrom == b.m_valueFrom
  134. && m_valueTo == b.m_valueTo);
  135. }
  136. };
  137. DynamicArrayAuto<Record> m_records;
  138. MutationRewrite(GenericMemoryPoolAllocator<U8> alloc)
  139. : m_records(alloc)
  140. {
  141. }
  142. };
  143. static const U32 MAX_INCLUDE_DEPTH = 8;
  144. GenericMemoryPoolAllocator<U8> m_alloc;
  145. StringAuto m_fname;
  146. ShaderProgramFilesystemInterface* m_fsystem = nullptr;
  147. StringListAuto m_codeLines = {m_alloc}; ///< The code.
  148. StringAuto m_codeSource = {m_alloc};
  149. U64 m_codeSourceHash = 0;
  150. DynamicArrayAuto<Mutator> m_mutators = {m_alloc};
  151. DynamicArrayAuto<MutationRewrite> m_mutationRewrites = {m_alloc};
  152. ShaderTypeBit m_shaderTypes = ShaderTypeBit::NONE;
  153. Bool m_insideShader = false;
  154. ShaderCompilerOptions m_compilerOptions;
  155. StringAuto m_libName = {m_alloc};
  156. U32 m_rayType = MAX_U32;
  157. StringListAuto m_symbolsToReflect = {m_alloc};
  158. ANKI_USE_RESULT Error parseFile(CString fname, U32 depth);
  159. ANKI_USE_RESULT Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth);
  160. ANKI_USE_RESULT Error parseInclude(const StringAuto* begin, const StringAuto* end, CString line, CString fname,
  161. U32 depth);
  162. ANKI_USE_RESULT Error parsePragmaMutator(const StringAuto* begin, const StringAuto* end, CString line,
  163. CString fname);
  164. ANKI_USE_RESULT Error parsePragmaStart(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  165. ANKI_USE_RESULT Error parsePragmaEnd(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  166. ANKI_USE_RESULT Error parsePragmaRewriteMutation(const StringAuto* begin, const StringAuto* end, CString line,
  167. CString fname);
  168. ANKI_USE_RESULT Error parsePragmaLibraryName(const StringAuto* begin, const StringAuto* end, CString line,
  169. CString fname);
  170. ANKI_USE_RESULT Error parsePragmaRayType(const StringAuto* begin, const StringAuto* end, CString line,
  171. CString fname);
  172. ANKI_USE_RESULT Error parsePragmaReflect(const StringAuto* begin, const StringAuto* end, CString line,
  173. CString fname);
  174. void tokenizeLine(CString line, DynamicArrayAuto<StringAuto>& tokens) const;
  175. static Bool tokenIsComment(CString token)
  176. {
  177. return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
  178. }
  179. static Bool mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value);
  180. };
  181. /// @}
  182. } // end namespace anki