Browse Source

Work on the new material

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
2ba90f1841

+ 225 - 0
src/anki/resource/MaterialResource2.h

@@ -7,6 +7,8 @@
 
 #include <anki/resource/ResourceObject.h>
 #include <anki/resource/RenderingKey.h>
+#include <anki/resource/ShaderProgramResource2.h>
+#include <anki/Math.h>
 
 namespace anki
 {
@@ -31,6 +33,229 @@ enum class BuiltinMaterialVariableId2 : U8
 	GLOBAL_SAMPLER,
 	COUNT
 };
+
+/// Holds the shader variables. It's a container for shader program variables that share the same name.
+class MaterialVariable2 : public NonCopyable
+{
+	friend class MaterialVariant2;
+
+public:
+	/// Get the builtin info.
+	BuiltinMaterialVariableId2 getBuiltin() const
+	{
+		return m_builtin;
+	}
+
+	CString getName() const
+	{
+		return m_name;
+	}
+
+	template<typename T>
+	const T& getValue() const;
+
+	Bool isTexture() const
+	{
+		return m_dataType >= ShaderVariableDataType::TEXTURE_FIRST
+			   && m_dataType <= ShaderVariableDataType::TEXTURE_LAST;
+	}
+
+	Bool isSampler() const
+	{
+		return m_dataType == ShaderVariableDataType::SAMPLER;
+	}
+
+	Bool inBlock() const
+	{
+		return !m_constant && !isTexture() && !isSampler();
+	}
+
+protected:
+	String m_name;
+	U32 m_index = MAX_U32;
+	Bool m_constant = false;
+	Bool m_instanced = false;
+	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
+	BuiltinMaterialVariableId2 m_builtin = BuiltinMaterialVariableId2::NONE;
+
+	union
+	{
+		I32 m_int;
+		IVec2 m_ivec2;
+		IVec3 m_ivec3;
+		IVec4 m_ivec4;
+		U32 m_uint;
+		UVec2 m_uvec2;
+		UVec3 m_uvec3;
+		UVec4 m_uvec4;
+		F32 m_float;
+		Vec2 m_vec2;
+		Vec3 m_vec3;
+		Vec4 m_vec4;
+		Mat3 m_mat3;
+		Mat4 m_mat4;
+	};
+
+	TextureResourcePtr m_tex;
+};
+
+// Specialize the MaterialVariable::getValue
+#define ANKI_SPECIALIZE_GET_VALUE(t_, var_, shaderType_) \
+	template<> \
+	inline const t_& MaterialVariable2::getValue<t_>() const \
+	{ \
+		ANKI_ASSERT(m_dataType == ShaderVariableDataType::shaderType_); \
+		ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId2::NONE); \
+		return var_; \
+	}
+
+ANKI_SPECIALIZE_GET_VALUE(I32, m_int, INT)
+ANKI_SPECIALIZE_GET_VALUE(IVec2, m_ivec2, IVEC2)
+ANKI_SPECIALIZE_GET_VALUE(IVec3, m_ivec3, IVEC3)
+ANKI_SPECIALIZE_GET_VALUE(IVec4, m_ivec4, IVEC4)
+ANKI_SPECIALIZE_GET_VALUE(U32, m_uint, UINT)
+ANKI_SPECIALIZE_GET_VALUE(UVec2, m_uvec2, UVEC2)
+ANKI_SPECIALIZE_GET_VALUE(UVec3, m_uvec3, UVEC3)
+ANKI_SPECIALIZE_GET_VALUE(UVec4, m_uvec4, UVEC4)
+ANKI_SPECIALIZE_GET_VALUE(F32, m_float, FLOAT)
+ANKI_SPECIALIZE_GET_VALUE(Vec2, m_vec2, VEC2)
+ANKI_SPECIALIZE_GET_VALUE(Vec3, m_vec3, VEC3)
+ANKI_SPECIALIZE_GET_VALUE(Vec4, m_vec4, VEC4)
+ANKI_SPECIALIZE_GET_VALUE(Mat3, m_mat3, MAT3)
+ANKI_SPECIALIZE_GET_VALUE(Mat4, m_mat4, MAT4)
+
+template<>
+inline const TextureResourcePtr& MaterialVariable2::getValue() const
+{
+	ANKI_ASSERT(isTexture());
+	ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId2::NONE);
+	return m_tex;
+}
+
+#undef ANKI_SPECIALIZE_GET_VALUE
+
+/// Material variant.
+class MaterialVariant2 : public NonCopyable
+{
+public:
+	/// Return true of the the variable is active.
+	Bool isVariableActive(const MaterialVariable2& var) const
+	{
+		return m_activeVars.get(var.m_index);
+	}
+
+	const ShaderProgramPtr& getShaderProgram() const
+	{
+		return m_prog;
+	}
+
+	U32 getUniformBlockSize() const
+	{
+		return m_uniBlockSize;
+	}
+
+	U32 getOpaqueBinding(const MaterialVariable2& var) const
+	{
+		ANKI_ASSERT(m_opaqueBindings[var.m_index] >= 0);
+		return U32(m_opaqueBindings[var.m_index]);
+	}
+
+	const ShaderVariableBlockInfo& getBlockInfo(const MaterialVariable2& var) const
+	{
+		ANKI_ASSERT(var.inBlock());
+		ANKI_ASSERT(m_blockInfos[var.m_index].m_offset >= 0);
+		return m_blockInfos[var.m_index];
+	}
+
+private:
+	ShaderProgramPtr m_prog;
+	DynamicArray<ShaderVariableBlockInfo> m_blockInfos;
+	DynamicArray<I16> m_opaqueBindings;
+	BitSet<128, U32> m_activeVars = {false};
+	U32 m_uniBlockSize = 0;
+};
+
+/// Material resource.
+///
+/// Material XML file format:
+/// @code
+/// <material
+///		[shadow="0 | 1"]
+///		[forwardShading="0 | 1"]
+///		<shaderProgram="path"/>
+///
+///		[<mutators>
+///			<mutator name="str" value="value"/>
+///		</mutators>]
+///
+///		[<inputs>
+///			<input shaderInput="name to shaderProg input" value="values"/> (1)
+///		</inputs>]
+/// </material>
+/// @endcode
+/// (1): Only for non-builtins.
+class MaterialResource2 : public ResourceObject
+{
+public:
+	MaterialResource2(ResourceManager* manager);
+
+	~MaterialResource2();
+
+	/// 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;
+	}
+
+	Bool isForwardShading() const
+	{
+		return m_forwardShading;
+	}
+
+	Bool isInstanced() const
+	{
+		return m_instanced;
+	}
+
+	const MaterialVariant2& getOrCreateVariant(const RenderingKey& key) const;
+
+	ConstWeakArray<MaterialVariable2> getVariables() const
+	{
+		return m_vars;
+	}
+
+	U32 getDescriptorSetIndex() const
+	{
+		return m_descriptorSetIdx;
+	}
+
+private:
+	ShaderProgramResource2Ptr m_prog;
+
+	Bool m_shadow = true;
+	Bool m_forwardShading = false;
+	Bool m_instanced = false;
+	U8 m_lodCount = 1;
+	U8 m_descriptorSetIdx = 0; ///< Cache the value from the m_prog;
+
+	/// Matrix of variants.
+	mutable Array5d<MaterialVariant2, U(Pass::COUNT), MAX_LOD_COUNT, MAX_INSTANCE_GROUPS, 2, 2> m_variantMatrix;
+	mutable RWMutex m_variantMatrixMtx;
+
+	DynamicArray<MaterialVariable2> m_vars;
+};
 /// @}
 
 } // end namespace anki

+ 57 - 208
src/anki/resource/ShaderProgramResource2.cpp

@@ -30,6 +30,7 @@ ShaderProgramResource2::ShaderProgramResource2(ResourceManager* manager)
 ShaderProgramResource2::~ShaderProgramResource2()
 {
 	m_mutators.destroy(getAllocator());
+	m_consts.destroy(getAllocator());
 }
 
 Error ShaderProgramResource2::load(const ResourceFilename& filename, Bool async)
@@ -55,187 +56,88 @@ Error ShaderProgramResource2::load(const ResourceFilename& filename, Bool async)
 		}
 	}
 
-	// Create the inputs
+	// Create the constants
+	for(const ShaderProgramBinaryConstant& c : binary.m_constants)
 	{
-		U32 descriptorSet = MAX_U32;
-		U32 maxDescriptorSet = 0;
-		for(const ShaderProgramBinaryBlock& block : binary.m_uniformBlocks)
+		U32 componentIdx;
+		U32 componentCount;
+		CString name;
+		ANKI_CHECK(parseConst(c.m_name.getBegin(), componentIdx, componentCount, name));
+
+		// Do the mapping
+		ConstMapping mapping;
+		mapping.m_component = componentIdx;
+		if(componentIdx > 0)
 		{
-			maxDescriptorSet = max(maxDescriptorSet, block.m_set);
-
-			if(block.m_name.getBegin() != CString("b_ankiMaterial"))
-			{
-				continue;
-			}
-
-			m_materialUboIdx = U8(&block - &binary.m_uniformBlocks[0]);
-			descriptorSet = block.m_set;
-
-			for(const ShaderProgramBinaryVariable& var : block.m_variables)
-			{
-				Bool instanced;
-				U32 idx;
-				CString name;
-				ANKI_CHECK(parseVariable(var.m_name.getBegin(), instanced, idx, name));
-
-				if(idx > 0)
-				{
-					continue;
-				}
-
-				ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
-				in.m_name.create(getAllocator(), name);
-				in.m_index = m_inputVars.getSize() - 1;
-				in.m_constant = false;
-				in.m_dataType = var.m_type;
-				in.m_instanced = instanced;
-			}
+			const ShaderProgramResourceConstant2* other = tryFindConstant(name);
+			ANKI_ASSERT(other);
+			mapping.m_constsIdx = U32(other - m_consts.getBegin());
 		}
-
-		// Continue with the opaque if it's a material shader program
-		if(descriptorSet != MAX_U32)
+		else
 		{
-			for(const ShaderProgramBinaryOpaque& o : binary.m_opaques)
-			{
-				maxDescriptorSet = max(maxDescriptorSet, o.m_set);
-
-				if(o.m_set != descriptorSet)
-				{
-					continue;
-				}
-
-				ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
-				in.m_name.create(getAllocator(), o.m_name.getBegin());
-				in.m_index = m_inputVars.getSize() - 1;
-				in.m_constant = false;
-				in.m_dataType = o.m_type;
-				in.m_instanced = false;
-			}
+			mapping.m_constsIdx = m_consts.getSize();
 		}
 
-		if(descriptorSet != MAX_U32 && descriptorSet != maxDescriptorSet)
+		m_constBinaryMapping.emplaceBack(getAllocator(), mapping);
+
+		// Skip if const is there
+		if(componentIdx > 0)
 		{
-			ANKI_RESOURCE_LOGE("All bindings of a material shader should be in the highest descriptor set");
-			return Error::USER_DATA;
+			continue;
 		}
 
-		m_descriptorSet = U8(descriptorSet);
+		// Create new one
+		ShaderProgramResourceConstant2& in = *m_consts.emplaceBack(getAllocator());
+		in.m_name.create(getAllocator(), name);
+		in.m_index = m_consts.getSize() - 1;
 
-		for(const ShaderProgramBinaryConstant& c : binary.m_constants)
+		if(componentCount == 1)
 		{
-			U32 componentIdx;
-			U32 componentCount;
-			CString name;
-			ANKI_CHECK(parseConst(c.m_name.getBegin(), componentIdx, componentCount, name));
-
-			if(componentIdx > 0)
+			in.m_dataType = c.m_type;
+		}
+		else if(componentCount == 2)
+		{
+			if(c.m_type == ShaderVariableDataType::INT)
 			{
-				continue;
+				in.m_dataType = ShaderVariableDataType::IVEC2;
 			}
-
-			ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
-			in.m_name.create(getAllocator(), name);
-			in.m_index = m_inputVars.getSize() - 1;
-			in.m_constant = true;
-
-			if(componentCount == 1)
+			else
 			{
-				in.m_dataType = c.m_type;
+				ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
+				in.m_dataType = ShaderVariableDataType::VEC2;
 			}
-			else if(componentCount == 2)
+		}
+		else if(componentCount == 3)
+		{
+			if(c.m_type == ShaderVariableDataType::INT)
 			{
-				if(c.m_type == ShaderVariableDataType::INT)
-				{
-					in.m_dataType = ShaderVariableDataType::IVEC2;
-				}
-				else
-				{
-					ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
-					in.m_dataType = ShaderVariableDataType::VEC2;
-				}
+				in.m_dataType = ShaderVariableDataType::IVEC3;
 			}
-			else if(componentCount == 3)
+			else
 			{
-				if(c.m_type == ShaderVariableDataType::INT)
-				{
-					in.m_dataType = ShaderVariableDataType::IVEC3;
-				}
-				else
-				{
-					ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
-					in.m_dataType = ShaderVariableDataType::VEC3;
-				}
+				ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
+				in.m_dataType = ShaderVariableDataType::VEC3;
 			}
-			else if(componentCount == 4)
+		}
+		else if(componentCount == 4)
+		{
+			if(c.m_type == ShaderVariableDataType::INT)
 			{
-				if(c.m_type == ShaderVariableDataType::INT)
-				{
-					in.m_dataType = ShaderVariableDataType::IVEC4;
-				}
-				else
-				{
-					ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
-					in.m_dataType = ShaderVariableDataType::VEC4;
-				}
+				in.m_dataType = ShaderVariableDataType::IVEC4;
 			}
 			else
 			{
-				ANKI_ASSERT(0);
+				ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
+				in.m_dataType = ShaderVariableDataType::VEC4;
 			}
 		}
-	} // End creating the inputs
-
-	m_shaderStages = binary.m_presentShaderTypes;
-
-	return Error::NONE;
-}
-
-Error ShaderProgramResource2::parseVariable(CString fullVarName, Bool& instanced, U32& idx, CString& name)
-{
-	if(fullVarName.find("u_ankiPerDraw") == CString::NPOS)
-	{
-		instanced = false;
-	}
-	else if(fullVarName.find("u_ankiPerInstance") == CString::NPOS)
-	{
-		instanced = true;
-	}
-	else
-	{
-		ANKI_RESOURCE_LOGE("Wrong variable name: %s", fullVarName.cstr());
-		return Error::USER_DATA;
-	}
-
-	if(instanced)
-	{
-		const PtrSize leftBracket = fullVarName.find("[");
-		const PtrSize rightBracket = fullVarName.find("]");
-
-		if(leftBracket == CString::NPOS || rightBracket == CString::NPOS || rightBracket <= leftBracket)
-		{
-			ANKI_RESOURCE_LOGE("Wrong variable name: %s", fullVarName.cstr());
-			return Error::USER_DATA;
-		}
-
-		Array<char, 8> idxStr;
-		ANKI_ASSERT(rightBracket - leftBracket < idxStr.getSize() - 1);
-		for(PtrSize i = leftBracket; i <= rightBracket; ++i)
+		else
 		{
-			idxStr[i - leftBracket] = fullVarName[i];
+			ANKI_ASSERT(0);
 		}
-		idxStr[rightBracket - leftBracket + 1] = '\0';
-
-		ANKI_CHECK(CString(idxStr.getBegin()).toNumber(idx));
 	}
 
-	const PtrSize dot = fullVarName.find(".");
-	if(dot == CString::NPOS)
-	{
-		ANKI_RESOURCE_LOGE("Wrong variable name: %s", fullVarName.cstr());
-		return Error::USER_DATA;
-	}
-
-	name = fullVarName.getBegin() + dot;
+	m_shaderStages = binary.m_presentShaderTypes;
 
 	return Error::NONE;
 }
@@ -338,59 +240,6 @@ void ShaderProgramResource2::initVariant(
 	}
 	ANKI_ASSERT(binaryVariant);
 
-	// Init the uniform vars
-	if(m_materialUboIdx != MAX_U8)
-	{
-		variant.m_blockInfos.create(getAllocator(), m_inputVars.getSize());
-
-		for(const ShaderProgramBinaryVariableInstance& instance :
-			binaryVariant->m_uniformBlocks[m_materialUboIdx].m_variables)
-		{
-			ANKI_ASSERT(instance.m_index == m_materialUboIdx);
-			const U32 inputIdx = m_binaryMapping.m_uniformVars[instance.m_index].m_inputVarIdx;
-			const U32 arrayIdx = m_binaryMapping.m_uniformVars[instance.m_index].m_arrayIdx;
-			ShaderVariableBlockInfo& blockInfo = variant.m_blockInfos[inputIdx];
-
-			if(arrayIdx == 0)
-			{
-				blockInfo = instance.m_blockInfo;
-			}
-			else if(arrayIdx == 1)
-			{
-				ANKI_ASSERT(blockInfo.m_offset >= 0);
-				blockInfo.m_arraySize = max(blockInfo.m_arraySize, I16(arrayIdx + 1));
-				ANKI_ASSERT(instance.m_blockInfo.m_offset > blockInfo.m_offset);
-				blockInfo.m_arrayStride = instance.m_blockInfo.m_offset - blockInfo.m_offset;
-			}
-			else
-			{
-				ANKI_ASSERT(blockInfo.m_offset >= 0);
-				blockInfo.m_arraySize = max(blockInfo.m_arraySize, I16(arrayIdx + 1));
-			}
-
-			variant.m_activeInputVars.set(inputIdx);
-		}
-	}
-
-	// Init the opaques
-	variant.m_opaqueBindings.create(getAllocator(), m_inputVars.getSize(), -1);
-	for(const ShaderProgramBinaryOpaqueInstance& instance : binaryVariant->m_opaques)
-	{
-		const U32 opaqueIdx = instance.m_index;
-		const ShaderProgramBinaryOpaque& opaque = binary.m_opaques[opaqueIdx];
-		if(opaque.m_set != m_descriptorSet)
-		{
-			continue;
-		}
-
-		const U32 inputIdx = m_binaryMapping.m_opaques[opaqueIdx];
-		const Input& in = m_inputVars[inputIdx];
-		ANKI_ASSERT(in.isSampler() || in.isTexture());
-
-		variant.m_opaqueBindings[inputIdx] = I16(opaque.m_binding);
-		variant.m_activeInputVars.set(inputIdx);
-	}
-
 	// Set the constannt values
 	Array2d<ShaderSpecializationConstValue, U(ShaderType::COUNT), 64> constValues;
 	Array<U32, U(ShaderType::COUNT)> constValueCounts;
@@ -409,14 +258,14 @@ void ShaderProgramResource2::initVariant(
 				continue;
 			}
 
-			const U32 inputIdx = m_binaryMapping.m_constants[instance.m_index].m_inputVarIdx;
-			const U32 component = m_binaryMapping.m_constants[instance.m_index].m_component;
+			const U32 inputIdx = m_constBinaryMapping[instance.m_index].m_constsIdx;
+			const U32 component = m_constBinaryMapping[instance.m_index].m_component;
 
 			// Get value
 			const ShaderProgramResourceConstantValue2* value = nullptr;
 			for(U32 i = 0; i < info.m_constantValueCount; ++i)
 			{
-				if(info.m_constantValues[i].m_inputVariableIndex == inputIdx)
+				if(info.m_constantValues[i].m_constantIndex == inputIdx)
 				{
 					value = &info.m_constantValues[i];
 					break;

+ 22 - 81
src/anki/resource/ShaderProgramResource2.h

@@ -33,30 +33,12 @@ public:
 };
 
 /// Shader program resource variant.
-class ShaderProgramResourceInputVariable2
+class ShaderProgramResourceConstant2
 {
 public:
 	String m_name;
-	U32 m_index = MAX_U32;
 	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
-	Bool m_constant = false;
-	Bool m_instanced = false;
-
-	Bool isTexture() const
-	{
-		return m_dataType >= ShaderVariableDataType::TEXTURE_FIRST
-			   && m_dataType <= ShaderVariableDataType::TEXTURE_LAST;
-	}
-
-	Bool isSampler() const
-	{
-		return m_dataType == ShaderVariableDataType::SAMPLER;
-	}
-
-	Bool inBlock() const
-	{
-		return !m_constant && !isTexture() && !isSampler();
-	}
+	U32 m_index;
 };
 
 /// Shader program resource variant.
@@ -75,35 +57,14 @@ public:
 	}
 
 	/// Return true if the the variable is active in this variant.
-	Bool variableActive(const ShaderProgramResourceInputVariable2& var) const
+	Bool isConstantActive(const ShaderProgramResourceConstant2& var) const
 	{
-		return m_activeInputVars.get(var.m_index);
-	}
-
-	U32 getBinding(const ShaderProgramResourceInputVariable2& var) const
-	{
-		ANKI_ASSERT(m_opaqueBindings[var.m_index] >= 0);
-		return U32(m_opaqueBindings[var.m_index]);
-	}
-
-	U32 getUniformBlockSize() const
-	{
-		return m_uniBlockSize;
-	}
-
-	Bool usePushConstants() const
-	{
-		return m_usesPushConstants;
+		return m_activeConsts.get(var.m_index);
 	}
 
 private:
 	ShaderProgramPtr m_prog;
-
-	BitSet<128, U64> m_activeInputVars = {false};
-	DynamicArray<ShaderVariableBlockInfo> m_blockInfos;
-	DynamicArray<I16> m_opaqueBindings;
-	U32 m_uniBlockSize = 0;
-	Bool m_usesPushConstants = false;
+	BitSet<128, U64> m_activeConsts = {false};
 };
 
 /// Shader program resource. It loads special AnKi programs.
@@ -117,16 +78,16 @@ public:
 	/// Load the resource.
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
 
-	/// Get the array of input variables.
-	const DynamicArray<ShaderProgramResourceInputVariable2>& getInputVariables() const
+	/// Get the array of constants.
+	const DynamicArray<ShaderProgramResourceConstant2>& getConstants() const
 	{
-		return m_inputVars;
+		return m_consts;
 	}
 
-	/// Try to find an input variable.
-	const ShaderProgramResourceInputVariable2* tryFindInputVariable(CString name) const
+	/// Try to find a constant.
+	const ShaderProgramResourceConstant2* tryFindConstant(CString name) const
 	{
-		for(const ShaderProgramResourceInputVariable2& m : m_inputVars)
+		for(const ShaderProgramResourceConstant2& m : m_consts)
 		{
 			if(m.m_name == name)
 			{
@@ -155,10 +116,9 @@ public:
 		return nullptr;
 	}
 
-	/// Has tessellation shaders.
-	Bool hasTessellation() const
+	ShaderTypeBit getStages() const
 	{
-		return !!(m_shaderStages & ShaderTypeBit::TESSELLATION_EVALUATION);
+		return m_shaderStages;
 	}
 
 	/// Get or create a graphics shader program variant.
@@ -168,47 +128,29 @@ public:
 
 private:
 	using Mutator = ShaderProgramResourceMutator2;
-	using Input = ShaderProgramResourceInputVariable2;
+	using Const = ShaderProgramResourceConstant2;
 
 	ShaderProgramBinaryWrapper m_binary;
 
-	DynamicArray<Input> m_inputVars;
+	DynamicArray<Const> m_consts;
 	DynamicArray<Mutator> m_mutators;
 
-	class UniformVarInfo
-	{
-	public:
-		U32 m_arrayIdx = 0;
-		U32 m_inputVarIdx = 0;
-	};
-
-	class ConstInfo
+	class ConstMapping
 	{
 	public:
 		U32 m_component = 0;
-		U32 m_inputVarIdx = 0;
+		U32 m_constsIdx = 0; ///< Index in m_consts
 	};
 
-	class
-	{
-	public:
-		DynamicArray<UniformVarInfo> m_uniformVars;
-		DynamicArray<ConstInfo> m_constants;
-		DynamicArray<U32> m_opaques;
-	} m_binaryMapping;
+	DynamicArray<ConstMapping> m_constBinaryMapping;
 
 	mutable HashMap<U64, ShaderProgramResourceVariant2*> m_variants;
 	mutable RWMutex m_mtx;
 
-	U8 m_descriptorSet = MAX_U8;
-	U8 m_materialUboIdx = MAX_U8; ///< Index into the program binary.
-
 	ShaderTypeBit m_shaderStages = ShaderTypeBit::NONE;
 
 	void initVariant(const ShaderProgramResourceVariantInitInfo2& info, ShaderProgramResourceVariant2& variant) const;
 
-	static ANKI_USE_RESULT Error parseVariable(CString fullVarName, Bool& instanced, U32& idx, CString& name);
-
 	static ANKI_USE_RESULT Error parseConst(CString constName, U32& componentIdx, U32& componentCount, CString& name);
 };
 
@@ -229,8 +171,8 @@ public:
 		Vec4 m_vec4;
 	};
 
-	U32 m_inputVariableIndex;
-	U8 _m_padding[sizeof(Vec4) - sizeof(m_inputVariableIndex)];
+	U32 m_constantIndex;
+	U8 _m_padding[sizeof(Vec4) - sizeof(m_constantIndex)];
 
 	ShaderProgramResourceConstantValue2()
 	{
@@ -257,11 +199,10 @@ public:
 	template<typename T>
 	ShaderProgramResourceVariantInitInfo2& addConstant(CString name, const T& value)
 	{
-		const ShaderProgramResourceInputVariable2* in = m_ptr->tryFindInputVariable(name);
+		const ShaderProgramResourceConstant2* in = m_ptr->tryFindConstant(name);
 		ANKI_ASSERT(in);
-		ANKI_ASSERT(in->m_constant);
 		ANKI_ASSERT(in->m_dataType == getShaderVariableTypeFromTypename<T>());
-		m_constantValues[m_constantValueCount].m_inputVariableIndex = U32(in - m_ptr->getInputVariables().getBegin());
+		m_constantValues[m_constantValueCount].m_constantIndex = U32(in - m_ptr->getConstants().getBegin());
 		memcpy(&m_constantValues[m_constantValueCount].m_int, &value, sizeof(T));
 		++m_constantValueCount;
 		return *this;