| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <AnKi/Resource/ResourceObject.h>
- #include <AnKi/Resource/RenderingKey.h>
- #include <AnKi/Resource/ShaderProgramResource.h>
- #include <AnKi/Resource/ImageResource.h>
- #include <AnKi/Math.h>
- #include <AnKi/Util/Enum.h>
- #include <AnKi/Shaders/Include/MaterialTypes.h>
- namespace anki {
- // Forward
- class XmlElement;
- /// @addtogroup resource
- /// @{
- /// The ID of builtin mutators.
- enum class BuiltinMutatorId : U8
- {
- NONE = 0,
- TECHNIQUE,
- LOD,
- BONES,
- VELOCITY,
- COUNT,
- FIRST = 0
- };
- ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BuiltinMutatorId)
- /// Holds the shader variables. It's a container for shader program variables that share the same name.
- class MaterialVariable
- {
- friend class MaterialVariant;
- friend class MaterialResource;
- public:
- MaterialVariable();
- MaterialVariable(const MaterialVariable&) = delete; // Non-copyable
- MaterialVariable(MaterialVariable&& b)
- {
- *this = std::move(b);
- }
- ~MaterialVariable();
- MaterialVariable& operator=(const MaterialVariable&) = delete; // Non-copyable
- MaterialVariable& operator=(MaterialVariable&& b)
- {
- m_name = std::move(b.m_name);
- m_offsetInLocalUniforms = b.m_offsetInLocalUniforms;
- m_opaqueBinding = b.m_opaqueBinding;
- m_dataType = b.m_dataType;
- m_Mat4 = b.m_Mat4;
- m_image = std::move(b.m_image);
- return *this;
- }
- CString getName() const
- {
- return m_name;
- }
- template<typename T>
- const T& getValue() const;
- Bool isBoundableTexture() const
- {
- return m_dataType >= ShaderVariableDataType::TEXTURE_FIRST
- && m_dataType <= ShaderVariableDataType::TEXTURE_LAST;
- }
- Bool isBindlessTexture() const
- {
- return m_dataType == ShaderVariableDataType::U32 && m_image.get();
- }
- Bool isUniform() const
- {
- return !isBoundableTexture();
- }
- ShaderVariableDataType getDataType() const
- {
- ANKI_ASSERT(m_dataType != ShaderVariableDataType::NONE);
- return m_dataType;
- }
- /// Get the binding of a texture or a sampler type of material variable.
- U32 getTextureBinding() const
- {
- ANKI_ASSERT(m_opaqueBinding != MAX_U32 && isBoundableTexture());
- return m_opaqueBinding;
- }
- U32 getOffsetInLocalUniforms() const
- {
- ANKI_ASSERT(m_offsetInLocalUniforms != MAX_U32);
- return m_offsetInLocalUniforms;
- }
- protected:
- String m_name;
- U32 m_offsetInLocalUniforms = MAX_U32;
- U32 m_opaqueBinding = MAX_U32; ///< Binding for textures and samplers.
- ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
- /// Values
- /// @{
- union
- {
- #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) type ANKI_CONCATENATE(m_, type);
- #include <AnKi/Gr/ShaderVariableDataType.defs.h>
- #undef ANKI_SVDT_MACRO
- };
- ImageResourcePtr m_image;
- /// @}
- };
- // Specialize the MaterialVariable::getValue
- #define ANKI_SPECIALIZE_GET_VALUE(t_, var_, shaderType_) \
- template<> \
- inline const t_& MaterialVariable::getValue<t_>() const \
- { \
- ANKI_ASSERT(m_dataType == ShaderVariableDataType::shaderType_); \
- return var_; \
- }
- #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) \
- ANKI_SPECIALIZE_GET_VALUE(type, ANKI_CONCATENATE(m_, type), capital)
- #include <AnKi/Gr/ShaderVariableDataType.defs.h>
- #undef ANKI_SVDT_MACRO
- #undef ANKI_SPECIALIZE_GET_VALUE
- template<>
- inline const ImageResourcePtr& MaterialVariable::getValue() const
- {
- ANKI_ASSERT(m_image.get());
- return m_image;
- }
- /// Material variant.
- class MaterialVariant
- {
- friend class MaterialResource;
- public:
- MaterialVariant() = default;
- MaterialVariant(const MaterialVariant&) = delete; // Non-copyable
- MaterialVariant& operator=(const MaterialVariant&) = delete; // Non-copyable
- const ShaderProgramPtr& getShaderProgram() const
- {
- return m_prog;
- }
- U32 getRtShaderGroupHandleIndex() const
- {
- ANKI_ASSERT(m_rtShaderGroupHandleIndex != MAX_U32);
- return m_rtShaderGroupHandleIndex;
- }
- private:
- ShaderProgramPtr m_prog;
- U32 m_rtShaderGroupHandleIndex = MAX_U32;
- MaterialVariant(MaterialVariant&& b)
- {
- *this = std::move(b);
- }
- MaterialVariant& operator=(MaterialVariant&& b)
- {
- m_prog = std::move(b.m_prog);
- m_rtShaderGroupHandleIndex = b.m_rtShaderGroupHandleIndex;
- return *this;
- }
- };
- /// Material resource.
- ///
- /// Material XML file format:
- /// @code
- /// <material [shadows="0|1"]>
- /// <shaderPrograms>
- /// <shaderProgram name="name of the shader">
- /// [<mutation>
- /// <mutator name="str" value="value"/>
- /// </mutation>]
- /// </shaderProgram>
- ///
- /// [<shaderProgram ...>
- /// ...
- /// </shaderProgram>]
- /// </shaderPrograms>
- ///
- /// [<inputs>
- /// <input name="name in AnKiMaterialUniforms struct or opaque type" value="value(s)"/> (1)
- /// </inputs>]
- /// </material>
- /// @endcode
- ///
- /// (1): Only for non-builtins.
- class MaterialResource : public ResourceObject
- {
- public:
- MaterialResource(ResourceManager* manager);
- ~MaterialResource();
- /// Load a material file
- ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
- Bool castsShadow() const
- {
- return !!(m_techniquesMask & (RenderingTechniqueBit::SHADOW | RenderingTechniqueBit::RT_SHADOW));
- }
- ConstWeakArray<MaterialVariable> getVariables() const
- {
- return m_vars;
- }
- Bool supportsSkinning() const
- {
- return m_supportsSkinning;
- }
- RenderingTechniqueBit getRenderingTechniques() const
- {
- ANKI_ASSERT(!!m_techniquesMask);
- return m_techniquesMask;
- }
- /// Get all GPU resources of this material. Will be used for GPU refcounting.
- ConstWeakArray<TexturePtr> getAllTextures() const
- {
- return m_textures;
- }
- /// @note It's thread-safe.
- const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
- /// Get a buffer with prefilled uniforms.
- ConstWeakArray<U8> getPrefilledLocalUniforms() const
- {
- return ConstWeakArray<U8>(static_cast<const U8*>(m_prefilledLocalUniforms), m_localUniformsSize);
- }
- private:
- class PartialMutation
- {
- public:
- const ShaderProgramResourceMutator* m_mutator;
- MutatorValue m_value;
- };
- class Program;
- DynamicArray<Program> m_programs;
- Array<U8, U(RenderingTechnique::COUNT)> m_techniqueToProgram;
- RenderingTechniqueBit m_techniquesMask = RenderingTechniqueBit::NONE;
- DynamicArray<MaterialVariable> m_vars;
- Bool m_supportsSkinning = false;
- DynamicArray<TexturePtr> m_textures;
- void* m_prefilledLocalUniforms = nullptr;
- U32 m_localUniformsSize = 0;
- ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl, Program& prog);
- ANKI_USE_RESULT Error parseShaderProgram(XmlElement techniqueEl, Bool async);
- ANKI_USE_RESULT Error parseInput(XmlElement inputEl, Bool async, BitSet<128>& varsSet);
- ANKI_USE_RESULT Error findBuiltinMutators(Program& prog);
- ANKI_USE_RESULT Error createVars(Program& prog);
- void prefillLocalUniforms();
- const MaterialVariable* tryFindVariableInternal(CString name) const;
- const MaterialVariable* tryFindVariable(CString name) const
- {
- return tryFindVariableInternal(name);
- }
- MaterialVariable* tryFindVariable(CString name)
- {
- return const_cast<MaterialVariable*>(tryFindVariableInternal(name));
- }
- };
- /// @}
- } // end namespace anki
|