| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- // Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <anki/shader_compiler/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, U(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}
- /// #pragma anki end
- ///
- /// Only the "anki input" should be in an ifdef-like guard. For everything else it's ignored.
- class ShaderProgramParser : public NonCopyable
- {
- public:
- ShaderProgramParser(CString fname,
- ShaderProgramFilesystemInterface* fsystem,
- GenericMemoryPoolAllocator<U8> alloc,
- const GpuDeviceCapabilities& gpuCapabilities,
- const BindlessLimits& bindlessLimits);
- ~ShaderProgramParser();
- /// 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;
- }
- 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};
- DynamicArrayAuto<Mutator> m_mutators = {m_alloc};
- DynamicArrayAuto<MutationRewrite> m_mutationRewrites = {m_alloc};
- ShaderTypeBit m_shaderTypes = ShaderTypeBit::NONE;
- Bool m_insideShader = false;
- GpuDeviceCapabilities m_gpuCapabilities;
- BindlessLimits m_bindlessLimits;
- 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);
- 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
|