| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <AnKi/ShaderCompiler/Common.h>
- #include <AnKi/Util/StringList.h>
- #include <AnKi/Util/WeakArray.h>
- #include <AnKi/Util/DynamicArray.h>
- #include <AnKi/Gr/Utils/Functions.h>
- namespace anki
- {
- // Forward
- class ShaderProgramParser;
- class ShaderProgramParserVariant;
- /// @addtogroup shader_compiler
- /// @{
- /// @memberof ShaderProgramParser
- class ShaderProgramParserMutator
- {
- friend ShaderProgramParser;
- public:
- ShaderProgramParserMutator(GenericMemoryPoolAllocator<U8> alloc)
- : m_name(alloc)
- , m_values(alloc)
- {
- }
- CString getName() const
- {
- return m_name;
- }
- ConstWeakArray<MutatorValue> getValues() const
- {
- return m_values;
- }
- private:
- StringAuto m_name;
- DynamicArrayAuto<MutatorValue> m_values;
- };
- /// @memberof ShaderProgramParser
- class ShaderProgramParserVariant
- {
- friend class ShaderProgramParser;
- public:
- ~ShaderProgramParserVariant()
- {
- for(String& s : m_sources)
- {
- s.destroy(m_alloc);
- }
- }
- CString getSource(ShaderType type) const
- {
- return m_sources[type];
- }
- private:
- GenericMemoryPoolAllocator<U8> m_alloc;
- Array<String, U32(ShaderType::COUNT)> m_sources;
- };
- /// This is a special preprocessor that run before the usual preprocessor. Its purpose is to add some meta information
- /// in the shader programs.
- ///
- /// It supports the following expressions:
- /// #include {<> | ""}
- /// #pragma once
- /// #pragma anki mutator NAME VALUE0 [VALUE1 [VALUE2] ...]
- /// #pragma anki rewrite_mutation NAME_A VALUE0 NAME_B VALUE1 [NAME_C VALUE3...] to
- /// NAME_A VALUE4 NAME_B VALUE5 [NAME_C VALUE6...]
- /// #pragma anki start {vert | tessc | tesse | geom | frag | comp | rgen | ahit | chit | miss | int | call}
- /// #pragma anki end
- /// #pragma anki library "name"
- /// #pragma anki ray_type NUMBER
- /// #pragma anki reflect NAME
- ///
- /// Only the "anki input" should be in an ifdef-like guard. For everything else it's ignored.
- class ShaderProgramParser
- {
- public:
- ShaderProgramParser(CString fname, ShaderProgramFilesystemInterface* fsystem, GenericMemoryPoolAllocator<U8> alloc,
- const ShaderCompilerOptions& compilerOptions);
- ShaderProgramParser(const ShaderProgramParser&) = delete; // Non-copyable
- ~ShaderProgramParser();
- ShaderProgramParser& operator=(const ShaderProgramParser&) = delete; // Non-copyable
- /// Parse the file and its includes.
- ANKI_USE_RESULT Error parse();
- /// Given a mutation convert it to something acceptable. This will reduce the variants.
- /// @return true if the mutation was rewritten.
- Bool rewriteMutation(WeakArray<MutatorValue> mutation) const;
- /// Get the source (and a few more things) given a list of mutators.
- ANKI_USE_RESULT Error generateVariant(ConstWeakArray<MutatorValue> mutation,
- ShaderProgramParserVariant& variant) const;
- ConstWeakArray<ShaderProgramParserMutator> getMutators() const
- {
- return m_mutators;
- }
- ShaderTypeBit getShaderTypes() const
- {
- return m_shaderTypes;
- }
- U64 getHash() const
- {
- ANKI_ASSERT(m_codeSourceHash != 0);
- return m_codeSourceHash;
- }
- CString getLibraryName() const
- {
- return m_libName;
- }
- U32 getRayType() const
- {
- return m_rayType;
- }
- const StringListAuto& getSymbolsToReflect() const
- {
- return m_symbolsToReflect;
- }
- /// Generates the common header that will be used by all AnKi shaders.
- static void generateAnkiShaderHeader(ShaderType shaderType, const ShaderCompilerOptions& compilerOptions,
- StringAuto& header);
- private:
- using Mutator = ShaderProgramParserMutator;
- class MutationRewrite
- {
- public:
- class Record
- {
- public:
- U32 m_mutatorIndex = MAX_U32;
- MutatorValue m_valueFrom = getMaxNumericLimit<MutatorValue>();
- MutatorValue m_valueTo = getMaxNumericLimit<MutatorValue>();
- Bool operator!=(const Record& b) const
- {
- return !(m_mutatorIndex == b.m_mutatorIndex && m_valueFrom == b.m_valueFrom
- && m_valueTo == b.m_valueTo);
- }
- };
- DynamicArrayAuto<Record> m_records;
- MutationRewrite(GenericMemoryPoolAllocator<U8> alloc)
- : m_records(alloc)
- {
- }
- };
- static const U32 MAX_INCLUDE_DEPTH = 8;
- GenericMemoryPoolAllocator<U8> m_alloc;
- StringAuto m_fname;
- ShaderProgramFilesystemInterface* m_fsystem = nullptr;
- StringListAuto m_codeLines = {m_alloc}; ///< The code.
- StringAuto m_codeSource = {m_alloc};
- U64 m_codeSourceHash = 0;
- DynamicArrayAuto<Mutator> m_mutators = {m_alloc};
- DynamicArrayAuto<MutationRewrite> m_mutationRewrites = {m_alloc};
- ShaderTypeBit m_shaderTypes = ShaderTypeBit::NONE;
- Bool m_insideShader = false;
- ShaderCompilerOptions m_compilerOptions;
- StringAuto m_libName = {m_alloc};
- U32 m_rayType = MAX_U32;
- StringListAuto m_symbolsToReflect = {m_alloc};
- ANKI_USE_RESULT Error parseFile(CString fname, U32 depth);
- ANKI_USE_RESULT Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth);
- ANKI_USE_RESULT Error parseInclude(const StringAuto* begin, const StringAuto* end, CString line, CString fname,
- U32 depth);
- ANKI_USE_RESULT Error parsePragmaMutator(const StringAuto* begin, const StringAuto* end, CString line,
- CString fname);
- ANKI_USE_RESULT Error parsePragmaStart(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
- ANKI_USE_RESULT Error parsePragmaEnd(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
- ANKI_USE_RESULT Error parsePragmaRewriteMutation(const StringAuto* begin, const StringAuto* end, CString line,
- CString fname);
- ANKI_USE_RESULT Error parsePragmaLibraryName(const StringAuto* begin, const StringAuto* end, CString line,
- CString fname);
- ANKI_USE_RESULT Error parsePragmaRayType(const StringAuto* begin, const StringAuto* end, CString line,
- CString fname);
- ANKI_USE_RESULT Error parsePragmaReflect(const StringAuto* begin, const StringAuto* end, CString line,
- CString fname);
- void tokenizeLine(CString line, DynamicArrayAuto<StringAuto>& tokens) const;
- static Bool tokenIsComment(CString token)
- {
- return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
- }
- static Bool mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value);
- };
- /// @}
- } // end namespace anki
|