ShaderProgramParser.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Copyright (C) 2009-2020, 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/shader_compiler/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, U(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}
  70. /// #pragma anki end
  71. ///
  72. /// Only the "anki input" should be in an ifdef-like guard. For everything else it's ignored.
  73. class ShaderProgramParser : public NonCopyable
  74. {
  75. public:
  76. ShaderProgramParser(CString fname,
  77. ShaderProgramFilesystemInterface* fsystem,
  78. GenericMemoryPoolAllocator<U8> alloc,
  79. const GpuDeviceCapabilities& gpuCapabilities,
  80. const BindlessLimits& bindlessLimits);
  81. ~ShaderProgramParser();
  82. /// Parse the file and its includes.
  83. ANKI_USE_RESULT Error parse();
  84. /// Given a mutation convert it to something acceptable. This will reduce the variants.
  85. /// @return true if the mutation was rewritten.
  86. Bool rewriteMutation(WeakArray<MutatorValue> mutation) const;
  87. /// Get the source (and a few more things) given a list of mutators.
  88. ANKI_USE_RESULT Error generateVariant(
  89. ConstWeakArray<MutatorValue> mutation, ShaderProgramParserVariant& variant) const;
  90. ConstWeakArray<ShaderProgramParserMutator> getMutators() const
  91. {
  92. return m_mutators;
  93. }
  94. ShaderTypeBit getShaderTypes() const
  95. {
  96. return m_shaderTypes;
  97. }
  98. private:
  99. using Mutator = ShaderProgramParserMutator;
  100. class MutationRewrite
  101. {
  102. public:
  103. class Record
  104. {
  105. public:
  106. U32 m_mutatorIndex = MAX_U32;
  107. MutatorValue m_valueFrom = getMaxNumericLimit<MutatorValue>();
  108. MutatorValue m_valueTo = getMaxNumericLimit<MutatorValue>();
  109. Bool operator!=(const Record& b) const
  110. {
  111. return !(
  112. m_mutatorIndex == b.m_mutatorIndex && m_valueFrom == b.m_valueFrom && m_valueTo == b.m_valueTo);
  113. }
  114. };
  115. DynamicArrayAuto<Record> m_records;
  116. MutationRewrite(GenericMemoryPoolAllocator<U8> alloc)
  117. : m_records(alloc)
  118. {
  119. }
  120. };
  121. static const U32 MAX_INCLUDE_DEPTH = 8;
  122. GenericMemoryPoolAllocator<U8> m_alloc;
  123. StringAuto m_fname;
  124. ShaderProgramFilesystemInterface* m_fsystem = nullptr;
  125. StringListAuto m_codeLines = {m_alloc}; ///< The code.
  126. StringAuto m_codeSource = {m_alloc};
  127. DynamicArrayAuto<Mutator> m_mutators = {m_alloc};
  128. DynamicArrayAuto<MutationRewrite> m_mutationRewrites = {m_alloc};
  129. ShaderTypeBit m_shaderTypes = ShaderTypeBit::NONE;
  130. Bool m_insideShader = false;
  131. GpuDeviceCapabilities m_gpuCapabilities;
  132. BindlessLimits m_bindlessLimits;
  133. ANKI_USE_RESULT Error parseFile(CString fname, U32 depth);
  134. ANKI_USE_RESULT Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth);
  135. ANKI_USE_RESULT Error parseInclude(
  136. const StringAuto* begin, const StringAuto* end, CString line, CString fname, U32 depth);
  137. ANKI_USE_RESULT Error parsePragmaMutator(
  138. const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  139. ANKI_USE_RESULT Error parsePragmaStart(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  140. ANKI_USE_RESULT Error parsePragmaEnd(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  141. ANKI_USE_RESULT Error parsePragmaRewriteMutation(
  142. const StringAuto* begin, const StringAuto* end, CString line, CString fname);
  143. void tokenizeLine(CString line, DynamicArrayAuto<StringAuto>& tokens) const;
  144. static Bool tokenIsComment(CString token)
  145. {
  146. return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
  147. }
  148. static Bool mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value);
  149. };
  150. /// @}
  151. } // end namespace anki