Просмотр исходного кода

New material parameter caching system works

BearishSun 10 лет назад
Родитель
Сommit
25a7656e54

+ 58 - 85
BansheeCore/Include/BsMaterialParams.h

@@ -11,6 +11,7 @@
 #include "BsMatrix3.h"
 #include "BsMatrix4.h"
 #include "BsMatrixNxM.h"
+#include "BsGpuParams.h"
 #include "BsMaterial.h"
 #include "BsShader.h"
 
@@ -88,11 +89,17 @@ namespace BansheeEngine
 		template <typename T>
 		void getDataParam(const String& name, UINT32 arrayIdx, T& output) const
 		{
-			const ParamData* param = getParamData(name, ParamType::Data, getDataType(output), arrayIdx);
+			GpuParamDataType dataType = getDataType(output);
+
+			const ParamData* param = getParamData(name, ParamType::Data, dataType, arrayIdx);
 			if (param == nullptr)
 				return;
 
-			getDataParam(param->index + arrayIdx, output);
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES[dataType];
+			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
+			output = *(T*)(mDataParamsBuffer[param->index + arrayIdx * paramTypeSize]);
+
+			memcpy(output, &mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], sizeof(paramTypeSize));
 		}
 
 		/** 
@@ -108,11 +115,16 @@ namespace BansheeEngine
 		template <typename T>
 		void setDataParam(const String& name, UINT32 arrayIdx, const T& input) const
 		{
-			const ParamData* param = getParamData(name, ParamType::Data, getDataType(input), arrayIdx);
+			GpuParamDataType dataType = getDataType(output);
+
+			const ParamData* param = getParamData(name, ParamType::Data, dataType, arrayIdx);
 			if (param == nullptr)
 				return;
 
-			setDataParam(param->index + arrayIdx, input);
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES[dataType];
+			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
+
+			memcpy(&mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], input, sizeof(paramTypeSize));
 		}
 
 		/** 
@@ -124,7 +136,7 @@ namespace BansheeEngine
 		 * @param[in]	size		Size of the buffer into which to write the value. Must match parameter struct's size.
 		 * @param[in]	arrayIdx	If the parameter is an array, index of the entry to access.
 		 */
-		void getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx);
+		void getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const;
 
 		/** 
 		 * Sets the value of a shader structure parameter with the specified name at the specified array index. If the
@@ -144,7 +156,7 @@ namespace BansheeEngine
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 */
-		void getTexture(const String& name, HTexture& value);
+		void getTexture(const String& name, HTexture& value) const;
 
 		/** 
 		 * Sets the value of a shader texture parameter with the specified name. If the parameter name or type is not 
@@ -163,7 +175,7 @@ namespace BansheeEngine
 		 * @param[out]	value		Output value of the parameter.
 		 * @param[out]	surface		Surface describing which part of the texture is being accessed.
 		 */
-		void getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface);
+		void getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface) const;
 
 		/** 
 		 * Sets the value of a shader load/store texture parameter with the specified name. If the parameter name or 
@@ -182,7 +194,7 @@ namespace BansheeEngine
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 */
-		void getSamplerState(const String& name, SamplerStatePtr& value);
+		void getSamplerState(const String& name, SamplerStatePtr& value) const;
 
 		/** 
 		 * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not 
@@ -208,55 +220,45 @@ namespace BansheeEngine
 		 * @return					If successful, object describing the parameter with an index to its data. Otherwise
 		 *							null.
 		 */
-		const ParamData* getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx);
-
-		/** Returns a value of a parameter using its iternal array index as returned by getParamData(). */
-		void getDataParam(UINT32 index, float& output) const { output = mFloatParams[index]; }
-
-		/** @copydoc getDataParam(UINT32, float&) */
-		void getDataParam(UINT32 index, Vector2& output) const { output = mVec2Params[index]; }
-
-		/** @copydoc getDataParam(UINT32, float&) */
-		void getDataParam(UINT32 index, Vector3& output) const { output = mVec3Params[index]; }
+		const ParamData* getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx) const;
 
-		/** @copydoc getDataParam(UINT32, float&) */
-		void getDataParam(UINT32 index, Vector4& output) const { output = mVec4Params[index]; }
-
-		/** @copydoc getDataParam(UINT32, float&) */
-		void getDataParam(UINT32 index, Matrix3& output) const { output = mMat3Params[index]; }
-
-		/** @copydoc getDataParam(UINT32, float&) */
-		void getDataParam(UINT32 index, Matrix4& output) const { output = mMat4Params[index]; }
-
-		/** @copydoc getDataParam(UINT32, float&) */
-		void getDataParam(UINT32 index, Color& output) const { output = mColorParams[index]; }
-
-		/** Sets a value of a parameter using its iternal array index as returned by getParamData(). */
-		void setDataParam(UINT32 index, float input) { mFloatParams[index] = input; }
-
-		/** @copydoc setDataParam(UINT32, float&) */
-		void setDataParam(UINT32 index, Vector2 input) { mVec2Params[index] = input; }
+		/** 
+		 * Equivalent to getStructData(const String&, UINT32, T&) except it uses the internal parameter index
+		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 */
+		template <typename T>
+		void getDataParam(UINT32 index, UINT32 arrayIdx, T& output) const
+		{
+			GpuParamDataType dataType = getDataType(output);
 
-		/** @copydoc setDataParam(UINT32, float&) */
-		void setDataParam(UINT32 index, Vector3 input) { mVec3Params[index] = input; }
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
+			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 
-		/** @copydoc setDataParam(UINT32, float&) */
-		void setDataParam(UINT32 index, Vector4 input) { mVec4Params[index] = input; }
+			assert(sizeof(output) == paramTypeSize);
+			memcpy(&output, &mDataParamsBuffer[index + arrayIdx * paramTypeSize], paramTypeSize);
+		}
 
-		/** @copydoc setDataParam(UINT32, float&) */
-		void setDataParam(UINT32 index, Matrix3 input) { mMat3Params[index] = input; }
+		/** 
+		 * Equivalent to setDataParam(const String&, UINT32, T&) except it uses the internal parameter index
+		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
+		 */
+		template <typename T>
+		void setDataParam(UINT32 index, UINT32 arrayIdx, const T& input) const
+		{
+			GpuParamDataType dataType = getDataType(input);
 
-		/** @copydoc setDataParam(UINT32, float&) */
-		void setDataParam(UINT32 index, Matrix4 input) { mMat4Params[index] = input; }
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
+			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 
-		/** @copydoc setDataParam(UINT32, float&) */
-		void setDataParam(UINT32 index, Color input) { mColorParams[index] = input; }
+			assert(sizeof(input) == paramTypeSize);
+			memcpy(&mDataParamsBuffer[index + arrayIdx * paramTypeSize], &input, paramTypeSize);
+		}
 
 		/** 
 		 * Equivalent to getStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
-		void getStructData(UINT32 index, void* value, UINT32 size);
+		void getStructData(UINT32 index, void* value, UINT32 size) const;
 
 		/** 
 		 * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
@@ -264,11 +266,17 @@ namespace BansheeEngine
 		 */
 		void setStructData(UINT32 index, const void* value, UINT32 size);
 
+		/** 
+		 * Returns a size of a struct parameter in bytes, using the internal parameter index. Caller must guarantee the 
+		 * index is valid. 
+		 */
+		UINT32 getStructSize(UINT32 index) const;
+
 		/** 
 		 * Equivalent to getTexture(const String&, HTexture&) except it uses the internal parameter index directly, 
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
-		void getTexture(UINT32 index, HTexture& value);
+		void getTexture(UINT32 index, HTexture& value) const;
 
 		/** 
 		 * Equivalent to setTexture(const String&, HTexture&) except it uses the internal parameter index directly, 
@@ -280,7 +288,7 @@ namespace BansheeEngine
 		 * Equivalent to getLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal 
 		 * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
-		void getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface);
+		void getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface) const;
 
 		/** 
 		 * Equivalent to setLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal 
@@ -292,7 +300,7 @@ namespace BansheeEngine
 		 * Equivalent to getSamplerState(const String&, SamplerStatePtr&) except it uses the internal parameter index 
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
-		void getSamplerState(UINT32 index, SamplerStatePtr& value);
+		void getSamplerState(UINT32 index, SamplerStatePtr& value) const;
 
 		/** 
 		 * Equivalent to setSamplerState(const String&, SamplerStatePtr&) except it uses the internal parameter index 
@@ -323,46 +331,11 @@ namespace BansheeEngine
 
 		UnorderedMap<String, ParamData> mParams;
 
-		float* mFloatParams = nullptr;
-		Vector2* mVec2Params = nullptr;
-		Vector3* mVec3Params = nullptr;
-		Vector4* mVec4Params = nullptr;
-		int* mIntParams = nullptr;
-		Vector2I* mVec2IParams = nullptr;
-		Vector3I* mVec3IParams = nullptr;
-		Vector4I* mVec4IParams = nullptr;
-		Matrix2* mMat2Params = nullptr;
-		Matrix2x3* mMat2x3Params = nullptr;
-		Matrix2x4* mMat2x4Params = nullptr;
-		Matrix3* mMat3Params = nullptr;
-		Matrix3x2* mMat3x2Params = nullptr;
-		Matrix3x4* mMat3x4Params = nullptr;
-		Matrix4* mMat4Params = nullptr;
-		Matrix4x2* mMat4x2Params = nullptr;
-		Matrix4x3* mMat4x3Params = nullptr;
-		Color* mColorParams = nullptr;
+		UINT8* mDataParamsBuffer = nullptr;
 		StructParamData* mStructParams = nullptr;
 		TextureParamData* mTextureParams = nullptr;
 		SamplerStatePtr* mSamplerStateParams = nullptr;
 
-		UINT32 mNumFloatParams = 0;
-		UINT32 mNumVec2Params = 0;
-		UINT32 mNumVec3Params = 0;
-		UINT32 mNumVec4Params = 0;
-		UINT32 mNumIntParams = 0;
-		UINT32 mNumVec2IParams = 0;
-		UINT32 mNumVec3IParams = 0;
-		UINT32 mNumVec4IParams = 0;
-		UINT32 mNumMat2Params = 0;
-		UINT32 mNumMat2x3Params = 0;
-		UINT32 mNumMat2x4Params = 0;
-		UINT32 mNumMat3Params = 0;
-		UINT32 mNumMat3x2Params = 0;
-		UINT32 mNumMat3x4Params = 0;
-		UINT32 mNumMat4Params = 0;
-		UINT32 mNumMat4x2Params = 0;
-		UINT32 mNumMat4x3Params = 0;
-		UINT32 mNumColorParams = 0;
 		UINT32 mNumStructParams = 0;
 		UINT32 mNumTextureParams = 0;
 		UINT32 mNumSamplerParams = 0;

+ 80 - 85
BansheeCore/Source/BsMaterial.cpp

@@ -490,29 +490,28 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		auto iterFind = mValidParams.find(name);
-		if (iterFind == mValidParams.end())
-		{
-			LOGWRN_VERBOSE("Material doesn't have a parameter named " + name);
-			return TMaterialParamStruct<Core>();
-		}
+		SPtr<Vector<TGpuParamStruct<Core>>> gpuParams;
 
-		const String& gpuVarName = iterFind->second;
-		SPtr<Vector<TGpuParamStruct<Core>>> gpuParams = bs_shared_ptr_new<Vector<TGpuParamStruct<Core>>>();
-
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		auto iterFind = mValidParams.find(name);
+		if (iterFind != mValidParams.end())
 		{
-			SPtr<PassParamsType> params = *iter;
+			const String& gpuVarName = iterFind->second;
+			gpuParams = bs_shared_ptr_new<Vector<TGpuParamStruct<Core>>>();
 
-			for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
-				GpuParamsType& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
+				SPtr<PassParamsType> params = *iter;
+
+				for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
 				{
-					if (paramPtr->hasParam(gpuVarName))
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
 					{
-						gpuParams->push_back(TGpuParamStruct<Core>());
-						paramPtr->getStructParam(gpuVarName, gpuParams->back());
+						if (paramPtr->hasParam(gpuVarName))
+						{
+							gpuParams->push_back(TGpuParamStruct<Core>());
+							paramPtr->getStructParam(gpuVarName, gpuParams->back());
+						}
 					}
 				}
 			}
@@ -526,29 +525,28 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		auto iterFind = mValidParams.find(name);
-		if (iterFind == mValidParams.end())
-		{
-			LOGWRN_VERBOSE("Material doesn't have a parameter named " + name);
-			return TMaterialParamTexture<Core>();
-		}
+		SPtr<Vector<TGpuParamTexture<Core>>> gpuParams;
 
-		const String& gpuVarName = iterFind->second;
-		SPtr<Vector<TGpuParamTexture<Core>>> gpuParams = bs_shared_ptr_new<Vector<TGpuParamTexture<Core>>>();
-
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		auto iterFind = mValidParams.find(name);
+		if (iterFind != mValidParams.end())
 		{
-			SPtr<PassParamsType> params = *iter;
+			const String& gpuVarName = iterFind->second;
+			gpuParams = bs_shared_ptr_new<Vector<TGpuParamTexture<Core>>>();
 
-			for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
-				GpuParamsType& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
+				SPtr<PassParamsType> params = *iter;
+
+				for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
 				{
-					if (paramPtr->hasTexture(gpuVarName))
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
 					{
-						gpuParams->push_back(TGpuParamTexture<Core>());
-						paramPtr->getTextureParam(gpuVarName, gpuParams->back());
+						if (paramPtr->hasTexture(gpuVarName))
+						{
+							gpuParams->push_back(TGpuParamTexture<Core>());
+							paramPtr->getTextureParam(gpuVarName, gpuParams->back());
+						}
 					}
 				}
 			}
@@ -562,29 +560,28 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		auto iterFind = mValidParams.find(name);
-		if (iterFind == mValidParams.end())
-		{
-			LOGWRN_VERBOSE("Material doesn't have a parameter named " + name);
-			return TMaterialParamLoadStoreTexture<Core>();
-		}
-
-		const String& gpuVarName = iterFind->second;
-		SPtr<Vector<TGpuParamLoadStoreTexture<Core>>> gpuParams = bs_shared_ptr_new<Vector<TGpuParamLoadStoreTexture<Core>>>();
+		SPtr<Vector<TGpuParamLoadStoreTexture<Core>>> gpuParams;
 
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		auto iterFind = mValidParams.find(name);
+		if (iterFind != mValidParams.end())
 		{
-			SPtr<PassParamsType> params = *iter;
+			const String& gpuVarName = iterFind->second;
+			gpuParams = bs_shared_ptr_new<Vector<TGpuParamLoadStoreTexture<Core>>>();
 
-			for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
-				GpuParamsType& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
+				SPtr<PassParamsType> params = *iter;
+
+				for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
 				{
-					if (paramPtr->hasTexture(gpuVarName))
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
 					{
-						gpuParams->push_back(TGpuParamLoadStoreTexture<Core>());
-						paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams->back());
+						if (paramPtr->hasTexture(gpuVarName))
+						{
+							gpuParams->push_back(TGpuParamLoadStoreTexture<Core>());
+							paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams->back());
+						}
 					}
 				}
 			}
@@ -598,28 +595,27 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		auto iterFind = mValidParams.find(name);
-		if (iterFind == mValidParams.end())
-		{
-			LOGWRN_VERBOSE("Material doesn't have a parameter named " + name);
-			return TMaterialParamSampState<Core>();
-		}
+		SPtr<Vector<TGpuParamSampState<Core>>> gpuParams;
 
-		const String& gpuVarName = iterFind->second;
-		SPtr<Vector<TGpuParamSampState<Core>>> gpuParams = bs_shared_ptr_new<Vector<TGpuParamSampState<Core>>>();
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		auto iterFind = mValidParams.find(name);
+		if (iterFind != mValidParams.end())
 		{
-			SPtr<PassParamsType> params = *iter;
-
-			for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
+			const String& gpuVarName = iterFind->second;
+			gpuParams = bs_shared_ptr_new<Vector<TGpuParamSampState<Core>>>();
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
-				GpuParamsType& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
+				SPtr<PassParamsType> params = *iter;
+
+				for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
 				{
-					if (paramPtr->hasSamplerState(gpuVarName))
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
 					{
-						gpuParams->push_back(TGpuParamSampState<Core>());
-						paramPtr->getSamplerStateParam(gpuVarName, gpuParams->back());
+						if (paramPtr->hasSamplerState(gpuVarName))
+						{
+							gpuParams->push_back(TGpuParamSampState<Core>());
+							paramPtr->getSamplerStateParam(gpuVarName, gpuParams->back());
+						}
 					}
 				}
 			}
@@ -909,29 +905,28 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		auto iterFind = mValidParams.find(name);
-		if (iterFind == mValidParams.end())
-		{
-			LOGWRN_VERBOSE("Material doesn't have a parameter named " + name);
-			return;
-		}
-
-		const String& gpuVarName = iterFind->second;
-		SPtr<Vector<TGpuDataParam<T, Core>>> gpuParams = bs_shared_ptr_new<Vector<TGpuDataParam<T, Core>>>();
+		SPtr<Vector<TGpuDataParam<T, Core>>> gpuParams;
 
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		auto iterFind = mValidParams.find(name);
+		if (iterFind != mValidParams.end())
 		{
-			SPtr<PassParamsType> params = *iter;
+			const String& gpuVarName = iterFind->second;
+			gpuParams = bs_shared_ptr_new<Vector<TGpuDataParam<T, Core>>>();
 
-			for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
+			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
 			{
-				GpuParamsType& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
+				SPtr<PassParamsType> params = *iter;
+
+				for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
 				{
-					if (paramPtr->hasParam(gpuVarName))
+					GpuParamsType& paramPtr = params->getParamByIdx(i);
+					if (paramPtr)
 					{
-						gpuParams->push_back(TGpuDataParam<T, Core>());
-						paramPtr->getParam<T>(gpuVarName, gpuParams->back());
+						if (paramPtr->hasParam(gpuVarName))
+						{
+							gpuParams->push_back(TGpuDataParam<T, Core>());
+							paramPtr->getParam<T>(gpuVarName, gpuParams->back());
+						}
 					}
 				}
 			}

+ 24 - 8
BansheeCore/Source/BsMaterialParam.cpp

@@ -8,7 +8,7 @@ namespace BansheeEngine
 	template<class T>
 	TMaterialDataParam<T, false>::TMaterialDataParam(const String& name, const SPtr<__MaterialParams>& params,
 		const SPtr<Vector<TGpuDataParam<T, false>>>& gpuParams)
-		:mParamIndex(0), mArraySize(0), mMaterialParams(params), mGPUParams(gpuParams)
+		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if(params != nullptr)
 		{
@@ -17,6 +17,7 @@ namespace BansheeEngine
 
 			if(data != nullptr)
 			{
+				mMaterialParams = params;
 				mParamIndex = data->index;
 				mArraySize = data->arraySize;
 			}
@@ -36,7 +37,7 @@ namespace BansheeEngine
 			return;
 		}
 
-		mMaterialParams->setDataParam(mParamIndex + arrayIdx, value);
+		mMaterialParams->setDataParam(mParamIndex, arrayIdx, value);
 
 		if (mGPUParams != nullptr)
 		{
@@ -48,11 +49,11 @@ namespace BansheeEngine
 	template<class T>
 	T TMaterialDataParam<T, false>::get(UINT32 arrayIdx)
 	{
-		T output;
+		T output = T();
 		if (mMaterialParams == nullptr || arrayIdx >= mArraySize)
 			return output;
 
-		mMaterialParams->getDataParam(mParamIndex + arrayIdx, output);
+		mMaterialParams->getDataParam(mParamIndex, arrayIdx, output);
 		return output;
 	}
 
@@ -82,7 +83,7 @@ namespace BansheeEngine
 
 	TMaterialParamStruct<false>::TMaterialParamStruct(const String& name, const SPtr<__MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamStruct<false>>>& gpuParams)
-		:mParamIndex(0), mArraySize(0), mMaterialParams(params), mGPUParams(gpuParams)
+		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
@@ -91,6 +92,7 @@ namespace BansheeEngine
 
 			if (data != nullptr)
 			{
+				mMaterialParams = params;
 				mParamIndex = data->index;
 				mArraySize = data->arraySize;
 			}
@@ -126,6 +128,11 @@ namespace BansheeEngine
 		mMaterialParams->getStructData(mParamIndex + arrayIdx, value, sizeBytes);
 	}
 
+	UINT32 TMaterialParamStruct<false>::getElementSize() const
+	{
+		return mMaterialParams->getStructSize(mParamIndex);
+	}
+
 	TMaterialParamStruct<true>::TMaterialParamStruct(const SPtr<Vector<TGpuParamStruct<true>>>& params)
 		:mParams(params)
 	{ }
@@ -160,7 +167,7 @@ namespace BansheeEngine
 
 	TMaterialParamTexture<false>::TMaterialParamTexture(const String& name, const SPtr<__MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamTexture<false>>>& gpuParams)
-		:mParamIndex(0), mMaterialParams(params), mGPUParams(gpuParams)
+		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
@@ -168,7 +175,10 @@ namespace BansheeEngine
 				GPDT_UNKNOWN, 0);
 
 			if (data != nullptr)
+			{
+				mMaterialParams = params;
 				mParamIndex = data->index;
+			}
 		}
 	}
 
@@ -220,7 +230,7 @@ namespace BansheeEngine
 
 	TMaterialParamLoadStoreTexture<false>::TMaterialParamLoadStoreTexture(const String& name, const SPtr<__MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamLoadStoreTexture<false>>>& gpuParams)
-		:mParamIndex(0), mMaterialParams(params), mGPUParams(gpuParams)
+		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
@@ -228,7 +238,10 @@ namespace BansheeEngine
 				GPDT_UNKNOWN, 0);
 
 			if (data != nullptr)
+			{
+				mMaterialParams = params;
 				mParamIndex = data->index;
+			}
 		}
 	}
 
@@ -281,7 +294,7 @@ namespace BansheeEngine
 
 	TMaterialParamSampState<false>::TMaterialParamSampState(const String& name, const SPtr<__MaterialParams>& params, 
 		const SPtr<Vector<TGpuParamSampState<false>>>& gpuParams)
-		:mParamIndex(0), mMaterialParams(params), mGPUParams(gpuParams)
+		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
 	{
 		if (params != nullptr)
 		{
@@ -289,7 +302,10 @@ namespace BansheeEngine
 				GPDT_UNKNOWN, 0);
 
 			if (data != nullptr)
+			{
+				mMaterialParams = params;
 				mParamIndex = data->index;
+			}
 		}
 	}
 

+ 45 - 172
BansheeCore/Source/BsMaterialParams.cpp

@@ -1,30 +1,23 @@
 #include "BsMaterialParams.h"
+#include "BsProfilerCPU.h"
 
 namespace BansheeEngine
 {
 	__MaterialParams::__MaterialParams(const HShader& shader)
 	{
-		GpuParamDataType dataTypes[] = { GPDT_FLOAT1, GPDT_FLOAT2, GPDT_FLOAT3, GPDT_FLOAT4, GPDT_INT1, GPDT_INT2, GPDT_INT3,
-			GPDT_INT4, GPDT_MATRIX_2X2, GPDT_MATRIX_2X3, GPDT_MATRIX_2X4, GPDT_MATRIX_3X3, GPDT_MATRIX_3X2, GPDT_MATRIX_3X4,
-			GPDT_MATRIX_4X4, GPDT_MATRIX_4X2, GPDT_MATRIX_4X3, GPDT_COLOR, GPDT_STRUCT };
-		UINT32* dataCounts[] = { &mNumFloatParams, &mNumVec2Params, &mNumVec3Params, &mNumVec4Params, &mNumIntParams, 
-			&mNumVec2IParams, &mNumVec3IParams, &mNumVec4IParams, &mNumMat2Params, &mNumMat2x3Params, &mNumMat2x4Params, 
-			&mNumMat3Params, &mNumMat3x2Params, &mNumMat3x4Params, &mNumMat4Params, &mNumMat4x2Params, &mNumMat4x3Params, 
-			&mNumColorParams, &mNumStructParams };
+		gProfilerCPU().beginSample("Create material params");
+
+		UINT32 bufferSize = 0;
 
 		auto& dataParams = shader->getDataParams();
 		for (auto& param : dataParams)
 		{
-			for (UINT32 i = 0; i < sizeof(dataTypes); i++)
-			{
-				if (param.second.type == dataTypes[i])
-				{
-					UINT32 count = param.second.arraySize > 1 ? param.second.arraySize : 1;
+			UINT32 arraySize = param.second.arraySize > 1 ? param.second.arraySize : 1;
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)param.second.type];
+			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
+
+			bufferSize += arraySize * paramSize;
 
-					*dataCounts[i] += count;
-					break;
-				}
-			}
 		}
 
 		auto& textureParams = shader->getTextureParams();
@@ -33,49 +26,14 @@ namespace BansheeEngine
 		mNumTextureParams = (UINT32)textureParams.size();
 		mNumSamplerParams = (UINT32)samplerParams.size();
 
-		mFloatParams = mAlloc.construct<float>(mNumFloatParams);
-		mVec2Params = mAlloc.construct<Vector2>(mNumVec2Params);
-		mVec3Params = mAlloc.construct<Vector3>(mNumVec3Params);
-		mVec4Params = mAlloc.construct<Vector4>(mNumVec4Params);
-
-		mIntParams = mAlloc.construct<int>(mNumIntParams);
-		mVec2IParams = mAlloc.construct<Vector2I>(mNumVec2IParams);
-		mVec3IParams = mAlloc.construct<Vector3I>(mNumVec3IParams);
-		mVec4IParams = mAlloc.construct<Vector4I>(mNumVec4IParams);
-
-		mMat2Params = mAlloc.construct<Matrix2>(mNumMat2Params);
-		mMat2x3Params = mAlloc.construct<Matrix2x3>(mNumMat2x3Params);
-		mMat2x4Params = mAlloc.construct<Matrix2x4>(mNumMat2x4Params);
-		mMat3Params = mAlloc.construct<Matrix3>(mNumMat3Params);
-		mMat3x2Params = mAlloc.construct<Matrix3x2>(mNumMat3x2Params);
-		mMat3x4Params = mAlloc.construct<Matrix3x4>(mNumMat3x4Params);
-		mMat4Params = mAlloc.construct<Matrix4>(mNumMat4Params);
-		mMat4x2Params = mAlloc.construct<Matrix4x2>(mNumMat4x2Params);
-		mMat4x3Params = mAlloc.construct<Matrix4x3>(mNumMat4x3Params);
-
-		mColorParams = mAlloc.construct<Color>(mNumColorParams);
+		mDataParamsBuffer = mAlloc.alloc(bufferSize);
+		memset(mDataParamsBuffer, 0, bufferSize);
+
 		mStructParams = mAlloc.construct<StructParamData>(mNumStructParams);
 		mTextureParams = mAlloc.construct<TextureParamData>(mNumTextureParams);
 		mSamplerStateParams = mAlloc.construct<SamplerStatePtr>(mNumSamplerParams);
 
-		UINT32 mFloatIdx = 0;
-		UINT32 mVec2Idx = 0;
-		UINT32 mVec3Idx = 0;
-		UINT32 mVec4Idx = 0;
-		UINT32 mIntIdx = 0;
-		UINT32 mVec2IIdx = 0;
-		UINT32 mVec3IIdx = 0;
-		UINT32 mVec4IIdx = 0;
-		UINT32 mMat2Idx = 0;
-		UINT32 mMat2x3Idx = 0;
-		UINT32 mMat2x4Idx = 0;
-		UINT32 mMat3Idx = 0;
-		UINT32 mMat3x2Idx = 0;
-		UINT32 mMat3x4Idx = 0;
-		UINT32 mMat4Idx = 0;
-		UINT32 mMat4x2Idx = 0;
-		UINT32 mMat4x3Idx = 0;
-		UINT32 mColorIdx = 0;
+		UINT32 mDataBufferIdx = 0;
 		UINT32 mStructIdx = 0;
 		UINT32 mTextureIdx = 0;
 		UINT32 mSamplerIdx = 0;
@@ -88,95 +46,24 @@ namespace BansheeEngine
 			dataParam.arraySize = arraySize;
 			dataParam.type = ParamType::Data;
 			dataParam.dataType = entry.second.type;
-			dataParam.index = 0;
+			
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)dataParam.dataType];
+			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
+
+			dataParam.index = mDataBufferIdx;
+			mDataBufferIdx += arraySize * paramSize;
 
-			switch (entry.second.type)
+			if(entry.second.type == GPDT_STRUCT)
 			{
-			case GPDT_FLOAT1:
 				for (UINT32 i = 0; i < arraySize; i++)
-					mFloatParams[mFloatIdx + i] = 0.0f;
-
-				dataParam.index = mFloatIdx;
-				mFloatIdx += arraySize;
-				break;
-			case GPDT_FLOAT2:
-				dataParam.index = mVec2Idx;
-				mVec2Idx += arraySize;
-				break;
-			case GPDT_FLOAT3:
-				dataParam.index = mVec3Idx;
-				mVec3Idx += arraySize;
-				break;
-			case GPDT_FLOAT4:
-				dataParam.index = mVec4Idx;
-				mVec4Idx += arraySize;
-				break;
-			case GPDT_INT1:
-				dataParam.index = mIntIdx;
-				mIntIdx += arraySize;
-				break;
-			case GPDT_INT2:
-				dataParam.index = mVec2IIdx;
-				mVec2IIdx += arraySize;
-				break;
-			case GPDT_INT3:
-				dataParam.index = mVec3IIdx;
-				mVec3IIdx += arraySize;
-				break;
-			case GPDT_INT4:
-				dataParam.index = mVec4IIdx;
-				mVec4IIdx += arraySize;
-				break;
-			case GPDT_MATRIX_2X2:
-				dataParam.index = mMat2Idx;
-				mMat2Idx += arraySize;
-				break;
-			case GPDT_MATRIX_2X3:
-				dataParam.index = mMat2x3Idx;
-				mMat2x3Idx += arraySize;
-				break;
-			case GPDT_MATRIX_2X4:
-				dataParam.index = mMat2x4Idx;
-				mMat2x4Idx += arraySize;
-				break;
-			case GPDT_MATRIX_3X3:
-				dataParam.index = mMat3Idx;
-				mMat3Idx += arraySize;
-				break;
-			case GPDT_MATRIX_3X2:
-				dataParam.index = mMat3x2Idx;
-				mMat3x2Idx += arraySize;
-				break;
-			case GPDT_MATRIX_3X4:
-				dataParam.index = mMat3x4Idx;
-				mMat3x4Idx += arraySize;
-				break;
-			case GPDT_MATRIX_4X4:
-				dataParam.index = mMat4Idx;
-				mMat4Idx += arraySize;
-				break;
-			case GPDT_MATRIX_4X2:
-				dataParam.index = mMat4x2Idx;
-				mMat4x2Idx += arraySize;
-				break;
-			case GPDT_MATRIX_4X3:
-				dataParam.index = mMat4x3Idx;
-				mMat4x3Idx += arraySize;
-				break;
-			case GPDT_COLOR:
-				dataParam.index = mColorIdx;
-				mColorIdx += arraySize;
-				break;
-			case GPDT_STRUCT:
-			{
-				StructParamData& param = mStructParams[mStructIdx];
-				param.dataSize = entry.second.elementSize;
-				param.data = mAlloc.alloc(param.dataSize);
+				{
+					StructParamData& param = mStructParams[mStructIdx];
+					param.dataSize = entry.second.elementSize;
+					param.data = mAlloc.alloc(param.dataSize);
 
-				dataParam.index = mStructIdx;
-				mStructIdx += arraySize;
-			}
-			break;
+					dataParam.index = mStructIdx;
+					mStructIdx++;
+				}
 			}
 		}
 
@@ -206,6 +93,8 @@ namespace BansheeEngine
 
 			mSamplerIdx++;
 		}
+
+		gProfilerCPU().endSample("Create material params");
 	}
 
 	__MaterialParams::~__MaterialParams()
@@ -216,29 +105,7 @@ namespace BansheeEngine
 				mAlloc.free(mStructParams[i].data);
 		}
 
-		mAlloc.destruct(mFloatParams, mNumFloatParams);
-		mAlloc.destruct(mVec2Params, mNumVec2Params);
-		mAlloc.destruct(mVec3Params, mNumVec3Params);
-		mAlloc.destruct(mVec4Params, mNumVec4Params);
-
-		mAlloc.destruct(mIntParams, mNumIntParams);
-		mAlloc.destruct(mVec2IParams, mNumVec2IParams);
-		mAlloc.destruct(mVec3IParams, mNumVec3IParams);
-		mAlloc.destruct(mVec4IParams, mNumVec4IParams);
-
-		mAlloc.destruct(mMat2Params, mNumMat2Params);
-		mAlloc.destruct(mMat2x3Params, mNumMat2x3Params);
-		mAlloc.destruct(mMat2x4Params, mNumMat2x4Params);
-
-		mAlloc.destruct(mMat3Params, mNumMat3Params);
-		mAlloc.destruct(mMat3x2Params, mNumMat3x2Params);
-		mAlloc.destruct(mMat3x4Params, mNumMat3x4Params);
-
-		mAlloc.destruct(mMat4Params, mNumMat4Params);
-		mAlloc.destruct(mMat4x2Params, mNumMat4x2Params);
-		mAlloc.destruct(mMat4x3Params, mNumMat4x3Params);
-
-		mAlloc.destruct(mColorParams, mNumColorParams);
+		mAlloc.free(mDataParamsBuffer);
 		mAlloc.destruct(mStructParams, mNumStructParams);
 		mAlloc.destruct(mTextureParams, mNumTextureParams);
 		mAlloc.destruct(mSamplerStateParams, mNumSamplerParams);
@@ -246,7 +113,7 @@ namespace BansheeEngine
 		mAlloc.clear();
 	}
 
-	void __MaterialParams::getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx)
+	void __MaterialParams::getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const
 	{
 		const ParamData* param = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx);
 		if (param == nullptr)
@@ -264,7 +131,7 @@ namespace BansheeEngine
 		setStructData(param->index + arrayIdx, value, size);
 	}
 
-	void __MaterialParams::getTexture(const String& name, HTexture& value)
+	void __MaterialParams::getTexture(const String& name, HTexture& value) const
 	{
 		const ParamData* param = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0);
 		if (param == nullptr)
@@ -282,7 +149,7 @@ namespace BansheeEngine
 		setTexture(param->index, value);
 	}
 
-	void __MaterialParams::getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface)
+	void __MaterialParams::getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface) const
 	{
 		const ParamData* param = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0);
 		if (param == nullptr)
@@ -300,7 +167,7 @@ namespace BansheeEngine
 		setLoadStoreTexture(param->index, value, surface);
 	}
 
-	void __MaterialParams::getSamplerState(const String& name, SamplerStatePtr& value)
+	void __MaterialParams::getSamplerState(const String& name, SamplerStatePtr& value) const
 	{
 		const ParamData* param = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0);
 		if (param == nullptr)
@@ -319,7 +186,7 @@ namespace BansheeEngine
 	}
 
 	const __MaterialParams::ParamData* __MaterialParams::getParamData(const String& name, ParamType type, GpuParamDataType dataType,
-		UINT32 arrayIdx)
+		UINT32 arrayIdx) const
 	{
 		auto iterFind = mParams.find(name);
 		if (iterFind == mParams.end())
@@ -345,7 +212,7 @@ namespace BansheeEngine
 		return &param;
 	}
 
-	void __MaterialParams::getStructData(UINT32 index, void* value, UINT32 size)
+	void __MaterialParams::getStructData(UINT32 index, void* value, UINT32 size) const
 	{
 		const StructParamData& structParam = mStructParams[index];
 		if (structParam.dataSize != size)
@@ -371,7 +238,13 @@ namespace BansheeEngine
 		memcpy(structParam.data, value, structParam.dataSize);
 	}
 
-	void __MaterialParams::getTexture(UINT32 index, HTexture& value)
+	UINT32 __MaterialParams::getStructSize(UINT32 index) const
+	{
+		const StructParamData& structParam = mStructParams[index];
+		return structParam.dataSize;
+	}
+
+	void __MaterialParams::getTexture(UINT32 index, HTexture& value) const
 	{
 		TextureParamData& textureParam = mTextureParams[index];
 		value = textureParam.value;
@@ -384,7 +257,7 @@ namespace BansheeEngine
 		textureParam.isLoadStore = false;
 	}
 
-	void __MaterialParams::getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface)
+	void __MaterialParams::getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface) const
 	{
 		TextureParamData& textureParam = mTextureParams[index];
 		value = textureParam.value;
@@ -399,7 +272,7 @@ namespace BansheeEngine
 		textureParam.surface = surface;
 	}
 
-	void __MaterialParams::getSamplerState(UINT32 index, SamplerStatePtr& value)
+	void __MaterialParams::getSamplerState(UINT32 index, SamplerStatePtr& value) const
 	{
 		value = mSamplerStateParams[index];
 	}