瀏覽代碼

The material will calculate the uniform properties. Don't query GL

Panagiotis Christopoulos Charitos 11 年之前
父節點
當前提交
2ec2e366c7

+ 66 - 0
include/anki/gl/GlCommon.h

@@ -92,6 +92,72 @@ enum class ShaderType: U8
 };
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(ShaderType, inline)
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(ShaderType, inline)
 
 
+/// Shader variable type.
+enum class ShaderVariableDataType: U8
+{
+	FLOAT,
+	VEC2,
+	VEC3,
+	VEC4,
+	MAT3,
+	MAT4,
+	SAMPLER_2D,
+	SAMPLER_3D,
+	SAMPLER_2D_ARRAY,
+	SAMPLER_CUBE,
+
+	NUMERICS_FIRST = FLOAT,
+	NUMERICS_LAST = MAT4,
+
+	SAMPLERS_FIRST = SAMPLER_2D,
+	SAMPLERS_LAST = SAMPLER_CUBE
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(ShaderVariableDataType, inline)
+
+/// Using an AnKi typename get the ShaderVariableDataType. Used for debugging.
+template<typename T>
+ShaderVariableDataType getShaderVariableTypeFromTypename();
+
+#define ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET(typename_, type_) \
+	template<> \
+	inline ShaderVariableDataType \
+		getShaderVariableTypeFromTypename<typename_>() { \
+		return ShaderVariableDataType::type_; \
+	}
+
+ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET(F32, FLOAT)
+ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET(Vec2, VEC2)
+ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET(Vec3, VEC3)
+ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET(Vec4, VEC4)
+ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET(Mat3, MAT3)
+ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET(Mat4, MAT4)
+
+#undef ANKI_SPECIALIZE_SHADER_VAR_TYPE_GET
+
+/// Shader block information.
+struct ShaderVariableBlockInfo
+{
+	I16 m_offset = -1; ///< Offset inside the block
+
+	I16 m_arraySize = -1; ///< Number of elements.
+
+	/// Stride between the each array element if the variable is array.
+	I16 m_arrayStride = -1;
+
+	/// Identifying the stride between columns of a column-major matrix or rows
+	/// of a row-major matrix.
+	I16 m_matrixStride = -1;
+};
+
+/// Populate the memory of a variable that is inside a shader block.
+void writeShaderBlockMemory(
+	ShaderVariableDataType type,
+	const ShaderVariableBlockInfo& varBlkInfo,
+	const void* elements, 
+	U32 elementsCount,
+	void* buffBegin,
+	const void* buffEnd);
+
 /// Shader program variable. The type is attribute or uniform
 /// Shader program variable. The type is attribute or uniform
 class GlProgramVariable
 class GlProgramVariable
 {
 {

+ 23 - 26
include/anki/resource/Material.h

@@ -98,20 +98,33 @@ public:
 		return m_instanced;
 		return m_instanced;
 	}
 	}
 
 
-	void setUniformBufferInfo(U16 offset, U16 arrayStride, U16 matrixStride)
+	U32 getTextureUnit() const
 	{
 	{
-		m_offset = offset;
-		m_arrayStride = arrayStride;
-		m_matrixStride = matrixStride;
+		ANKI_ASSERT(m_textureUnit != -1);
+		return static_cast<U32>(m_textureUnit);
 	}
 	}
 
 
-private:
+	template<typename T>
+	void writeShaderBlockMemory(
+		const T* elements, 
+		U32 elementsCount,
+		void* buffBegin,
+		const void* buffEnd)
+	{
+		ANKI_ASSERT(Base::isTypeOf<MaterialVariableTemplate<T>>());
+		ANKI_ASSERT(m_varType == getShaderVariableTypeFromTypename<T>());
+		anki::writeShaderBlockMemory(m_varType, m_varBlkInfo, 
+			reinterpret_cast<T*>(elements), elementsCount, buffBegin, buffEnd);
+	}
+
+protected:
 	/// Keep one program variable here for easy access of the common
 	/// Keep one program variable here for easy access of the common
 	/// variable stuff like name or GL data type etc
 	/// variable stuff like name or GL data type etc
 	const GlProgramVariable* m_progVar;
 	const GlProgramVariable* m_progVar;
-	I16 m_offset = -1;
-	I16 m_arrayStride = -1;
-	I16 m_matrixStride = -1;
+	ShaderVariableDataType m_varType;
+	ShaderVariableBlockInfo m_varBlkInfo;
+	I16 m_textureUnit = -1;
+	ResourceString m_name;
 
 
 	Bool8 m_instanced;
 	Bool8 m_instanced;
 };
 };
@@ -134,24 +147,8 @@ public:
 	~MaterialVariableTemplate()
 	~MaterialVariableTemplate()
 	{}
 	{}
 
 
-	ANKI_USE_RESULT Error create(
-		ResourceAllocator<U8> alloc, const TData* x, U32 size)
-	{
-		Error err = ErrorCode::NONE;
-		if(size > 0)
-		{
-			err = m_data.create(alloc, size);
-			if(!err)
-			{
-				for(U i = 0; i < size; i++)
-				{
-					m_data[i] = x[i];
-				}
-			}
-		}
-
-		return ErrorCode::NONE;
-	}
+	ANKI_USE_RESULT Error create(ResourceAllocator<U8> alloc, 
+		const CString& name, const TData* x, U32 size);
 
 
 	void destroy(ResourceAllocator<U8> alloc)
 	void destroy(ResourceAllocator<U8> alloc)
 	{
 	{

+ 5 - 3
include/anki/resource/MaterialProgramCreator.h

@@ -24,7 +24,8 @@ public:
 
 
 	TempResourceAllocator<U8> m_alloc;
 	TempResourceAllocator<U8> m_alloc;
 	MPString m_name;
 	MPString m_name;
-	MPString m_type;
+	MPString m_typeStr;
+	ShaderVariableDataType m_type;
 	MPStringList m_value;
 	MPStringList m_value;
 	Bool8 m_constant = false;
 	Bool8 m_constant = false;
 	U16 m_arraySize = 0;
 	U16 m_arraySize = 0;
@@ -53,7 +54,7 @@ public:
 	~MaterialProgramCreatorInputVariable()
 	~MaterialProgramCreatorInputVariable()
 	{
 	{
 		m_name.destroy(m_alloc);
 		m_name.destroy(m_alloc);
-		m_type.destroy(m_alloc);
+		m_typeStr.destroy(m_alloc);
 		m_value.destroy(m_alloc);
 		m_value.destroy(m_alloc);
 		m_line.destroy(m_alloc);
 		m_line.destroy(m_alloc);
 	}
 	}
@@ -69,7 +70,8 @@ public:
 	{
 	{
 		m_alloc = std::move(b.m_alloc);
 		m_alloc = std::move(b.m_alloc);
 		m_name = std::move(b.m_name);
 		m_name = std::move(b.m_name);
-		m_type = std::move(b.m_type);
+		m_type = b.m_type;
+		m_typeStr = std::move(b.m_typeStr);
 		m_value = std::move(b.m_value);
 		m_value = std::move(b.m_value);
 		m_constant = b.m_constant;
 		m_constant = b.m_constant;
 		m_arraySize = b.m_arraySize;
 		m_arraySize = b.m_arraySize;

+ 126 - 0
src/gl/GlCommon.cpp

@@ -58,4 +58,130 @@ GLenum computeGlShaderType(const ShaderType idx, GLbitfield* bit)
 	return gltype[enumToType(idx)];
 	return gltype[enumToType(idx)];
 }
 }
 
 
+//==============================================================================
+template<typename T>
+void writeShaderBlockMemorySanityChecks(
+	const ShaderVariableBlockInfo& varBlkInfo,
+	const void* elements, 
+	U32 elementsCount,
+	void* buffBegin,
+	const void* buffEnd)
+{
+	// Check args
+	ANKI_ASSERT(elements != nullptr);
+	ANKI_ASSERT(elementsCount > 0);
+	ANKI_ASSERT(buffBegin != nullptr);
+	ANKI_ASSERT(buffEnd != nullptr);
+	ANKI_ASSERT(buffBegin < buffEnd);
+	
+	// Check varBlkInfo
+	ANKI_ASSERT(varBlkInfo.m_offset != -1);
+	ANKI_ASSERT(varBlkInfo.m_arraySize > 0);
+
+	if(varBlkInfo.m_arraySize > 1)
+	{
+		ANKI_ASSERT(varBlkInfo.m_arrayStride > 0);
+	}
+
+	// Check array size
+	ANKI_ASSERT(static_cast<I16>(elementsCount) <= varBlkInfo.m_arraySize);
+}
+
+//==============================================================================
+template<typename T>
+static void writeShaderBlockMemorySimple(
+	const ShaderVariableBlockInfo& varBlkInfo,
+	const void* elements, 
+	U32 elementsCount,
+	void* buffBegin,
+	const void* buffEnd)
+{
+	writeShaderBlockMemorySanityChecks<T>(varBlkInfo, elements, elementsCount,
+		buffBegin, buffEnd);
+	
+	U8* buff = static_cast<U8*>(buffBegin) + varBlkInfo.m_offset;
+	for(U i = 0; i < elementsCount; i++)
+	{
+		ANKI_ASSERT(buff + sizeof(T) <= static_cast<const U8*>(buffEnd));
+
+		T* out = reinterpret_cast<T*>(buff);
+		const T* in = reinterpret_cast<const T*>(elements) + i;
+		*out = *in;
+
+		buff += varBlkInfo.m_arrayStride;
+	}
+}
+
+//==============================================================================
+template<typename T, typename Vec>
+static void writeShaderBlockMemoryMatrix(
+	const ShaderVariableBlockInfo& varBlkInfo,
+	const void* elements, 
+	U32 elementsCount,
+	void* buffBegin,
+	const void* buffEnd)
+{
+	writeShaderBlockMemorySanityChecks<T>(varBlkInfo, elements, elementsCount,
+		buffBegin, buffEnd);
+	ANKI_ASSERT(varBlkInfo.m_matrixStride > 0);
+	ANKI_ASSERT(varBlkInfo.m_matrixStride >= static_cast<I16>(sizeof(Vec)));
+
+	U8* buff = static_cast<U8*>(buffBegin) + varBlkInfo.m_offset;
+	for(U i = 0; i < elementsCount; i++)
+	{
+		U8* subbuff = buff;
+		T matrix = reinterpret_cast<const T*>(elements)[i];
+		matrix.transpose();
+		for(U j = 0; j < sizeof(T) / sizeof(Vec); j++)
+		{
+			ANKI_ASSERT(subbuff + sizeof(Vec) <= static_cast<U8*>(buffEnd));
+
+			Vec* out = reinterpret_cast<Vec*>(subbuff);
+			*out = matrix.getRow(j);
+			subbuff += varBlkInfo.m_matrixStride;
+		}
+		buff += varBlkInfo.m_arrayStride;
+	}
+}
+
+//==============================================================================
+void writeShaderBlockMemory(
+	ShaderVariableDataType type,
+	const ShaderVariableBlockInfo& varBlkInfo,
+	const void* elements, 
+	U32 elementsCount,
+	void* buffBegin,
+	const void* buffEnd)
+{
+	switch(type)
+	{
+	case ShaderVariableDataType::FLOAT:
+		writeShaderBlockMemorySimple<F32>(varBlkInfo, elements, elementsCount,
+			buffBegin, buffEnd);
+		break;
+	case ShaderVariableDataType::VEC2:
+		writeShaderBlockMemorySimple<Vec2>(varBlkInfo, elements, elementsCount,
+			buffBegin, buffEnd);
+		break;
+	case ShaderVariableDataType::VEC3:
+		writeShaderBlockMemorySimple<Vec3>(varBlkInfo, elements, elementsCount,
+			buffBegin, buffEnd);
+		break;
+	case ShaderVariableDataType::VEC4:
+		writeShaderBlockMemorySimple<Vec4>(varBlkInfo, elements, elementsCount,
+			buffBegin, buffEnd);
+		break;
+	case ShaderVariableDataType::MAT3:
+		writeShaderBlockMemorySimple<Mat3>(varBlkInfo, elements, elementsCount,
+			buffBegin, buffEnd);
+		break;
+	case ShaderVariableDataType::MAT4:
+		writeShaderBlockMemorySimple<Mat4>(varBlkInfo, elements, elementsCount,
+			buffBegin, buffEnd);
+		break;
+	default:
+		ANKI_ASSERT(0);
+	}
+}
+
 } // end namespace anki
 } // end namespace anki

+ 65 - 21
src/resource/Material.cpp

@@ -71,14 +71,43 @@ U32 MaterialVariable::getArraySize() const
 	return m_progVar->getArraySize();
 	return m_progVar->getArraySize();
 }
 }
 
 
+//==============================================================================
+template<typename T>
+Error MaterialVariableTemplate<T>::create(ResourceAllocator<U8> alloc, 
+	const CString& name, const T* x, U32 size)
+{
+	Error err = ErrorCode::NONE;
+
+	err = m_name.create(alloc, name);
+
+	if(!err && size > 0)
+	{
+		err = m_data.create(alloc, size);
+		if(!err)
+		{
+			for(U i = 0; i < size; i++)
+			{
+				m_data[i] = x[i];
+			}
+		}
+	}
+
+	return ErrorCode::NONE;
+}
+
 //==============================================================================
 //==============================================================================
 template<typename T>
 template<typename T>
 MaterialVariableTemplate<T>* MaterialVariableTemplate<T>::_newInstance(
 MaterialVariableTemplate<T>* MaterialVariableTemplate<T>::_newInstance(
 	const GlProgramVariable& glvar, const MaterialProgramCreator::Input& in,
 	const GlProgramVariable& glvar, const MaterialProgramCreator::Input& in,
 	ResourceAllocator<U8> alloc, TempResourceAllocator<U8> talloc)
 	ResourceAllocator<U8> alloc, TempResourceAllocator<U8> talloc)
 {
 {
+	Error err = ErrorCode::NONE;
 	MaterialVariableTemplate<T>* out = nullptr;
 	MaterialVariableTemplate<T>* out = nullptr;
 
 
+	TempResourceDArray<F32> floats;
+	TempResourceDArray<F32>::ScopeDestroyer floatsd(&floats, talloc);
+
+	// Get the float values
 	if(in.m_value.getSize() > 0)
 	if(in.m_value.getSize() > 0)
 	{
 	{
 		// Has values
 		// Has values
@@ -93,43 +122,58 @@ MaterialVariableTemplate<T>* MaterialVariableTemplate<T>::_newInstance(
 			return nullptr;
 			return nullptr;
 		}
 		}
 
 
-		TempResourceVector<F32> floatvec(talloc);
-		floatvec.resize(floatsNeeded);
+		err = floats.create(talloc, floatsNeeded);
+		if(err) return nullptr;
+
 		auto it = in.m_value.getBegin();
 		auto it = in.m_value.getBegin();
 		for(U i = 0; i < floatsNeeded; ++i)
 		for(U i = 0; i < floatsNeeded; ++i)
 		{
 		{
 			F64 d;
 			F64 d;
-			Error err = it->toF64(d);
-			if(err)
-			{
-				return nullptr;
-			}
+			err = it->toF64(d);
+			if(err)	return nullptr;
 
 
-			floatvec[i] = d;
+			floats[i] = d;
 			++it;
 			++it;
 		}
 		}
 
 
 		out = alloc.newInstance<MaterialVariableTemplate<T>>(
 		out = alloc.newInstance<MaterialVariableTemplate<T>>(
 			&glvar, in.m_instanced);
 			&glvar, in.m_instanced);
+	}
 
 
-		if(out)
-		{
-			Error err = out->create(
-				alloc, (T*)&floatvec[0], glvar.getArraySize());
+	// Create new instance
+	out = alloc.newInstance<MaterialVariableTemplate<T>>(
+		&glvar, in.m_instanced);
+	if(!out) return nullptr;
 
 
-			if(err)
-			{
-				alloc.deleteInstance(out);
-				out = nullptr;
-			}
-		}
+	if(floats.getSize() > 0)
+	{
+		err = out->create(alloc, in.m_name.toCString(), 
+			(T*)&floats[0], glvar.getArraySize());
 	}
 	}
 	else
 	else
 	{
 	{
 		// Buildin
 		// Buildin
+		err = out->create(alloc, in.m_name.toCString(), nullptr, 0);
+	}
 
 
-		out = alloc.newInstance<MaterialVariableTemplate<T>>(
-			&glvar, in.m_instanced);
+	if(err && out)
+	{
+		alloc.deleteInstance(out);
+		return nullptr;
+	}
+
+	// Set some values
+	out->m_varType = in.m_type;
+	out->m_textureUnit = in.m_binding;
+	out->m_varBlkInfo.m_arraySize = in.m_arraySize;
+
+	// Set UBO data
+	if(out && in.m_inBlock)
+	{
+		out->m_varBlkInfo.m_offset = in.m_offset;
+		ANKI_ASSERT(out->m_varBlkInfo.m_offset >= 0);
+		out->m_varBlkInfo.m_arrayStride = in.m_arrayStride;
+		out->m_varBlkInfo.m_matrixStride = in.m_matrixStride;
 	}
 	}
 
 
 	return out;
 	return out;
@@ -657,7 +701,7 @@ Error Material::populateVariables(const MaterialProgramCreator& loader)
 
 
 				if(tvar)
 				if(tvar)
 				{
 				{
-					err = tvar->create(alloc, &tp, 1);
+					err = tvar->create(alloc, in.m_name.toCString(), &tp, 1);
 
 
 					if(err)
 					if(err)
 					{
 					{

+ 52 - 11
src/resource/MaterialProgramCreator.cpp

@@ -68,6 +68,45 @@ static ANKI_USE_RESULT Error getShaderInfo(
 	return err;
 	return err;
 }
 }
 
 
+//==============================================================================
+ANKI_USE_RESULT Error computeShaderVariableDataType(
+	const CString& str, ShaderVariableDataType& out)
+{
+	Error err = ErrorCode::NONE;
+
+	if(str == "float")
+	{
+		out = ShaderVariableDataType::FLOAT;
+	}
+	else if(str == "vec2")
+	{
+		out = ShaderVariableDataType::VEC2;
+	}
+	else if(str == "vec3")
+	{
+		out = ShaderVariableDataType::VEC3;
+	}
+	else if(str == "vec4")
+	{
+		out = ShaderVariableDataType::VEC4;
+	}
+	else if(str == "mat3")
+	{
+		out = ShaderVariableDataType::MAT3;
+	}
+	else if(str == "mat4")
+	{
+		out = ShaderVariableDataType::MAT4;
+	}
+	else
+	{
+		ANKI_LOGE("Incorrect variable type %s", &str[0]);
+		err = ErrorCode::USER_DATA;
+	}
+
+	return err;
+}
+
 //==============================================================================
 //==============================================================================
 // MaterialProgramCreator                                                      =
 // MaterialProgramCreator                                                      =
 //==============================================================================
 //==============================================================================
@@ -284,7 +323,8 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 		// <type>
 		// <type>
 		ANKI_CHECK(inputEl.getChildElement("type", el));
 		ANKI_CHECK(inputEl.getChildElement("type", el));
 		ANKI_CHECK(el.getText(cstr));
 		ANKI_CHECK(el.getText(cstr));
-		ANKI_CHECK(inpvar.m_type.create(m_alloc, cstr));
+		ANKI_CHECK(inpvar.m_typeStr.create(m_alloc, cstr));
+		ANKI_CHECK(computeShaderVariableDataType(cstr, inpvar.m_type));
 
 
 		// <value>
 		// <value>
 		XmlElement valueEl;
 		XmlElement valueEl;
@@ -391,7 +431,7 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 			// Handle NON-consts
 			// Handle NON-consts
 
 
 			ANKI_CHECK(inpvar.m_line.sprintf(
 			ANKI_CHECK(inpvar.m_line.sprintf(
-				m_alloc, "%s %s", &inpvar.m_type[0], &inpvar.m_name[0]));
+				m_alloc, "%s %s", &inpvar.m_typeStr[0], &inpvar.m_name[0]));
 			
 			
 			U arrSize = 0;
 			U arrSize = 0;
 			if(inpvar.m_instanced)
 			if(inpvar.m_instanced)
@@ -415,7 +455,8 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 			ANKI_CHECK(inpvar.m_line.append(m_alloc, ";"));
 			ANKI_CHECK(inpvar.m_line.append(m_alloc, ";"));
 
 
 			// Can put it block
 			// Can put it block
-			if(inpvar.m_type == "sampler2D" || inpvar.m_type == "samplerCube")
+			if(inpvar.m_type >= ShaderVariableDataType::SAMPLERS_FIRST 
+				&& inpvar.m_type <= ShaderVariableDataType::SAMPLERS_LAST)
 			{
 			{
 				MPString tmp;
 				MPString tmp;
 
 
@@ -443,16 +484,16 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 				inpvar.m_inBlock = true;
 				inpvar.m_inBlock = true;
 
 
 				inpvar.m_offset = m_blockSize;
 				inpvar.m_offset = m_blockSize;
-				if(inpvar.m_type == "float" 
-					|| inpvar.m_type == "vec2"
-					|| inpvar.m_type == "vec3"
-					|| inpvar.m_type == "vec4")
+				if(inpvar.m_type == ShaderVariableDataType::FLOAT 
+					|| inpvar.m_type == ShaderVariableDataType::VEC2
+					|| inpvar.m_type == ShaderVariableDataType::VEC3
+					|| inpvar.m_type == ShaderVariableDataType::VEC4)
 				{
 				{
 					inpvar.m_arrayStride = sizeof(Vec4);
 					inpvar.m_arrayStride = sizeof(Vec4);
 					m_blockSize += sizeof(Vec4) * inpvar.m_arraySize;
 					m_blockSize += sizeof(Vec4) * inpvar.m_arraySize;
 				}
 				}
-				else if(inpvar.m_type == "mat3"
-					|| inpvar.m_type == "mat4")
+				else if(inpvar.m_type == ShaderVariableDataType::MAT3
+					|| inpvar.m_type == ShaderVariableDataType::MAT4)
 				{
 				{
 					inpvar.m_arrayStride = sizeof(Mat4);
 					inpvar.m_arrayStride = sizeof(Mat4);
 					m_blockSize += sizeof(Mat4) * inpvar.m_arraySize;
 					m_blockSize += sizeof(Mat4) * inpvar.m_arraySize;
@@ -460,7 +501,7 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 				}
 				}
 				else
 				else
 				{
 				{
-					ANKI_LOGE("Unsupported type %s", &inpvar.m_type[0]);
+					ANKI_LOGE("Unsupported type %s", &inpvar.m_typeStr[0]);
 					return ErrorCode::USER_DATA;
 					return ErrorCode::USER_DATA;
 				}
 				}
 			}
 			}
@@ -487,7 +528,7 @@ Error MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 			ANKI_CHECK(inpvar.m_value.join(m_alloc, ", ", initList));
 			ANKI_CHECK(inpvar.m_value.join(m_alloc, ", ", initList));
 
 
 			err = inpvar.m_line.sprintf(m_alloc, "const %s %s = %s(%s);",
 			err = inpvar.m_line.sprintf(m_alloc, "const %s %s = %s(%s);",
-				&inpvar.m_type[0], &inpvar.m_name[0], &inpvar.m_type[0], 
+				&inpvar.m_typeStr[0], &inpvar.m_name[0], &inpvar.m_typeStr[0], 
 				&initList[0]);
 				&initList[0]);
 			initList.destroy(m_alloc);
 			initList.destroy(m_alloc);