ShaderProgramParser.h 6.3 KB

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