ShaderParser.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright (C) 2009-present, 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 ShaderParser;
  13. /// @addtogroup shader_compiler
  14. /// @{
  15. /// @memberof ShaderParser
  16. class ShaderParserMutator
  17. {
  18. public:
  19. ShaderCompilerString m_name;
  20. ShaderCompilerDynamicArray<MutatorValue> m_values;
  21. };
  22. /// @memberof ShaderParser
  23. class ShaderParserGhostStructMember
  24. {
  25. public:
  26. ShaderCompilerString m_name;
  27. ShaderVariableDataType m_type;
  28. U32 m_offset = kMaxU32;
  29. Array<U8, 16> m_defaultValues = {};
  30. };
  31. /// @memberof ShaderParser
  32. class ShaderParserGhostStruct
  33. {
  34. public:
  35. ShaderCompilerDynamicArray<ShaderParserGhostStructMember> m_members;
  36. ShaderCompilerString m_name;
  37. };
  38. /// @memberof ShaderParser
  39. class ShaderParserTechnique
  40. {
  41. public:
  42. ShaderCompilerString m_name;
  43. ShaderTypeBit m_shaderTypes = ShaderTypeBit::kNone;
  44. Array<U64, U32(ShaderType::kCount)> m_activeMutators = {};
  45. };
  46. /// This is a special preprocessor that run before the usual preprocessor. Its purpose is to add some meta information
  47. /// in the shader programs.
  48. ///
  49. /// It supports the following expressions:
  50. /// #include {<> | ""}
  51. /// #pragma once
  52. /// #pragma anki mutator NAME VALUE0 [VALUE1 [VALUE2 ...]]
  53. /// #pragma anki skip_mutation MUTATOR0 VALUE0 [MUTATOR1 VALUE1 [MUTATOR2 VALUE2 ...]]
  54. /// #pragma anki technique [NAME] STAGE0 [STAGE1 ...] [mutators [MUTATOR0 [MUTATOR1 ...]]]
  55. /// #pragma anki extra_compiler_args ARG0 [ARG1 [ARG2...]]
  56. ///
  57. /// #pragma anki struct NAME
  58. /// # pragma anki member TYPE NAME [DEFAULT_VALUE0 [DEFAULT_VALUE1 ...]]
  59. /// ...
  60. /// #pragma anki struct_end
  61. ///
  62. /// None of the pragmas should be in an ifdef-like guard. It's ignored.
  63. class ShaderParser
  64. {
  65. public:
  66. ShaderParser(CString fname, ShaderCompilerFilesystemInterface* fsystem, ConstWeakArray<ShaderCompilerDefine> defines);
  67. ShaderParser(const ShaderParser&) = delete; // Non-copyable
  68. ~ShaderParser();
  69. ShaderParser& operator=(const ShaderParser&) = delete; // Non-copyable
  70. /// Parse the file and its includes.
  71. Error parse();
  72. /// Returns true if the mutation should be skipped.
  73. Bool skipMutation(ConstWeakArray<MutatorValue> mutation) const;
  74. /// Get the source (and a few more things) given a list of mutators.
  75. void generateVariant(ConstWeakArray<MutatorValue> mutation, const ShaderParserTechnique& technique, ShaderType shaderType,
  76. ShaderCompilerString& source) const;
  77. ConstWeakArray<ShaderParserMutator> getMutators() const
  78. {
  79. return m_mutators;
  80. }
  81. U64 getHash() const
  82. {
  83. ANKI_ASSERT(m_hash != 0);
  84. return m_hash;
  85. }
  86. ConstWeakArray<ShaderParserGhostStruct> getGhostStructs() const
  87. {
  88. return m_ghostStructs;
  89. }
  90. ConstWeakArray<ShaderParserTechnique> getTechniques() const
  91. {
  92. return m_techniques;
  93. }
  94. ConstWeakArray<CString> getExtraCompilerArgs() const
  95. {
  96. return m_extraCompilerArgsCString;
  97. }
  98. /// Generates the common header that will be used by all AnKi shaders.
  99. static void generateAnkiShaderHeader(ShaderType shaderType, ShaderCompilerString& header);
  100. private:
  101. using Mutator = ShaderParserMutator;
  102. using Member = ShaderParserGhostStructMember;
  103. using GhostStruct = ShaderParserGhostStruct;
  104. using Technique = ShaderParserTechnique;
  105. class PartialMutationSkip
  106. {
  107. public:
  108. ShaderCompilerDynamicArray<MutatorValue> m_partialMutation;
  109. };
  110. static constexpr U32 kMaxIncludeDepth = 8;
  111. ShaderCompilerString m_fname;
  112. ShaderCompilerFilesystemInterface* m_fsystem = nullptr;
  113. ShaderCompilerDynamicArray<ShaderCompilerString> m_defineNames;
  114. ShaderCompilerDynamicArray<I32> m_defineValues;
  115. U64 m_hash = 0;
  116. ShaderCompilerStringList m_sourceLines;
  117. ShaderCompilerString m_source;
  118. ShaderCompilerDynamicArray<Technique> m_techniques;
  119. ShaderCompilerDynamicArray<Mutator> m_mutators;
  120. ShaderCompilerDynamicArray<PartialMutationSkip> m_skipMutations;
  121. ShaderCompilerDynamicArray<GhostStruct> m_ghostStructs;
  122. Bool m_insideStruct = false;
  123. ShaderCompilerDynamicArray<ShaderCompilerString> m_extraCompilerArgs;
  124. ShaderCompilerDynamicArray<CString> m_extraCompilerArgsCString;
  125. Error parseFile(CString fname, U32 depth);
  126. Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth, U32 lineNumber);
  127. Error parseInclude(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname, U32 depth);
  128. Error parsePragmaMutator(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  129. Error parsePragmaTechnique(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  130. Error parsePragmaSkipMutation(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  131. Error parsePragmaStructBegin(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  132. Error parsePragmaStructEnd(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  133. Error parsePragmaMember(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  134. Error parseExtraCompilerArgs(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  135. void tokenizeLine(CString line, ShaderCompilerDynamicArray<ShaderCompilerString>& tokens) const;
  136. static Bool tokenIsComment(CString token)
  137. {
  138. return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
  139. }
  140. static Bool mutatorHasValue(const ShaderParserMutator& mutator, MutatorValue value);
  141. static ShaderCompilerString sanitizeFilename(CString fname)
  142. {
  143. ShaderCompilerString s = fname;
  144. s.replaceAll("\\", "\\\\");
  145. return s;
  146. }
  147. Error checkNoActiveStruct() const
  148. {
  149. if(m_insideStruct)
  150. {
  151. ANKI_SHADER_COMPILER_LOGE("Unsupported \"pragma anki\" inside \"pragma anki struct\"");
  152. return Error::kUserData;
  153. }
  154. return Error::kNone;
  155. }
  156. Error checkActiveStruct() const
  157. {
  158. if(!m_insideStruct)
  159. {
  160. ANKI_SHADER_COMPILER_LOGE("Expected a \"pragma anki struct\" to open");
  161. return Error::kUserData;
  162. }
  163. return Error::kNone;
  164. }
  165. };
  166. /// @}
  167. } // end namespace anki