Browse Source

Write the new MaterialResource

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
6698705fc9

+ 3 - 1
AnKi/Config.h.cmake

@@ -175,7 +175,8 @@
 #	define ANKI_HOT __attribute__ ((hot))
 #	define ANKI_UNREACHABLE() __builtin_unreachable()
 #	define ANKI_PREFETCH_MEMORY(addr) __builtin_prefetch(addr)
-#	define ANKI_CHECK_FORMAT(fmtArgIdx, firstArgIdx) __attribute__((format(printf, fmtArgIdx + 1, firstArgIdx + 1))) // On methods need to include "this"
+#	define ANKI_CHECK_FORMAT(fmtArgIdx, firstArgIdx) __attribute__((format(printf, fmtArgIdx + 1, firstArgIdx + 1))) // On methods you need to include "this"
+#	define ANKI_PURE __attribute__((pure))
 #else
 #	define ANKI_LIKELY(x) (x)
 #	define ANKI_UNLIKELY(x) (x)
@@ -189,6 +190,7 @@
 #	define ANKI_UNREACHABLE() __assume(false)
 #	define ANKI_PREFETCH_MEMORY(addr) (void)(addr)
 #	define ANKI_CHECK_FORMAT(fmtArgIdx, firstArgIdx)
+#	define ANKI_PURE
 #endif
 
 // Pack structs

+ 1 - 0
AnKi/Gr/CMakeLists.txt

@@ -3,6 +3,7 @@ set(COMMON
 	"GrObject.cpp"
 	"RenderGraph.cpp"
 	"ShaderProgram.cpp"
+	"Enums.cpp"
 	"Utils/FrameGpuAllocator.cpp"
 	"Utils/Functions.cpp")
 

+ 48 - 0
AnKi/Gr/Enums.cpp

@@ -0,0 +1,48 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Gr/Enums.h>
+#include <AnKi/Math.h>
+
+namespace anki {
+
+/// @warning Don't use Array because the compilers can't handle it for some reason.
+static constexpr ShaderVariableDataTypeInfo SVD_INFOS[] = {
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) {ANKI_STRINGIZE(type), sizeof(type), false},
+#define ANKI_SVDT_MACRO_OPAQUE(capital, type) {ANKI_STRINGIZE(type), MAX_U32, true},
+#include <AnKi/Gr/ShaderVariableDataType.defs.h>
+#undef ANKI_SVDT_MACRO
+#undef ANKI_SVDT_MACRO_OPAQUE
+	{"", 0, false}};
+
+const ShaderVariableDataTypeInfo& getShaderVariableDataTypeInfo(ShaderVariableDataType type)
+{
+	ANKI_ASSERT(type > ShaderVariableDataType::NONE && type < ShaderVariableDataType::COUNT);
+	return SVD_INFOS[U32(type)];
+}
+
+/// @warning Don't use Array because the compilers can't handle it for some reason.
+static constexpr FormatInfo FORMAT_INFOS[] = {
+#define ANKI_FORMAT_DEF(type, id, componentCount, texelSize, blockWidth, blockHeight, blockSize, shaderType, \
+						depthStencil) \
+	{componentCount, \
+	 texelSize, \
+	 blockWidth, \
+	 blockHeight, \
+	 blockSize, \
+	 shaderType, \
+	 DepthStencilAspectBit::depthStencil, \
+	 ANKI_STRINGIZE(type)},
+#include <AnKi/Gr/Format.defs.h>
+#undef ANKI_FORMAT_DEF
+	{0, 0, 0, 0, 0, 0, DepthStencilAspectBit::NONE, ""}};
+
+const FormatInfo& getFormatInfo(Format fmt)
+{
+	ANKI_ASSERT(fmt > Format::NONE && fmt < Format::COUNT);
+	return FORMAT_INFOS[U32(fmt)];
+}
+
+} // namespace anki

+ 30 - 49
AnKi/Gr/Enums.h

@@ -140,6 +140,8 @@ enum class Format : U32
 	type = id,
 #include <AnKi/Gr/Format.defs.h>
 #undef ANKI_FORMAT_DEF
+
+	COUNT
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Format)
 
@@ -155,62 +157,30 @@ public:
 	U8 m_shaderType; ///< It's 0 if the shader sees it as float, 1 if uint and 2 if signed int.
 	DepthStencilAspectBit m_depthStencil; ///< Depth/stencil mask.
 	const char* m_name;
-};
 
-/// Get info for a specific Format.
-inline FormatInfo getFormatInfo(Format fmt)
-{
-	ANKI_ASSERT(fmt != Format::NONE);
-	FormatInfo out;
-	switch(fmt)
+	Bool isDepthStencil() const
 	{
-#define ANKI_FORMAT_DEF(type, id, componentCount, texelSize, blockWidth, blockHeight, blockSize, shaderType, \
-						depthStencil) \
-	case Format::type: \
-		out.m_componentCount = componentCount; \
-		out.m_texelSize = texelSize; \
-		out.m_blockWidth = blockWidth; \
-		out.m_blockHeight = blockHeight; \
-		out.m_blockSize = blockSize; \
-		out.m_shaderType = shaderType; \
-		out.m_depthStencil = DepthStencilAspectBit::depthStencil; \
-		out.m_name = #type; \
-		break;
-#include <AnKi/Gr/Format.defs.h>
-#undef ANKI_FORMAT_DEF
-
-	default:
-		ANKI_ASSERT(0);
-		out = {};
+		return m_depthStencil != DepthStencilAspectBit::NONE;
 	}
 
-	return out;
-}
-
-inline Bool formatIsDepthStencil(const Format fmt)
-{
-	return getFormatInfo(fmt).m_depthStencil != DepthStencilAspectBit::NONE;
-}
-
-inline Bool formatIsDepth(const Format fmt)
-{
-	return !!(getFormatInfo(fmt).m_depthStencil & DepthStencilAspectBit::DEPTH);
-}
+	Bool isDepth() const
+	{
+		return !!(m_depthStencil & DepthStencilAspectBit::DEPTH);
+	}
 
-inline Bool formatIsStencil(const Format fmt)
-{
-	return !!(getFormatInfo(fmt).m_depthStencil & DepthStencilAspectBit::STENCIL);
-}
+	Bool isStencil() const
+	{
+		return !!(m_depthStencil & DepthStencilAspectBit::STENCIL);
+	}
 
-inline Bool formatIsCompressed(const Format fmt)
-{
-	return getFormatInfo(fmt).m_blockSize > 0;
-}
+	Bool isCompressed() const
+	{
+		return m_blockSize > 0;
+	}
+};
 
-inline DepthStencilAspectBit computeFormatAspect(const Format fmt)
-{
-	return getFormatInfo(fmt).m_depthStencil;
-}
+/// Get info for a specific Format.
+ANKI_PURE const FormatInfo& getFormatInfo(Format fmt);
 
 /// Texture type.
 enum class TextureType : U8
@@ -355,6 +325,7 @@ enum class ShaderVariableDataType : U8
 #undef ANKI_SVDT_MACRO_OPAQUE
 
 	// Derived
+	COUNT,
 
 	NUMERICS_FIRST = I32,
 	NUMERICS_LAST = MAT4,
@@ -379,6 +350,16 @@ enum class ShaderVariableDataType : U8
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(ShaderVariableDataType)
 
+class ShaderVariableDataTypeInfo
+{
+public:
+	const Char* m_name;
+	U32 m_size; ///< Size of the type.
+	Bool m_opaque;
+};
+
+ANKI_PURE const ShaderVariableDataTypeInfo& getShaderVariableDataTypeInfo(ShaderVariableDataType type);
+
 /// Occlusion query result bit.
 enum class OcclusionQueryResultBit : U8
 {

+ 1 - 1
AnKi/Gr/TextureView.h

@@ -31,7 +31,7 @@ public:
 		m_faceCount =
 			(tex->getTextureType() == TextureType::CUBE_ARRAY || tex->getTextureType() == TextureType::CUBE) ? 6 : 1;
 
-		m_depthStencilAspect = computeFormatAspect(tex->getFormat());
+		m_depthStencilAspect = getFormatInfo(tex->getFormat()).m_depthStencil;
 	}
 
 	TextureViewInitInfo(CString name = {})

+ 0 - 23
AnKi/Gr/Utils/Functions.cpp

@@ -138,27 +138,4 @@ void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlo
 	}
 }
 
-const CString shaderVariableDataTypeToString(ShaderVariableDataType t)
-{
-	switch(t)
-	{
-	case ShaderVariableDataType::NONE:
-		return "NONE";
-
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
-	case ShaderVariableDataType::capital: \
-		return ANKI_STRINGIZE(type);
-#define ANKI_SVDT_MACRO_OPAQUE(capital, type) ANKI_SVDT_MACRO(capital, type, 0, 0, 0)
-#include <AnKi/Gr/ShaderVariableDataType.defs.h>
-#undef ANKI_SVDT_MACRO
-#undef ANKI_SVDT_MACRO_OPAQUE
-
-	default:
-		ANKI_ASSERT(0);
-	}
-
-	ANKI_ASSERT(0);
-	return "";
-}
-
 } // end namespace anki

+ 0 - 3
AnKi/Gr/Utils/Functions.h

@@ -45,7 +45,4 @@ ShaderVariableDataType getShaderVariableTypeFromTypename();
 void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlockInfo& varBlkInfo,
 							const void* elements, U32 elementsCount, void* buffBegin, const void* buffEnd);
 
-/// Convert a ShaderVariableDataType to string.
-const CString shaderVariableDataTypeToString(ShaderVariableDataType t);
-
 } // end namespace anki

File diff suppressed because it is too large
+ 368 - 579
AnKi/Resource/MaterialResource.cpp


+ 51 - 263
AnKi/Resource/MaterialResource.h

@@ -11,7 +11,7 @@
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Math.h>
 #include <AnKi/Util/Enum.h>
-#include <AnKi/Shaders/Include/ModelTypes.h>
+#include <AnKi/Shaders/Include/MaterialTypes.h>
 
 namespace anki {
 
@@ -21,26 +21,10 @@ class XmlElement;
 /// @addtogroup resource
 /// @{
 
-/// The ID of a buildin material variable.
-enum class BuiltinMaterialVariableId : U8
-{
-	NONE = 0,
-	TRANSFORM,
-	PREVIOUS_TRANSFORM,
-	ROTATION,
-	GLOBAL_SAMPLER,
-
-	COUNT,
-	FIRST = 0,
-};
-ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BuiltinMaterialVariableId)
-
 /// The ID of builtin mutators.
 enum class BuiltinMutatorId : U8
 {
 	NONE = 0,
-	INSTANCED,
-	PASS,
 	LOD,
 	BONES,
 	VELOCITY,
@@ -73,26 +57,13 @@ public:
 	MaterialVariable& operator=(MaterialVariable&& b)
 	{
 		m_name = std::move(b.m_name);
-		m_index = b.m_index;
-		m_indexInBinary = b.m_indexInBinary;
-		m_indexInBinary2ndElement = b.m_indexInBinary2ndElement;
 		m_opaqueBinding = b.m_opaqueBinding;
-		m_constant = b.m_constant;
-		m_instanced = b.m_instanced;
-		m_numericValueIsSet = b.m_numericValueIsSet;
 		m_dataType = b.m_dataType;
-		m_builtin = b.m_builtin;
 		m_Mat4 = b.m_Mat4;
 		m_image = std::move(b.m_image);
 		return *this;
 	}
 
-	/// Get the builtin info.
-	BuiltinMaterialVariableId getBuiltin() const
-	{
-		return m_builtin;
-	}
-
 	CString getName() const
 	{
 		return m_name;
@@ -112,24 +83,9 @@ public:
 		return m_dataType == ShaderVariableDataType::SAMPLER;
 	}
 
-	Bool inBlock() const
-	{
-		return !m_constant && !isTexture() && !isSampler();
-	}
-
-	Bool isConstant() const
+	Bool isUniform() const
 	{
-		return m_constant;
-	}
-
-	Bool isInstanced() const
-	{
-		return m_instanced;
-	}
-
-	Bool isBuildin() const
-	{
-		return m_builtin != BuiltinMaterialVariableId::NONE;
+		return !isTexture() && !isSampler();
 	}
 
 	ShaderVariableDataType getDataType() const
@@ -147,17 +103,11 @@ public:
 
 protected:
 	String m_name;
-	U32 m_index = MAX_U32;
-	U32 m_indexInBinary = MAX_U32;
-	U32 m_indexInBinary2ndElement = MAX_U32; ///< To calculate the stride.
+	U32 m_offsetInLocalUniforms = MAX_U32;
 	U32 m_opaqueBinding = MAX_U32; ///< Binding for textures and samplers.
-	Bool m_constant = false;
-	Bool m_instanced = false;
-	Bool m_numericValueIsSet = false; ///< The unamed union bellow is set
 	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
-	BuiltinMaterialVariableId m_builtin = BuiltinMaterialVariableId::NONE;
 
-	/// Values for non-builtins
+	/// Values
 	/// @{
 	union
 	{
@@ -168,11 +118,6 @@ protected:
 
 	ImageResourcePtr m_image;
 	/// @}
-
-	Bool valueSetByMaterial() const
-	{
-		return m_image.isCreated() || m_numericValueIsSet;
-	}
 };
 
 // Specialize the MaterialVariable::getValue
@@ -181,7 +126,6 @@ protected:
 	inline const t_& MaterialVariable::getValue<t_>() const \
 	{ \
 		ANKI_ASSERT(m_dataType == ShaderVariableDataType::shaderType_); \
-		ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId::NONE); \
 		return var_; \
 	}
 
@@ -196,7 +140,6 @@ template<>
 inline const ImageResourcePtr& MaterialVariable::getValue() const
 {
 	ANKI_ASSERT(isTexture());
-	ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId::NONE);
 	return m_image;
 }
 
@@ -212,92 +155,34 @@ public:
 
 	MaterialVariant& operator=(const MaterialVariant&) = delete; // Non-copyable
 
-	/// Return true of the the variable is active.
-	Bool isVariableActive(const MaterialVariable& var) const
-	{
-		return m_activeVars.get(var.m_index);
-	}
-
 	const ShaderProgramPtr& getShaderProgram() const
 	{
 		return m_prog;
 	}
 
-	U32 getPerDrawUniformBlockSize() const
-	{
-		return m_perDrawUboSize;
-	}
-
-	U32 getPerInstanceUniformBlockSize(U32 instanceCount) const
-	{
-		ANKI_ASSERT(instanceCount > 0 && instanceCount <= MAX_INSTANCE_COUNT);
-		return m_perInstanceUboSizeSingleInstance * instanceCount;
-	}
-
-	ShaderVariableBlockInfo getBlockInfo(const MaterialVariable& var, U32 instanceCount) const
-	{
-		ANKI_ASSERT(isVariableActive(var));
-		ANKI_ASSERT(var.inBlock());
-		ANKI_ASSERT(m_blockInfos[var.m_index].m_offset >= 0);
-		if(var.isInstanced())
-		{
-			ANKI_ASSERT(m_blockInfos[var.m_index].m_arraySize == I16(MAX_INSTANCE_COUNT));
-			ANKI_ASSERT(instanceCount > 0 && instanceCount <= MAX_INSTANCE_COUNT);
-		}
-		else
-		{
-			ANKI_ASSERT(m_blockInfos[var.m_index].m_arraySize == 1);
-			ANKI_ASSERT(instanceCount == 1);
-		}
-
-		ShaderVariableBlockInfo out = m_blockInfos[var.m_index];
-		out.m_arraySize = I16(instanceCount);
-		return out;
-	}
-
-	template<typename T>
-	void writeShaderBlockMemory(const MaterialVariable& var, const T* elements, U32 elementCount, void* buffBegin,
-								const void* buffEnd) const
-	{
-		ANKI_ASSERT(isVariableActive(var));
-		ANKI_ASSERT(getShaderVariableTypeFromTypename<T>() == var.getDataType());
-		const ShaderVariableBlockInfo blockInfo = getBlockInfo(var, elementCount);
-		anki::writeShaderBlockMemory(var.getDataType(), blockInfo, elements, elementCount, buffBegin, buffEnd);
-	}
-
 private:
 	ShaderProgramPtr m_prog;
-	DynamicArray<ShaderVariableBlockInfo> m_blockInfos;
-	BitSet<128, U32> m_activeVars = {false};
-	U32 m_perDrawUboSize = 0;
-	U32 m_perInstanceUboSizeSingleInstance = 0;
 };
 
 /// Material resource.
 ///
 /// Material XML file format:
 /// @code
-/// <material [shadow="0 | 1"] [forwardShading="0 | 1"] shaderProgram="path">
-///		[<mutation>
-///			<mutator name="str" value="value"/>
-///		</mutation>]
-///
-///		[<inputs>
-///			<input shaderVar="name to shaderProg var" value="values"/> (1)
-///		</inputs>]
-/// </material>
-///
-/// [<rtMaterial>
-///		<rayType shaderProgram="path" type="shadows|gi|reflections|pathTracing">
+///	<material [shadows="0|1"]>
+///		<technique name="technique_name" shaderProgram="filename">
 ///			[<mutation>
 ///				<mutator name="str" value="value"/>
 ///			</mutation>]
-///		</rayType>
+///		</technique>
+///
+///		[<technique ...>
+///			...
+///		</technique>]
 ///
-/// 	[<inputs>
-/// 		<input name="name" value="value" />
-/// 	</inputs>]
-/// </rtMaterial>]
+///		[<inputs>
+///			<input name="name in AnKiMaterialUniforms struct or opaque type" value="value(s)"/> (1)
+///		</inputs>]
+///	</material>
 /// @endcode
 ///
 /// (1): Only for non-builtins.
@@ -311,29 +196,9 @@ public:
 	/// Load a material file
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
 
-	U32 getLodCount() const
-	{
-		return m_lodCount;
-	}
-
 	Bool castsShadow() const
 	{
-		return m_shadow;
-	}
-
-	Bool hasTessellation() const
-	{
-		return !!(m_prog->getStages() & (ShaderTypeBit::TESSELLATION_CONTROL | ShaderTypeBit::TESSELLATION_EVALUATION));
-	}
-
-	Bool isForwardShading() const
-	{
-		return m_forwardShading;
-	}
-
-	Bool isInstanced() const
-	{
-		return m_builtinMutators[BuiltinMutatorId::INSTANCED] != nullptr;
+		return !!(m_techniquesMask & (RenderingTechniqueBit::SHADOW | RenderingTechniqueBit::RT_SHADOW));
 	}
 
 	ConstWeakArray<MaterialVariable> getVariables() const
@@ -341,142 +206,69 @@ public:
 		return m_vars;
 	}
 
-	U32 getDescriptorSetIndex() const
-	{
-		ANKI_ASSERT(m_descriptorSetIdx != MAX_U8);
-		return m_descriptorSetIdx;
-	}
-
-	U32 getBoneTransformsStorageBlockBinding() const
-	{
-		ANKI_ASSERT(supportsSkinning());
-		return m_boneTrfsBinding;
-	}
-
-	U32 getPrevFrameBoneTransformsStorageBlockBinding() const
-	{
-		ANKI_ASSERT(supportsSkinning());
-		return m_prevFrameBoneTrfsBinding;
-	}
-
 	Bool supportsSkinning() const
 	{
-		ANKI_ASSERT((m_boneTrfsBinding == MAX_U32 && m_prevFrameBoneTrfsBinding == MAX_U32)
-					|| (m_boneTrfsBinding != MAX_U32 && m_prevFrameBoneTrfsBinding != MAX_U32));
-		return m_boneTrfsBinding != MAX_U32;
-	}
-
-	U32 getPerDrawUniformBlockBinding() const
-	{
-		ANKI_ASSERT(m_perDrawUboBinding != MAX_U32);
-		return m_perDrawUboBinding;
-	}
-
-	U32 getPerInstanceUniformBlockBinding() const
-	{
-		ANKI_ASSERT(isInstanced() && m_perInstanceUboBinding != MAX_U32);
-		return m_perInstanceUboBinding;
+		return m_supportsSkinning;
 	}
 
-	U32 getGlobalUniformsUniformBlockBinding() const
+	/// Get all GPU resources of this material. Will be used for GPU refcounting.
+	ConstWeakArray<TexturePtr> getAllTextures() const
 	{
-		ANKI_ASSERT(m_globalUniformsUboBinding != MAX_U32);
-		return m_globalUniformsUboBinding;
+		return m_textures;
 	}
 
+	/// @note It's thread-safe.
 	const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
 
-	U32 getShaderGroupHandleIndex(RayType type) const
+	/// Get a buffer with prefilled uniforms.
+	ConstWeakArray<U8> getPrefilledLocalUniforms() const
 	{
-		ANKI_ASSERT(!!(m_rayTypes & RayTypeBit(1 << type)));
-		ANKI_ASSERT(m_rtShaderGroupHandleIndices[type] < MAX_U32);
-		return m_rtShaderGroupHandleIndices[type];
-	}
-
-	RayTypeBit getSupportedRayTracingTypes() const
-	{
-		return m_rayTypes;
-	}
-
-	const MaterialGpuDescriptor& getMaterialGpuDescriptor() const
-	{
-		return m_materialGpuDescriptor;
-	}
-
-	/// Get all texture views that the MaterialGpuDescriptor returned by getMaterialGpuDescriptor(), references. Used
-	/// for lifetime management.
-	ConstWeakArray<TextureViewPtr> getAllTextureViews() const
-	{
-		return ConstWeakArray<TextureViewPtr>((m_textureViewCount) ? &m_textureViews[0] : nullptr, m_textureViewCount);
+		return ConstWeakArray<U8>(static_cast<const U8*>(m_prefilledLocalUniforms), m_localUniformsSize);
 	}
 
 private:
-	class SubMutation
+	class PartialMutation
 	{
 	public:
 		const ShaderProgramResourceMutator* m_mutator;
 		MutatorValue m_value;
 	};
 
-	ShaderProgramResourcePtr m_prog;
-
-	Array<const ShaderProgramResourceMutator*, U32(BuiltinMutatorId::COUNT)> m_builtinMutators = {};
-
-	Bool m_shadow = true;
-	Bool m_forwardShading = false;
-	U8 m_lodCount = 1;
-	U8 m_descriptorSetIdx = MAX_U8; ///< The material set.
-	U32 m_perDrawUboIdx = MAX_U32; ///< The b_perDraw UBO inside the binary.
-	U32 m_perInstanceUboIdx = MAX_U32; ///< The b_perInstance UBO inside the binary.
-	U32 m_perDrawUboBinding = MAX_U32;
-	U32 m_perInstanceUboBinding = MAX_U32;
-	U32 m_boneTrfsBinding = MAX_U32;
-	U32 m_prevFrameBoneTrfsBinding = MAX_U32;
-	U32 m_globalUniformsUboBinding = MAX_U32;
-
-	/// Matrix of variants.
-	mutable Array5d<MaterialVariant, U(Pass::COUNT), MAX_LOD_COUNT, 2, 2, 2> m_variantMatrix;
-	mutable RWMutex m_variantMatrixMtx;
-
-	DynamicArray<MaterialVariable> m_vars;
-
-	DynamicArray<SubMutation> m_nonBuiltinsMutation;
+	class Technique
+	{
+	public:
+		ShaderProgramResourcePtr m_prog;
+		U8 m_lodCount = 1;
 
-	Array<ShaderProgramResourcePtr, U(RayType::COUNT)> m_rtPrograms;
-	Array<U32, U(RayType::COUNT)> m_rtShaderGroupHandleIndices = {};
+		mutable Array3d<MaterialVariant, MAX_LOD_COUNT, 2, 2> m_variantMatrix; ///< Matrix of variants.
+		mutable RWMutex m_variantMatrixMtx;
 
-	MaterialGpuDescriptor m_materialGpuDescriptor;
+		DynamicArray<PartialMutation> m_partialMutation; ///< Only with the non-builtins.
 
-	Array<ImageResourcePtr, U(TextureChannelId::COUNT)> m_images; ///< Keep the resources alive.
-	Array<TextureViewPtr, U(TextureChannelId::COUNT)> m_textureViews; ///< Cache the GPU objects.
-	U8 m_textureViewCount = 0;
+		U32 m_presentBuildinMutators = 0;
+		U32 m_localUniformsStructIdx = 0; ///< Struct index in the program binary.
+	};
 
-	RayTypeBit m_rayTypes = RayTypeBit::NONE;
+	Array<Technique, U(RenderingTechnique::COUNT)> m_techniques;
+	RenderingTechniqueBit m_techniquesMask = RenderingTechniqueBit::NONE;
 
-	ANKI_USE_RESULT Error createVars();
+	DynamicArray<MaterialVariable> m_vars;
 
-	static ANKI_USE_RESULT Error parseVariable(CString fullVarName, Bool instanced, U32& idx, CString& name);
+	Bool m_supportsSkinning = false;
 
-	/// Parse whatever is inside the <inputs> tag.
-	ANKI_USE_RESULT Error parseInputs(XmlElement inputsEl, Bool async);
+	DynamicArray<TexturePtr> m_textures;
 
-	ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl);
-	ANKI_USE_RESULT Error findBuiltinMutators();
+	void* m_prefilledLocalUniforms = nullptr;
+	U32 m_localUniformsSize = 0;
 
-	void initVariant(const ShaderProgramResourceVariant& progVariant, MaterialVariant& variant, Bool instanced) const;
+	ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl, Technique& technique);
+	ANKI_USE_RESULT Error parseTechnique(XmlElement techniqueEl, Bool async);
+	ANKI_USE_RESULT Error parseInput(XmlElement inputEl, Bool async);
+	ANKI_USE_RESULT Error findBuiltinMutators(Technique& technique);
+	ANKI_USE_RESULT Error createVars(Technique& technique);
+	void prefillLocalUniforms();
 
-	const MaterialVariable* tryFindVariableInternal(CString name) const
-	{
-		for(const MaterialVariable& v : m_vars)
-		{
-			if(v.m_name == name)
-			{
-				return &v;
-			}
-		}
-
-		return nullptr;
-	}
+	const MaterialVariable* tryFindVariableInternal(CString name) const;
 
 	const MaterialVariable* tryFindVariable(CString name) const
 	{
@@ -487,10 +279,6 @@ private:
 	{
 		return const_cast<MaterialVariable*>(tryFindVariableInternal(name));
 	}
-
-	ANKI_USE_RESULT Error parseRtMaterial(XmlElement rootEl);
-
-	ANKI_USE_RESULT Error findGlobalUniformsUbo();
 };
 /// @}
 

+ 33 - 24
AnKi/Resource/RenderingKey.h

@@ -11,23 +11,36 @@
 namespace anki {
 
 /// The AnKi passes visible to materials.
-enum class Pass : U8
+enum class RenderingTechnique : U8
 {
-	GB, ///< GBuffer.
-	FS, ///< Forward shading.
-	SM, ///< Shadow mapping.
-	EZ, ///< Early Z.
+	GBUFFER,
+	GBUFFER_EARLY_Z,
+	SHADOW,
+	FORWARD,
+	RT_SHADOW,
 
 	COUNT,
 	FIRST = 0
 };
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RenderingTechnique)
+
+enum class RenderingTechniqueBit : U8
+{
+	NONE = 0,
+	GBUFFER = 1 << 0,
+	GBUFFER_EARLY_Z = 1 << 1,
+	SHADOW = 1 << 2,
+	FORWARD = 1 << 3,
+	RT_SHADOW = 1 << 4
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RenderingTechniqueBit)
 
 /// A key that consistst of the rendering pass and the level of detail
 class RenderingKey
 {
 public:
-	RenderingKey(Pass pass, U32 lod, U32 instanceCount, Bool skinned, Bool velocity)
-		: m_pass(pass)
+	RenderingKey(RenderingTechnique technique, U32 lod, U32 instanceCount, Bool skinned, Bool velocity)
+		: m_technique(technique)
 		, m_lod(U8(lod))
 		, m_instanceCount(U8(instanceCount))
 		, m_skinned(skinned)
@@ -38,12 +51,12 @@ public:
 	}
 
 	RenderingKey()
-		: RenderingKey(Pass::GB, 0, 1, false, false)
+		: RenderingKey(RenderingTechnique::FIRST, 0, 1, false, false)
 	{
 	}
 
 	RenderingKey(const RenderingKey& b)
-		: RenderingKey(b.m_pass, b.m_lod, b.m_instanceCount, b.m_skinned, b.m_velocity)
+		: RenderingKey(b.m_technique, b.m_lod, b.m_instanceCount, b.m_skinned, b.m_velocity)
 	{
 	}
 
@@ -55,18 +68,18 @@ public:
 
 	Bool operator==(const RenderingKey& b) const
 	{
-		return m_pass == b.m_pass && m_lod == b.m_lod && m_instanceCount == b.m_instanceCount
+		return m_technique == b.m_technique && m_lod == b.m_lod && m_instanceCount == b.m_instanceCount
 			   && m_skinned == b.m_skinned && m_velocity == b.m_velocity;
 	}
 
-	Pass getPass() const
+	RenderingTechnique getRenderingTechnique() const
 	{
-		return m_pass;
+		return m_technique;
 	}
 
-	void setPass(Pass p)
+	void setRenderingTechnique(RenderingTechnique t)
 	{
-		m_pass = p;
+		m_technique = t;
 	}
 
 	U32 getLod() const
@@ -91,7 +104,7 @@ public:
 		m_instanceCount = U8(instanceCount);
 	}
 
-	Bool isSkinned() const
+	Bool getSkinned() const
 	{
 		return m_skinned;
 	}
@@ -101,7 +114,7 @@ public:
 		m_skinned = is;
 	}
 
-	Bool hasVelocity() const
+	Bool getVelocity() const
 	{
 		return m_velocity;
 	}
@@ -112,17 +125,13 @@ public:
 	}
 
 private:
-	Pass m_pass;
+	RenderingTechnique m_technique;
 	U8 m_lod;
 	U8 m_instanceCount;
-	Bool m_skinned : 1;
-	Bool m_velocity : 1;
+	Bool m_skinned;
+	Bool m_velocity;
 };
 
-template<>
-constexpr Bool isPacked<RenderingKey>()
-{
-	return sizeof(RenderingKey) == 5;
-}
+static_assert(sizeof(RenderingKey) == sizeof(U8) * 5, "RenderingKey needs to be packed because of hashing");
 
 } // end namespace anki

+ 5 - 5
AnKi/Shaders/Common.glsl

@@ -31,8 +31,8 @@ const U32 MAX_SHARED_MEMORY = 32u * 1024u;
 #define saturateRp(x) min(x, F32(MAX_F16))
 #define mad(a_, b_, c_) fma((a_), (b_), (c_))
 
-// Passes
-#define PASS_GB 0
-#define PASS_FS 1
-#define PASS_SM 2
-#define PASS_EZ 3
+// Techniques
+#define RENDERING_TECHNIQUE_GBUFFER 0
+#define RENDERING_TECHNIQUE_GBUFFER_EZ 1
+#define RENDERING_TECHNIQUE_SHADOWS 2
+#define RENDERING_TECHNIQUE_FORWARD 3

+ 16 - 10
AnKi/Shaders/GBufferCommon.glsl

@@ -10,6 +10,11 @@
 #include <AnKi/Shaders/PackFunctions.glsl>
 #include <AnKi/Shaders/Include/ModelTypes.h>
 #include <AnKi/Shaders/Include/MaterialTypes.h>
+#include <AnKi/Shaders/Include/GpuSceneTypes.h>
+#include <AnKi/Shaders/Common.glsl>
+
+#define REALLY_USING_PARALLAX \
+	(PARALLAX == 1 && TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER && ANKI_LOD == 0 && ALPHA_TEST == 0)
 
 //
 // Vert input
@@ -18,12 +23,12 @@
 
 layout(location = VERTEX_ATTRIBUTE_ID_POSITION) in Vec3 in_position;
 
-#	if ANKI_PASS == PASS_GB
+#	if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 layout(location = VERTEX_ATTRIBUTE_ID_NORMAL) in Vec3 in_normal;
 layout(location = VERTEX_ATTRIBUTE_ID_TANGENT) in Vec4 in_tangent;
 #	endif
 
-#	if ANKI_PASS == PASS_GB || ALPHA_TEST
+#	if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER || ALPHA_TEST
 layout(location = VERTEX_ATTRIBUTE_ID_UV0) in Vec2 in_uv;
 #	endif
 
@@ -39,11 +44,11 @@ layout(location = VERTEX_ATTRIBUTE_ID_BONE_INDICES) in UVec4 in_boneIndices;
 //
 #if defined(ANKI_VERTEX_SHADER)
 
-#	if ANKI_PASS == PASS_GB || ALPHA_TEST
+#	if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER || ALPHA_TEST
 layout(location = 0) out Vec2 out_uv;
 #	endif
 
-#	if ANKI_PASS == PASS_GB
+#	if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 layout(location = 1) out ANKI_RP Vec3 out_normal;
 layout(location = 2) out ANKI_RP Vec3 out_tangent;
 layout(location = 3) out Vec3 out_bitangent;
@@ -57,7 +62,7 @@ layout(location = 6) out Vec3 out_normalTangentSpace;
 #		if ANKI_VELOCITY || ANKI_BONES
 layout(location = 7) out Vec2 out_velocity;
 #		endif
-#	endif // ANKI_PASS == PASS_GB
+#	endif // TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 
 #endif // defined(ANKI_VERTEX_SHADER)
 
@@ -66,11 +71,11 @@ layout(location = 7) out Vec2 out_velocity;
 //
 #if defined(ANKI_FRAGMENT_SHADER)
 
-#	if ANKI_PASS == PASS_GB || ALPHA_TEST
+#	if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER || ALPHA_TEST
 layout(location = 0) in Vec2 in_uv;
 #	endif
 
-#	if ANKI_PASS == PASS_GB
+#	if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 layout(location = 1) in ANKI_RP Vec3 in_normal;
 layout(location = 2) in ANKI_RP Vec3 in_tangent;
 layout(location = 3) in Vec3 in_bitangent;
@@ -84,14 +89,15 @@ layout(location = 6) in Vec3 in_normalTangentSpace;
 #		if ANKI_VELOCITY || ANKI_BONES
 layout(location = 7) in Vec2 in_velocity;
 #		endif
-#	endif // ANKI_PASS == PASS_GB
+#	endif // TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 
 #endif // defined(ANKI_FRAGMENT_SHADER)
 
 //
 // Frag out
 //
-#if defined(ANKI_FRAGMENT_SHADER) && (ANKI_PASS == PASS_GB || ANKI_PASS == PASS_EZ)
+#if defined(ANKI_FRAGMENT_SHADER) \
+	&& (TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER || TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER_EZ)
 layout(location = 0) out Vec4 out_gbuffer0;
 layout(location = 1) out Vec4 out_gbuffer1;
 layout(location = 2) out Vec4 out_gbuffer2;
@@ -103,7 +109,7 @@ layout(location = 3) out Vec2 out_gbuffer3;
 //
 
 // Write the data to RTs
-#if defined(ANKI_FRAGMENT_SHADER) && ANKI_PASS == PASS_GB
+#if defined(ANKI_FRAGMENT_SHADER) && TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 void packGBuffer(ANKI_RP Vec3 diffColor, ANKI_RP Vec3 normal, ANKI_RP Vec3 specularColor, ANKI_RP F32 roughness,
 				 ANKI_RP F32 subsurface, ANKI_RP Vec3 emission, ANKI_RP F32 metallic, Vec2 velocity)
 {

+ 123 - 140
AnKi/Shaders/GBufferGeneric.ankiprog

@@ -3,10 +3,9 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#pragma anki mutator ANKI_INSTANCED 0 1
 #pragma anki mutator ANKI_LOD 0 1 2
 #pragma anki mutator ANKI_VELOCITY 0 1
-#pragma anki mutator ANKI_PASS 0 2 3
+#pragma anki mutator TECHNIQUE 0 1 2
 #pragma anki mutator ANKI_BONES 0 1
 #pragma anki mutator DIFFUSE_TEX 0 1
 #pragma anki mutator SPECULAR_TEX 0 1
@@ -17,159 +16,143 @@
 #pragma anki mutator EMISSIVE_TEX 0 1
 #pragma anki mutator ALPHA_TEST 0 1
 
-#pragma anki rewrite_mutation ANKI_PASS 2 DIFFUSE_TEX 1 ALPHA_TEST 0 to ANKI_PASS 2 DIFFUSE_TEX 0 ALPHA_TEST 0
-#pragma anki rewrite_mutation ANKI_PASS 3 DIFFUSE_TEX 1 ALPHA_TEST 0 to ANKI_PASS 3 DIFFUSE_TEX 0 ALPHA_TEST 0
+#pragma anki rewrite_mutation TECHNIQUE 1 DIFFUSE_TEX 1 ALPHA_TEST 0 to TECHNIQUE 1 DIFFUSE_TEX 0 ALPHA_TEST 0
+#pragma anki rewrite_mutation TECHNIQUE 2 DIFFUSE_TEX 1 ALPHA_TEST 0 to TECHNIQUE 2 DIFFUSE_TEX 0 ALPHA_TEST 0
 
-#pragma anki rewrite_mutation ANKI_PASS 2 SPECULAR_TEX 1 to ANKI_PASS 2 SPECULAR_TEX 0
-#pragma anki rewrite_mutation ANKI_PASS 3 SPECULAR_TEX 1 to ANKI_PASS 3 SPECULAR_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 1 SPECULAR_TEX 1 to TECHNIQUE 1 SPECULAR_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 2 SPECULAR_TEX 1 to TECHNIQUE 2 SPECULAR_TEX 0
 
-#pragma anki rewrite_mutation ANKI_PASS 2 NORMAL_TEX 1 to ANKI_PASS 2 NORMAL_TEX 0
-#pragma anki rewrite_mutation ANKI_PASS 3 NORMAL_TEX 1 to ANKI_PASS 3 NORMAL_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 1 NORMAL_TEX 1 to TECHNIQUE 1 NORMAL_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 2 NORMAL_TEX 1 to TECHNIQUE 2 NORMAL_TEX 0
 
-#pragma anki rewrite_mutation ANKI_PASS 2 ROUGHNESS_TEX 1 to ANKI_PASS 2 ROUGHNESS_TEX 0
-#pragma anki rewrite_mutation ANKI_PASS 3 ROUGHNESS_TEX 1 to ANKI_PASS 3 ROUGHNESS_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 1 ROUGHNESS_TEX 1 to TECHNIQUE 1 ROUGHNESS_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 2 ROUGHNESS_TEX 1 to TECHNIQUE 2 ROUGHNESS_TEX 0
 
-#pragma anki rewrite_mutation ANKI_PASS 2 METAL_TEX 1 to ANKI_PASS 2 METAL_TEX 0
-#pragma anki rewrite_mutation ANKI_PASS 3 METAL_TEX 1 to ANKI_PASS 3 METAL_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 1 METAL_TEX 1 to TECHNIQUE 1 METAL_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 2 METAL_TEX 1 to TECHNIQUE 2 METAL_TEX 0
 
-#pragma anki rewrite_mutation ANKI_PASS 2 EMISSIVE_TEX 1 to ANKI_PASS 2 EMISSIVE_TEX 0
-#pragma anki rewrite_mutation ANKI_PASS 3 EMISSIVE_TEX 1 to ANKI_PASS 3 EMISSIVE_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 1 EMISSIVE_TEX 1 to TECHNIQUE 1 EMISSIVE_TEX 0
+#pragma anki rewrite_mutation TECHNIQUE 2 EMISSIVE_TEX 1 to TECHNIQUE 2 EMISSIVE_TEX 0
 
-#pragma anki rewrite_mutation ANKI_PASS 2 PARALLAX 1 to ANKI_PASS 2 PARALLAX 0
-#pragma anki rewrite_mutation ANKI_PASS 3 PARALLAX 1 to ANKI_PASS 3 PARALLAX 0
+#pragma anki rewrite_mutation TECHNIQUE 1 PARALLAX 1 to TECHNIQUE 1 PARALLAX 0
+#pragma anki rewrite_mutation TECHNIQUE 2 PARALLAX 1 to TECHNIQUE 2 PARALLAX 0
 
 #pragma anki rewrite_mutation ALPHA_TEST 1 DIFFUSE_TEX 0 to ALPHA_TEST 0 DIFFUSE_TEX 0
 
-#define REALLY_USING_PARALLAX (PARALLAX == 1 && ANKI_PASS == 0 && ANKI_LOD == 0 && ALPHA_TEST == 0)
-
 #include <AnKi/Shaders/GBufferCommon.glsl>
 
-#pragma anki reflect u_ankiGlobalSampler
-layout(set = 0, binding = 3) uniform sampler u_ankiGlobalSampler;
-#if DIFFUSE_TEX == 1 && (ANKI_PASS == PASS_GB || ALPHA_TEST)
+layout(set = MATERIAL_SET_EXTERNAL, binding = MATERIAL_BINDING_GLOBAL_SAMPLER) uniform sampler u_globalSampler;
+
+#if DIFFUSE_TEX
 #	pragma anki reflect u_diffTex
-layout(set = 0, binding = 4) uniform ANKI_RP texture2D u_diffTex;
-#	define USING_DIFF_TEX 1
+layout(set = MATERIAL_SET_EXTERNAL,
+	   binding = MATERIAL_BINDING_FIRST_NON_STANDARD + 0u) uniform ANKI_RP texture2D u_diffTex;
 #endif
-#if SPECULAR_TEX == 1 && ANKI_PASS == PASS_GB
+
+#if SPECULAR_TEX
 #	pragma anki reflect u_specTex
-layout(set = 0, binding = 5) uniform ANKI_RP texture2D u_specTex;
-#	define USING_SPECULAR_TEX 1
+layout(set = MATERIAL_SET_EXTERNAL,
+	   binding = MATERIAL_BINDING_FIRST_NON_STANDARD + 1u) uniform ANKI_RP texture2D u_specTex;
 #endif
-#if ROUGHNESS_TEX == 1 && ANKI_PASS == PASS_GB
+
+#if ROUGHNESS_TEX
 #	pragma anki reflect u_roughnessTex
-layout(set = 0, binding = 6) uniform ANKI_RP texture2D u_roughnessTex;
-#	define USING_ROUGHNESS_TEX 1
+layout(set = MATERIAL_SET_EXTERNAL,
+	   binding = MATERIAL_BINDING_FIRST_NON_STANDARD + 2u) uniform ANKI_RP texture2D u_roughnessTex;
 #endif
-#if NORMAL_TEX == 1 && ANKI_PASS == PASS_GB && ANKI_LOD < 2
+
+#if NORMAL_TEX
 #	pragma anki reflect u_normalTex
-layout(set = 0, binding = 7) uniform ANKI_RP texture2D u_normalTex;
-#	define USING_NORMAL_TEX 1
+layout(set = MATERIAL_SET_EXTERNAL,
+	   binding = MATERIAL_BINDING_FIRST_NON_STANDARD + 3u) uniform ANKI_RP texture2D u_normalTex;
 #endif
-#if METAL_TEX == 1 && ANKI_PASS == PASS_GB
+
+#if METAL_TEX
 #	pragma anki reflect u_metallicTex
-layout(set = 0, binding = 8) uniform ANKI_RP texture2D u_metallicTex;
-#	define USING_METALLIC_TEX 1
+layout(set = MATERIAL_SET_EXTERNAL,
+	   binding = MATERIAL_BINDING_FIRST_NON_STANDARD + 4u) uniform ANKI_RP texture2D u_metallicTex;
 #endif
-#if REALLY_USING_PARALLAX
+
+#if PARALLAX
 #	pragma anki reflect u_heightTex
-layout(set = 0, binding = 9) uniform ANKI_RP texture2D u_heightTex;
+layout(set = MATERIAL_SET_EXTERNAL,
+	   binding = MATERIAL_BINDING_FIRST_NON_STANDARD + 5u) uniform ANKI_RP texture2D u_heightTex;
 #endif
-#if EMISSIVE_TEX == 1 && ANKI_PASS == PASS_GB
+
+#if EMISSIVE_TEX
 #	pragma anki reflect u_emissiveTex
-layout(set = 0, binding = 10) uniform ANKI_RP texture2D u_emissiveTex;
-#	define USING_EMISSIVE_TEX 1
+layout(set = MATERIAL_SET_EXTERNAL,
+	   binding = MATERIAL_BINDING_FIRST_NON_STANDARD + 6u) uniform ANKI_RP texture2D u_emissiveTex;
 #endif
 
-#if ANKI_PASS == PASS_GB
-struct PerDraw
+#pragma anki reflect AnKiLocalUniforms
+struct AnKiLocalUniforms
 {
-#	if !defined(USING_DIFF_TEX)
+#if !DIFFUSE_TEX
 	Vec3 m_diffColor;
-#	endif
-#	if !defined(USING_ROUGHNESS_TEX)
+#endif
+#if !ROUGHNESS_TEX
 	F32 m_roughness;
-#	endif
-#	if !defined(USING_SPECULAR_TEX)
+#endif
+#if !SPECULAR_TEX
 	Vec3 m_specColor;
-#	endif
-#	if !defined(USING_METALLIC_TEX)
+#endif
+#if !METAL_TEX
 	F32 m_metallic;
-#	endif
-#	if !defined(USING_EMISSIVE_TEX)
+#endif
+#if !EMISSIVE_TEX
 	Vec3 m_emission;
-#	endif
-#	if REALLY_USING_PARALLAX
+#endif
+#if PARALLAX
 	F32 m_heightmapScale;
-#	endif
-#	if ANKI_PASS == PASS_GB
-	F32 m_subsurface;
-#	endif
-};
 #endif
 
-struct PerInstance
-{
-	Mat3x4 m_ankiTransform;
-#if ANKI_PASS == PASS_GB
-	Mat3 m_ankiRotation;
-#endif
-#if ANKI_PASS == PASS_GB && ANKI_VELOCITY == 1
-	Mat3x4 m_ankiPreviousTransform;
-#endif
+	F32 m_subsurface;
 };
 
-#if ANKI_PASS == PASS_GB
-#	pragma anki reflect b_ankiPerDraw
-layout(set = 0, binding = 0, row_major, scalar) uniform b_ankiPerDraw
+layout(set = MATERIAL_SET_EXTERNAL, binding = MATERIAL_BINDING_LOCAL_UNIFORMS, row_major,
+	   scalar) uniform b_localUniforms
 {
-	PerDraw u_ankiPerDraw;
+	AnKiLocalUniforms u_localUniforms;
 };
-#endif
 
-#pragma anki reflect b_ankiPerInstance
-layout(set = 0, binding = 1, row_major, scalar) uniform b_ankiPerInstance
+layout(set = MATERIAL_SET_EXTERNAL, binding = MATERIAL_BINDING_RENDERABLE_GPU_VIEW, row_major,
+	   scalar) uniform b_renderableGpuView
 {
-	PerInstance u_ankiPerInstance[MAX_INSTANCE_COUNT];
+	RenderableGpuView u_renderableGpuViews[MAX_INSTANCE_COUNT];
 };
 
-#pragma anki reflect b_ankiGlobalUniforms
-layout(set = 0, binding = 2, row_major, scalar) uniform b_ankiGlobalUniforms
+layout(set = MATERIAL_SET_EXTERNAL, binding = MATERIAL_BINDING_GLOBAL_UNIFORMS, row_major,
+	   scalar) uniform b_globalUniforms
 {
-	MaterialGlobalUniforms u_ankiGlobals;
+	MaterialGlobalUniforms u_globalUniforms;
 };
 
 #if ANKI_BONES
-#	pragma anki reflect b_ankiBoneTransforms
-layout(set = 0, binding = 11, row_major, std140) readonly buffer b_ankiBoneTransforms
+layout(set = MATERIAL_SET_EXTERNAL, binding = MATERIAL_BINDING_BONE_TRANSFORMS, row_major,
+	   std140) readonly buffer b_boneTransforms
 {
-	Mat4 u_ankiBoneTransforms[];
+	Mat4 u_boneTransforms[];
 };
 
-#	pragma anki reflect b_ankiPrevFrameBoneTransforms
-layout(set = 0, binding = 12, row_major, std140) readonly buffer b_ankiPrevFrameBoneTransforms
+layout(set = MATERIAL_SET_EXTERNAL, binding = MATERIAL_BINDING_PREVIOUS_BONE_TRANSFORMS, row_major,
+	   std140) readonly buffer b_prevFrameBoneTransforms
 {
-	Mat4 u_ankiPrevFrameBoneTransforms[];
+	Mat4 u_prevFrameBoneTransforms[];
 };
 #endif
 
-#if !ANKI_INSTANCED
-#	define INSTANCE_ID 0
-#else
-#	define INSTANCE_ID gl_InstanceIndex
-#endif
-
 #pragma anki start vert
 
 // Globals (always in local space)
 Vec3 g_position = in_position;
-#if ANKI_PASS == PASS_GB
+#if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 Vec3 g_prevPosition = in_position;
 ANKI_RP Vec3 g_normal = in_normal;
 ANKI_RP Vec4 g_tangent = in_tangent;
 #endif
 
-#if ANKI_PASS == PASS_GB || ALPHA_TEST
+#if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER || ALPHA_TEST
 Vec2 g_uv = in_uv;
 #endif
 
@@ -177,31 +160,32 @@ Vec2 g_uv = in_uv;
 #if ANKI_BONES
 void skinning()
 {
-	ANKI_RP Mat4 skinMat = u_ankiBoneTransforms[in_boneIndices[0]] * in_boneWeights[0];
-	ANKI_RP Mat4 prevSkinMat = u_ankiPrevFrameBoneTransforms[in_boneIndices[0]] * in_boneWeights[0];
+	ANKI_RP Mat4 skinMat = u_boneTransforms[in_boneIndices[0]] * in_boneWeights[0];
+	ANKI_RP Mat4 prevSkinMat = u_prevFrameBoneTransforms[in_boneIndices[0]] * in_boneWeights[0];
 	ANKI_UNROLL for(U32 i = 1u; i < 4u; ++i)
 	{
-		skinMat += u_ankiBoneTransforms[in_boneIndices[i]] * in_boneWeights[i];
-		prevSkinMat += u_ankiPrevFrameBoneTransforms[in_boneIndices[i]] * in_boneWeights[i];
+		skinMat += u_boneTransforms[in_boneIndices[i]] * in_boneWeights[i];
+		prevSkinMat += u_prevFrameBoneTransforms[in_boneIndices[i]] * in_boneWeights[i];
 	}
 
-#	if ANKI_PASS == PASS_GB
+#	if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 	g_prevPosition = (prevSkinMat * Vec4(g_position, 1.0)).xyz;
 	g_tangent.xyz = (skinMat * Vec4(g_tangent.xyz, 0.0)).xyz;
 	g_normal = (skinMat * Vec4(g_normal, 0.0)).xyz;
 #	endif
+
 	g_position = (skinMat * Vec4(g_position, 1.0)).xyz;
 }
 #endif
 
 // Common store function
-#if ANKI_PASS == PASS_GB
+#if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 void positionUvNormalTangent()
 {
-	gl_Position = u_ankiGlobals.m_viewProjectionMatrix
-				  * Vec4(u_ankiPerInstance[INSTANCE_ID].m_ankiTransform * Vec4(g_position, 1.0), 1.0);
-	out_normal = u_ankiPerInstance[INSTANCE_ID].m_ankiRotation * g_normal;
-	out_tangent = u_ankiPerInstance[INSTANCE_ID].m_ankiRotation * g_tangent.xyz;
+	gl_Position = u_globalUniforms.m_viewProjectionMatrix
+				  * Vec4(u_renderableGpuViews[gl_InstanceIndex].m_transform * Vec4(g_position, 1.0), 1.0);
+	out_normal = u_renderableGpuViews[gl_InstanceIndex].m_rotation * g_normal;
+	out_tangent = u_renderableGpuViews[gl_InstanceIndex].m_rotation * g_tangent.xyz;
 	out_bitangent = cross(out_normal, out_tangent) * g_tangent.w;
 	out_uv = g_uv;
 }
@@ -215,12 +199,12 @@ void parallax()
 	const Vec3 t = in_tangent.xyz;
 	const Vec3 b = cross(n, t) * in_tangent.w;
 
-	const Mat3 invTbn =
-		transpose(u_ankiGlobals.m_viewRotationMatrix * u_ankiPerInstance[INSTANCE_ID].m_ankiRotation * Mat3(t, b, n));
+	const Mat3 invTbn = transpose(u_globalUniforms.m_viewRotationMatrix
+								  * u_renderableGpuViews[gl_InstanceIndex].m_rotation * Mat3(t, b, n));
 
-	const Vec3 viewPos =
-		(u_ankiGlobals.m_viewMatrix * Vec4(u_ankiPerInstance[INSTANCE_ID].m_ankiTransform * Vec4(g_position, 1.0), 1.0))
-			.xyz;
+	const Vec3 viewPos = (u_globalUniforms.m_viewMatrix
+						  * Vec4(u_renderableGpuViews[gl_InstanceIndex].m_transform * Vec4(g_position, 1.0), 1.0))
+							 .xyz;
 	out_distFromTheCamera = viewPos.z;
 
 	out_eyeTangentSpace = invTbn * viewPos;
@@ -228,18 +212,18 @@ void parallax()
 }
 #endif
 
-#if(ANKI_VELOCITY || ANKI_BONES) && ANKI_PASS == PASS_GB
+#if(ANKI_VELOCITY || ANKI_BONES) && TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 void velocity()
 {
 	const Vec3 prevLocalPos = g_prevPosition;
 
 #	if ANKI_VELOCITY
-	const Mat3x4 trf = u_ankiPerInstance[INSTANCE_ID].m_ankiPreviousTransform;
+	const Mat3x4 trf = u_renderableGpuViews[gl_InstanceIndex].m_previousTransform;
 #	else
-	const Mat3x4 trf = u_ankiPerInstance[INSTANCE_ID].m_ankiTransform;
+	const Mat3x4 trf = u_renderableGpuViews[gl_InstanceIndex].m_transform;
 #	endif
 
-	const Vec4 v4 = u_ankiGlobals.m_viewProjectionMatrix * Vec4(trf * Vec4(prevLocalPos, 1.0), 1.0);
+	const Vec4 v4 = u_globalUniforms.m_viewProjectionMatrix * Vec4(trf * Vec4(prevLocalPos, 1.0), 1.0);
 
 	const Vec2 prevNdc = v4.xy / v4.w;
 
@@ -256,7 +240,7 @@ void main()
 	skinning();
 #endif
 
-#if ANKI_PASS == PASS_GB
+#if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 	positionUvNormalTangent();
 
 #	if REALLY_USING_PARALLAX
@@ -267,8 +251,8 @@ void main()
 	velocity();
 #	endif
 #else
-	gl_Position = u_ankiGlobals.m_viewProjectionMatrix
-				  * Vec4(u_ankiPerInstance[INSTANCE_ID].m_ankiTransform * Vec4(g_position, 1.0), 1.0);
+	gl_Position = u_globalUniforms.m_viewProjectionMatrix
+				  * Vec4(u_renderableGpuViews[gl_InstanceIndex].m_transform * Vec4(g_position, 1.0), 1.0);
 
 #	if ALPHA_TEST
 	out_uv = g_uv;
@@ -350,7 +334,7 @@ Vec2 computeTextureCoordParallax(texture2D heightMap, sampler sampl, Vec2 uv, F3
 #endif
 
 // Do normal mapping
-#if ANKI_PASS == PASS_GB
+#if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 ANKI_RP Vec3 readNormalFromTexture(ANKI_RP texture2D map, sampler sampl, highp Vec2 texCoords)
 {
 	// First read the texture
@@ -376,54 +360,53 @@ void doAlphaText(F32 alpha)
 
 void main()
 {
-#if ANKI_PASS == PASS_GB
+#if TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 #	if REALLY_USING_PARALLAX
-	const Vec2 uv =
-		computeTextureCoordParallax(u_heightTex, u_ankiGlobalSampler, in_uv, u_ankiPerDraw.m_heightmapScale);
+	const Vec2 uv = computeTextureCoordParallax(u_heightTex, u_globalSampler, in_uv, u_localUniforms.m_heightmapScale);
 #	else
 	const Vec2 uv = in_uv;
 #	endif
 
-#	if defined(USING_DIFF_TEX)
+#	if DIFFUSE_TEX
 #		if ALPHA_TEST
-	const ANKI_RP Vec4 diffColorA = texture(u_diffTex, u_ankiGlobalSampler, uv);
+	const ANKI_RP Vec4 diffColorA = texture(u_diffTex, u_globalSampler, uv);
 	doAlphaText(diffColorA.a);
 	const ANKI_RP Vec3 diffColor = diffColorA.rgb;
 #		else
-	const ANKI_RP Vec3 diffColor = texture(u_diffTex, u_ankiGlobalSampler, uv).rgb;
+	const ANKI_RP Vec3 diffColor = texture(u_diffTex, u_globalSampler, uv).rgb;
 #		endif
 #	else
-	const ANKI_RP Vec3 diffColor = u_ankiPerDraw.m_diffColor;
+	const ANKI_RP Vec3 diffColor = u_localUniforms.m_diffColor;
 #	endif
 
-#	if defined(USING_SPECULAR_TEX)
-	const ANKI_RP Vec3 specColor = texture(u_specTex, u_ankiGlobalSampler, uv).rgb;
+#	if SPECULAR_TEX
+	const ANKI_RP Vec3 specColor = texture(u_specTex, u_globalSampler, uv).rgb;
 #	else
-	const ANKI_RP Vec3 specColor = u_ankiPerDraw.m_specColor;
+	const ANKI_RP Vec3 specColor = u_localUniforms.m_specColor;
 #	endif
 
-#	if defined(USING_ROUGHNESS_TEX)
-	const ANKI_RP F32 roughness = texture(u_roughnessTex, u_ankiGlobalSampler, uv).g;
+#	if ROUGHNESS_TEX
+	const ANKI_RP F32 roughness = texture(u_roughnessTex, u_globalSampler, uv).g;
 #	else
-	const ANKI_RP F32 roughness = u_ankiPerDraw.m_roughness;
+	const ANKI_RP F32 roughness = u_localUniforms.m_roughness;
 #	endif
 
-#	if defined(USING_METALLIC_TEX)
-	const ANKI_RP F32 metallic = texture(u_metallicTex, u_ankiGlobalSampler, uv).b;
+#	if METAL_TEX
+	const ANKI_RP F32 metallic = texture(u_metallicTex, u_globalSampler, uv).b;
 #	else
-	const ANKI_RP F32 metallic = u_ankiPerDraw.m_metallic;
+	const ANKI_RP F32 metallic = u_localUniforms.m_metallic;
 #	endif
 
-#	if defined(USING_NORMAL_TEX)
-	const ANKI_RP Vec3 normal = readNormalFromTexture(u_normalTex, u_ankiGlobalSampler, uv);
+#	if NORMAL_TEX
+	const ANKI_RP Vec3 normal = readNormalFromTexture(u_normalTex, u_globalSampler, uv);
 #	else
 	const ANKI_RP Vec3 normal = normalize(in_normal);
 #	endif
 
-#	if defined(USING_EMISSIVE_TEX)
-	const ANKI_RP Vec3 emission = texture(u_emissiveTex, u_ankiGlobalSampler, uv).rgb;
+#	if EMISSIVE_TEX
+	const ANKI_RP Vec3 emission = texture(u_emissiveTex, u_globalSampler, uv).rgb;
 #	else
-	const ANKI_RP Vec3 emission = u_ankiPerDraw.m_emission;
+	const ANKI_RP Vec3 emission = u_localUniforms.m_emission;
 #	endif
 
 #	if ANKI_VELOCITY || ANKI_BONES
@@ -432,16 +415,16 @@ void main()
 	const Vec2 velocity = Vec2(1.0);
 #	endif
 
-	packGBuffer(diffColor, normal, specColor, roughness, u_ankiPerDraw.m_subsurface, emission, metallic, velocity);
-#elif ANKI_PASS == PASS_EZ
+	packGBuffer(diffColor, normal, specColor, roughness, u_localUniforms.m_subsurface, emission, metallic, velocity);
+#elif TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER_EZ
 	out_gbuffer0 = Vec4(0.0);
 	out_gbuffer1 = Vec4(0.0);
 	out_gbuffer2 = Vec4(0.0);
 	out_gbuffer3 = Vec2(0.0);
 #endif
 
-#if ANKI_PASS != PASS_GB && ALPHA_TEST
-	doAlphaText(texture(u_diffTex, u_ankiGlobalSampler, in_uv).a);
+#if TECHNIQUE != RENDERING_TECHNIQUE_GBUFFER && ALPHA_TEST
+	doAlphaText(texture(u_diffTex, u_globalSampler, in_uv).a);
 #endif
 }
 

+ 0 - 1
AnKi/Shaders/GBufferGpuParticles.ankiprog

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 
 #pragma anki mutator ANKI_PASS 0 2 3
-#pragma anki mutator ANKI_VELOCITY 0 1
 
 #include <AnKi/Shaders/Include/ParticleTypes.h>
 #include <AnKi/Shaders/Include/MaterialTypes.h>

+ 8 - 0
AnKi/Shaders/Include/Common.h

@@ -32,6 +32,10 @@ inline F32 dot(const T& a, const T& b)
 }
 
 using Address = U64;
+
+using ScalarVec4 = Array<F32, 4>;
+using ScalarMat3x4 = Array<F32, 12>;
+using ScalarMat4 = Array<F32, 16>;
 ANKI_END_NAMESPACE
 
 #	define ANKI_CPP_CODE(x) x
@@ -60,6 +64,10 @@ ANKI_END_NAMESPACE
 #	define ANKI_SHADER_STATIC_ASSERT(cond_)
 
 #	define ANKI_CPP_CODE(x)
+
+#	define ScalarVec4 Vec4
+#	define ScalarMat3x4 Mat3x4
+#	define ScalarMat4 Mat4
 #endif
 
 //

+ 24 - 0
AnKi/Shaders/Include/GpuSceneTypes.h

@@ -0,0 +1,24 @@
+// 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/Shaders/Include/Common.h>
+
+ANKI_BEGIN_NAMESPACE
+
+struct RenderableGpuView
+{
+	ScalarMat3x4 m_transform;
+	ScalarMat3x4 m_previousTransform;
+	Mat3 m_rotation;
+};
+
+struct SkinGpuView
+{
+	U32 m_tmp;
+};
+
+ANKI_END_NAMESPACE

+ 31 - 9
AnKi/Shaders/Include/MaterialTypes.h

@@ -9,18 +9,40 @@
 
 ANKI_BEGIN_NAMESPACE
 
-/// Per flare information
+/// Common data for all materials.
 struct MaterialGlobalUniforms
 {
-#if __cplusplus
-	Array<F32, 16> m_viewProjectionMatrix;
-	Array<F32, 12> m_viewMatrix;
-#else
-	Mat4 m_viewProjectionMatrix;
-	Mat3x4 m_viewMatrix;
-#endif
-	Mat3 m_viewRotationMatrix; ///< Essentially the rotation part of the view matrix
+	ScalarMat4 m_viewProjectionMatrix;
+	ScalarMat3x4 m_viewMatrix;
+	Mat3 m_viewRotationMatrix; ///< Essentially the rotation part of the view matrix.
 	Mat3 m_cameraRotationMatrix;
 };
 
+// Begin standard bindings
+const U32 MATERIAL_BINDING_GLOBAL_SAMPLER = 0u;
+const U32 MATERIAL_BINDING_RENDERABLE_GPU_VIEW = 1u;
+const U32 MATERIAL_BINDING_LOCAL_UNIFORMS = 2u;
+const U32 MATERIAL_BINDING_GLOBAL_UNIFORMS = 3u;
+const U32 MATERIAL_BINDING_BONE_TRANSFORMS = 4u;
+const U32 MATERIAL_BINDING_PREVIOUS_BONE_TRANSFORMS = 5u;
+// End standard bindings
+
+const U32 MATERIAL_BINDING_STANDARD_BINDING_COUNT = 6u;
+const U32 MATERIAL_BINDING_FIRST_NON_STANDARD = MATERIAL_BINDING_STANDARD_BINDING_COUNT;
+
+const U32 MATERIAL_SET_INTERNAL = 0u;
+const U32 MATERIAL_SET_EXTERNAL = 1u;
+
+#define ANKI_MATERIAL_UNIFORM_BUFFER(bindingNum, structName, varName) \
+	layout(set = MATERIAL_SET_EXTERNAL, binding = bindingNum, row_major, scalar) uniform b_##varName \
+	{ \
+		structName varName; \
+	};
+
+#define ANKI_MATERIAL_STORAGE_BUFFER(bindingNum, structName, varName) \
+	layout(set = MATERIAL_SET_EXTERNAL, binding = bindingNum, row_major, scalar) buffer b_##varName \
+	{ \
+		structName varName; \
+	};
+
 ANKI_END_NAMESPACE

+ 1 - 1
CMakeLists.txt

@@ -398,7 +398,7 @@ if(NOT MSVC)
 		"-Wconversion -Wno-sign-conversion -Wno-keyword-macro -Wno-string-conversion -Wno-class-memaccess "
 		"-Wunused-variable")
 
-	set(CMAKE_CXX_STANDARD 14)
+	set(CMAKE_CXX_STANDARD 17)
 else()
 	#add_definitions("/wd4996 /wd4244 /wd4262 /wd4267 /wd26495 /wd26439")
 	add_compile_definitions("_CRT_SECURE_NO_WARNINGS=1") # Disable some string function warnings

Some files were not shown because too many files changed in this diff