ShaderProgramPrePreprocessor.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #ifndef ANKI_RESOURCE_SHADER_PROGRAM_PRE_PREPROCESSOR_H
  2. #define ANKI_RESOURCE_SHADER_PROGRAM_PRE_PREPROCESSOR_H
  3. #include "anki/resource/ShaderProgramCommon.h"
  4. #include <limits>
  5. #include <boost/array.hpp>
  6. #include "anki/util/Vector.h"
  7. namespace anki {
  8. namespace scanner {
  9. class Scanner;
  10. }
  11. /// Helper class used for shader program loading
  12. ///
  13. /// The class fills some of the GLSL spec deficiencies. It adds the include
  14. /// preprocessor directive and the support to have all the shaders in the same
  15. /// file. The file that includes all the shaders is called
  16. /// PrePreprocessor-compatible.
  17. ///
  18. /// The preprocessor pragmas are:
  19. ///
  20. /// - #pragma anki start <vertexShader | tcShader | teShader |
  21. /// geometryShader | fragmentShader>
  22. /// - #pragma anki include "<filename>"
  23. /// - #pragma anki transformFeedbackVarying <varName>
  24. ///
  25. /// @note The order of the "#pragma anki start" is important
  26. class ShaderProgramPrePreprocessor
  27. {
  28. public:
  29. /// It loads a file and parses it
  30. /// @param[in] filename The file to load
  31. /// @exception Exception
  32. ShaderProgramPrePreprocessor(const char* filename)
  33. {
  34. parseFile(filename);
  35. }
  36. /// Destructor does nothing
  37. ~ShaderProgramPrePreprocessor()
  38. {}
  39. /// @name Accessors
  40. /// @{
  41. const Vector<std::string>& getTranformFeedbackVaryings() const
  42. {
  43. return trffbVaryings;
  44. }
  45. const std::string& getShaderSource(ShaderType type)
  46. {
  47. return output.shaderSources[type];
  48. }
  49. /// @}
  50. protected:
  51. /// The pragma base class
  52. struct Pragma
  53. {
  54. std::string definedInFile;
  55. int definedInLine;
  56. Pragma()
  57. : definedInLine(-1)
  58. {}
  59. Pragma(const std::string& definedInFile_, int definedInLine_)
  60. : definedInFile(definedInFile_), definedInLine(definedInLine_)
  61. {}
  62. bool isDefined() const
  63. {
  64. return definedInLine != -1;
  65. }
  66. };
  67. struct IncludePragma: Pragma
  68. {
  69. std::string filename;
  70. };
  71. struct TrffbVaryingPragma: Pragma
  72. {
  73. std::string name;
  74. TrffbVaryingPragma(const std::string& definedInFile_,
  75. int definedInLine_, const std::string& name_)
  76. : Pragma(definedInFile_, definedInLine_), name(name_)
  77. {}
  78. };
  79. struct CodeBeginningPragma: Pragma
  80. {
  81. /// The line number in the PrePreprocessor-compatible
  82. /// file
  83. int globalLine;
  84. CodeBeginningPragma()
  85. : globalLine(-1)
  86. {}
  87. };
  88. /// The output of the class packed in this struct
  89. struct Output
  90. {
  91. friend class PrePreprocessor;
  92. /// Names and and ids for transform feedback varyings
  93. Vector<TrffbVaryingPragma> trffbVaryings;
  94. boost::array<std::string, ST_NUM> shaderSources;
  95. };
  96. Output output; ///< The most important variable
  97. Vector<std::string> trffbVaryings;
  98. /// The parseFileForPragmas fills this
  99. Vector<std::string> sourceLines;
  100. boost::array<CodeBeginningPragma, ST_NUM> shaderStarts;
  101. static boost::array<const char*, ST_NUM> startTokens; ///< XXX
  102. /// Parse a PrePreprocessor formated GLSL file. Use
  103. /// the accessors to get the output
  104. /// @param filename The file to parse
  105. /// @exception Ecxeption
  106. void parseFile(const char* filename);
  107. /// A recursive function that parses a file for pragmas and updates
  108. /// the output
  109. /// @param filename The file to parse
  110. /// @param depth The #line in GLSL does not support filename so an
  111. /// depth it being used. It also tracks the
  112. /// includance depth
  113. /// @exception Exception
  114. void parseFileForPragmas(const std::string& filename, int depth = 0);
  115. /// @todo
  116. void parseStartPragma(scanner::Scanner& scanner,
  117. const std::string& filename, uint depth,
  118. const Vector<std::string>& lines);
  119. /// @todo
  120. void parseIncludePragma(scanner::Scanner& scanner,
  121. const std::string& filename, uint depth,
  122. const Vector<std::string>& lines);
  123. /// @todo
  124. void parseTrffbVarying(scanner::Scanner& scanner,
  125. const std::string& filename, uint depth,
  126. const Vector<std::string>& lines);
  127. /// Searches inside the Output::attributes or Output::trffbVaryings
  128. /// vectors
  129. /// @param vec Output::uniforms or Output::trffbVaryings
  130. /// @param what The name of the varying or attrib
  131. /// @return Iterator to the vector
  132. template<typename Type>
  133. typename Vector<Type>::const_iterator findNamed(
  134. const Vector<Type>& vec,
  135. const std::string& what) const;
  136. void printSourceLines() const; ///< For debugging
  137. /// Add a in the source lines a: #line <line> <depth> // cmnt
  138. void addLinePreProcExpression(uint line, uint depth, const char* cmnt);
  139. };
  140. template<typename Type>
  141. typename Vector<Type>::const_iterator
  142. ShaderProgramPrePreprocessor::findNamed(
  143. const Vector<Type>& vec, const std::string& what) const
  144. {
  145. typename Vector<Type>::const_iterator it = vec.begin();
  146. while(it != vec.end() && it->name != what)
  147. {
  148. ++it;
  149. }
  150. return it;
  151. }
  152. } // end namespace
  153. #endif