| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // Copyright (C) 2009-present, 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>
- namespace anki {
- // Forward
- class ShaderParser;
- /// @addtogroup shader_compiler
- /// @{
- /// @memberof ShaderParser
- class ShaderParserMutator
- {
- public:
- ShaderCompilerString m_name;
- ShaderCompilerDynamicArray<MutatorValue> m_values;
- };
- /// @memberof ShaderParser
- class ShaderParserGhostStructMember
- {
- public:
- ShaderCompilerString m_name;
- ShaderVariableDataType m_type;
- U32 m_offset = kMaxU32;
- Array<U8, 16> m_defaultValues = {};
- };
- /// @memberof ShaderParser
- class ShaderParserGhostStruct
- {
- public:
- ShaderCompilerDynamicArray<ShaderParserGhostStructMember> m_members;
- ShaderCompilerString m_name;
- };
- /// @memberof ShaderParser
- class ShaderParserTechnique
- {
- public:
- ShaderCompilerString m_name;
- ShaderTypeBit m_shaderTypes = ShaderTypeBit::kNone;
- Array<U64, U32(ShaderType::kCount)> m_activeMutators = {};
- };
- /// 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 skip_mutation MUTATOR0 VALUE0 [MUTATOR1 VALUE1 [MUTATOR2 VALUE2 ...]]
- /// #pragma anki technique [NAME] STAGE0 [STAGE1 ...] [mutators [MUTATOR0 [MUTATOR1 ...]]]
- /// #pragma anki extra_compiler_args ARG0 [ARG1 [ARG2...]]
- ///
- /// #pragma anki struct NAME
- /// # pragma anki member TYPE NAME [DEFAULT_VALUE0 [DEFAULT_VALUE1 ...]]
- /// ...
- /// #pragma anki struct_end
- ///
- /// None of the pragmas should be in an ifdef-like guard. It's ignored.
- class ShaderParser
- {
- public:
- ShaderParser(CString fname, ShaderCompilerFilesystemInterface* fsystem, ConstWeakArray<ShaderCompilerDefine> defines);
- ShaderParser(const ShaderParser&) = delete; // Non-copyable
- ~ShaderParser();
- ShaderParser& operator=(const ShaderParser&) = delete; // Non-copyable
- /// Parse the file and its includes.
- Error parse();
- /// Returns true if the mutation should be skipped.
- Bool skipMutation(ConstWeakArray<MutatorValue> mutation) const;
- /// Get the source (and a few more things) given a list of mutators.
- void generateVariant(ConstWeakArray<MutatorValue> mutation, const ShaderParserTechnique& technique, ShaderType shaderType,
- ShaderCompilerString& source) const;
- ConstWeakArray<ShaderParserMutator> getMutators() const
- {
- return m_mutators;
- }
- U64 getHash() const
- {
- ANKI_ASSERT(m_hash != 0);
- return m_hash;
- }
- ConstWeakArray<ShaderParserGhostStruct> getGhostStructs() const
- {
- return m_ghostStructs;
- }
- ConstWeakArray<ShaderParserTechnique> getTechniques() const
- {
- return m_techniques;
- }
- ConstWeakArray<CString> getExtraCompilerArgs() const
- {
- return m_extraCompilerArgsCString;
- }
- /// Generates the common header that will be used by all AnKi shaders.
- static void generateAnkiShaderHeader(ShaderType shaderType, ShaderCompilerString& header);
- private:
- using Mutator = ShaderParserMutator;
- using Member = ShaderParserGhostStructMember;
- using GhostStruct = ShaderParserGhostStruct;
- using Technique = ShaderParserTechnique;
- class PartialMutationSkip
- {
- public:
- ShaderCompilerDynamicArray<MutatorValue> m_partialMutation;
- };
- static constexpr U32 kMaxIncludeDepth = 8;
- ShaderCompilerString m_fname;
- ShaderCompilerFilesystemInterface* m_fsystem = nullptr;
- ShaderCompilerDynamicArray<ShaderCompilerString> m_defineNames;
- ShaderCompilerDynamicArray<I32> m_defineValues;
- U64 m_hash = 0;
- ShaderCompilerStringList m_sourceLines;
- ShaderCompilerString m_source;
- ShaderCompilerDynamicArray<Technique> m_techniques;
- ShaderCompilerDynamicArray<Mutator> m_mutators;
- ShaderCompilerDynamicArray<PartialMutationSkip> m_skipMutations;
- ShaderCompilerDynamicArray<GhostStruct> m_ghostStructs;
- Bool m_insideStruct = false;
- ShaderCompilerDynamicArray<ShaderCompilerString> m_extraCompilerArgs;
- ShaderCompilerDynamicArray<CString> m_extraCompilerArgsCString;
- Error parseFile(CString fname, U32 depth);
- Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth, U32 lineNumber);
- Error parseInclude(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname, U32 depth);
- Error parsePragmaMutator(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
- Error parsePragmaTechnique(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
- Error parsePragmaSkipMutation(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
- Error parsePragmaStructBegin(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
- Error parsePragmaStructEnd(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
- Error parsePragmaMember(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
- Error parseExtraCompilerArgs(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname);
- void tokenizeLine(CString line, ShaderCompilerDynamicArray<ShaderCompilerString>& tokens) const;
- static Bool tokenIsComment(CString token)
- {
- return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
- }
- static Bool mutatorHasValue(const ShaderParserMutator& mutator, MutatorValue value);
- static ShaderCompilerString sanitizeFilename(CString fname)
- {
- ShaderCompilerString s = fname;
- s.replaceAll("\\", "\\\\");
- return s;
- }
- Error checkNoActiveStruct() const
- {
- if(m_insideStruct)
- {
- ANKI_SHADER_COMPILER_LOGE("Unsupported \"pragma anki\" inside \"pragma anki struct\"");
- return Error::kUserData;
- }
- return Error::kNone;
- }
- Error checkActiveStruct() const
- {
- if(!m_insideStruct)
- {
- ANKI_SHADER_COMPILER_LOGE("Expected a \"pragma anki struct\" to open");
- return Error::kUserData;
- }
- return Error::kNone;
- }
- };
- /// @}
- } // end namespace anki
|