ShaderProgramParser.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright (C) 2009-2023, 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. public:
  20. ShaderCompilerString m_name;
  21. ShaderCompilerDynamicArray<MutatorValue> m_values;
  22. };
  23. /// @memberof ShaderProgramParser
  24. class ShaderProgramParserMember
  25. {
  26. public:
  27. ShaderCompilerString m_name;
  28. ShaderVariableDataType m_type;
  29. U32 m_offset = kMaxU32;
  30. };
  31. /// @memberof ShaderProgramParser
  32. class ShaderProgramParserGhostStruct
  33. {
  34. public:
  35. ShaderCompilerDynamicArray<ShaderProgramParserMember> m_members;
  36. ShaderCompilerString m_name;
  37. };
  38. /// @memberof ShaderProgramParser
  39. class ShaderProgramParserTechnique
  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 16bit // Works only in HLSL. Gain 16bit types but loose min16xxx types
  55. /// #pragma anki technique_start STAGE [NAME] [uses_mutators [USES_MUTATOR1 [USES_MUTATOR2 ...]]]
  56. /// #pragma anki technique_end STAGE [NAME]
  57. ///
  58. /// #pragma anki struct NAME
  59. /// # pragma anki member TYPE NAME
  60. /// ...
  61. /// #pragma anki struct_end
  62. ///
  63. /// None of the pragmas should be in an ifdef-like guard. It's ignored.
  64. class ShaderProgramParser
  65. {
  66. public:
  67. ShaderProgramParser(CString fname, ShaderProgramFilesystemInterface* fsystem, ConstWeakArray<ShaderCompilerDefine> defines);
  68. ShaderProgramParser(const ShaderProgramParser&) = delete; // Non-copyable
  69. ~ShaderProgramParser();
  70. ShaderProgramParser& operator=(const ShaderProgramParser&) = delete; // Non-copyable
  71. /// Parse the file and its includes.
  72. Error parse();
  73. /// Returns true if the mutation should be skipped.
  74. Bool skipMutation(ConstWeakArray<MutatorValue> mutation) const;
  75. /// Get the source (and a few more things) given a list of mutators.
  76. void generateVariant(ConstWeakArray<MutatorValue> mutation, const ShaderProgramParserTechnique& technique, ShaderType shaderType,
  77. ShaderCompilerString& source) const;
  78. ConstWeakArray<ShaderProgramParserMutator> getMutators() const
  79. {
  80. return m_mutators;
  81. }
  82. U64 getHash() const
  83. {
  84. ANKI_ASSERT(m_hash != 0);
  85. return m_hash;
  86. }
  87. ConstWeakArray<ShaderProgramParserGhostStruct> getGhostStructs() const
  88. {
  89. return m_ghostStructs;
  90. }
  91. ConstWeakArray<ShaderProgramParserTechnique> getTechniques() const
  92. {
  93. return m_techniques;
  94. }
  95. Bool compileWith16bitTypes() const
  96. {
  97. return m_16bitTypes;
  98. }
  99. /// Generates the common header that will be used by all AnKi shaders.
  100. static void generateAnkiShaderHeader(ShaderType shaderType, ShaderCompilerString& header);
  101. private:
  102. using Mutator = ShaderProgramParserMutator;
  103. using Member = ShaderProgramParserMember;
  104. using GhostStruct = ShaderProgramParserGhostStruct;
  105. using Technique = ShaderProgramParserTechnique;
  106. class PartialMutationSkip
  107. {
  108. public:
  109. ShaderCompilerDynamicArray<MutatorValue> m_partialMutation;
  110. };
  111. class TechniqueExtra
  112. {
  113. public:
  114. Array<ShaderCompilerStringList, U32(ShaderType::kCount)> m_sourceLines;
  115. Array<ShaderCompilerString, U32(ShaderType::kCount)> m_sources;
  116. };
  117. static constexpr U32 kMaxIncludeDepth = 8;
  118. ShaderCompilerString m_fname;
  119. ShaderProgramFilesystemInterface* m_fsystem = nullptr;
  120. ShaderCompilerDynamicArray<ShaderCompilerString> m_defineNames;
  121. ShaderCompilerDynamicArray<I32> m_defineValues;
  122. U64 m_hash = 0;
  123. ShaderCompilerStringList m_commonSourceLines; ///< Common code until now.
  124. ShaderCompilerDynamicArray<Technique> m_techniques;
  125. ShaderCompilerDynamicArray<TechniqueExtra> m_techniqueExtras;
  126. U32 m_insideTechniqueIdx = kMaxU32;
  127. ShaderType m_insideTechniqueShaderType = ShaderType::kCount;
  128. ShaderCompilerDynamicArray<Mutator> m_mutators;
  129. ShaderCompilerDynamicArray<PartialMutationSkip> m_skipMutations;
  130. ShaderCompilerDynamicArray<GhostStruct> m_ghostStructs;
  131. Bool m_insideStruct = false;
  132. Bool m_16bitTypes = false;
  133. ShaderCompilerStringList& getAppendSourceList()
  134. {
  135. return (insideTechnique()) ? m_techniqueExtras[m_insideTechniqueIdx].m_sourceLines[m_insideTechniqueShaderType] : m_commonSourceLines;
  136. }
  137. Bool insideTechnique() const
  138. {
  139. return m_insideTechniqueIdx < kMaxU32;
  140. }
  141. Error parseFile(CString fname, U32 depth);
  142. Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth, U32 lineNumber);
  143. Error parseInclude(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname, U32 depth);
  144. Error parsePragmaMutator(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  145. Error parsePragmaTechniqueStart(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  146. Error parsePragmaTechniqueEnd(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  147. Error parsePragmaSkipMutation(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  148. Error parsePragmaStructBegin(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  149. Error parsePragmaStructEnd(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  150. Error parsePragmaMember(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  151. Error parsePragma16bit(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
  152. void tokenizeLine(CString line, ShaderCompilerDynamicArray<ShaderCompilerString>& tokens) const;
  153. static Bool tokenIsComment(CString token)
  154. {
  155. return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
  156. }
  157. static Bool mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value);
  158. static ShaderCompilerString sanitizeFilename(CString fname)
  159. {
  160. ShaderCompilerString s = fname;
  161. s.replaceAll("\\", "\\\\");
  162. return s;
  163. }
  164. Error checkNoActiveStruct() const
  165. {
  166. if(m_insideStruct)
  167. {
  168. ANKI_SHADER_COMPILER_LOGE("Unsupported \"pragma anki\" inside \"pragma anki struct\"");
  169. return Error::kUserData;
  170. }
  171. return Error::kNone;
  172. }
  173. Error checkActiveStruct() const
  174. {
  175. if(!m_insideStruct)
  176. {
  177. ANKI_SHADER_COMPILER_LOGE("Expected a \"pragma anki struct\" to open");
  178. return Error::kUserData;
  179. }
  180. return Error::kNone;
  181. }
  182. };
  183. /// @}
  184. } // end namespace anki