Browse Source

Refactored material params so it can be used on both sim and core threads (in preparation of a minor Material refactor)

BearishSun 9 years ago
parent
commit
cfff49ac22

+ 1 - 1
Source/BansheeCore/Include/BsMaterial.h

@@ -840,7 +840,7 @@ namespace BansheeEngine
 	public:
 	public:
 		friend class MaterialRTTI;
 		friend class MaterialRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
+		RTTITypeBase* getRTTI() const override;
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 295 - 199
Source/BansheeCore/Include/BsMaterialParams.h

@@ -22,22 +22,11 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	/** 
-	 * Contains all parameter values set in a Material. This is similar to GpuParams which also stores parameter values,
-	 * however GpuParams are built for use on the GPU-side and don't store parameters that don't exist in a compiled GPU
-	 * program. This object on the other hand stores all parameters defined in a shader, regardless or not if they actually
-	 * exist in the GPU program. Additionally GpuParams are defined per-program (for example vertex, fragment) while this
-	 * object exists for the entire material.
-	 *
-	 * @note
-	 * This introduces redundancy as parameters stored by GpuParams and this object are duplicated. If this is an issue the
-	 * implementation can be modified to only store parameters not included in GpuParams.
-	 * @note
-	 * The reason why parameters in this class and GpuParams differ is most often compiler optimizations. If a compiler
-	 * optimizes out a variable in a GPU program we should still be able to store it, either for later when the variable
-	 * will be introduced, or for other techniques that might have that variable implemented.
-	 */
-	class BS_CORE_EXPORT MaterialParams : public IReflectable
+	struct SHADER_DATA_PARAM_DESC;
+	struct SHADER_OBJECT_PARAM_DESC;
+
+	/** Common functionality for MaterialParams and MaterialParamsCore. */
+	class BS_CORE_EXPORT MaterialParamsBase
 	{
 	{
 	public:
 	public:
 		/** Type of material parameter. */
 		/** Type of material parameter. */
@@ -64,39 +53,24 @@ namespace BansheeEngine
 			UINT32 arraySize;
 			UINT32 arraySize;
 		};
 		};
 
 
-		/** Raw data for a single structure parameter. */
-		class BS_CORE_EXPORT StructParamData : public IReflectable
-		{
-		public:
-			UINT8* data;
-			UINT32 dataSize;
-
-			friend class StructParamDataRTTI;
-			static RTTITypeBase* getRTTIStatic();
-			RTTITypeBase* getRTTI() const override;
-		};
+		/** 
+		 * Creates a new material params object and initializes enough room for parameters from the provided parameter data.
+		 */
+		MaterialParamsBase(
+			const Map<String, SHADER_DATA_PARAM_DESC>& dataParams, 
+			const Map<String, SHADER_OBJECT_PARAM_DESC>& textureParams,
+			const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferParams,
+			const Map<String, SHADER_OBJECT_PARAM_DESC>& samplerParams);
 
 
-		/** Data for a single texture parameter. */
-		class BS_CORE_EXPORT TextureParamData : public IReflectable
-		{
-		public:
-			HTexture value;
-			bool isLoadStore;
-			TextureSurface surface;
-
-			friend class TextureParamDataRTTI;
-			static RTTITypeBase* getRTTIStatic();
-			RTTITypeBase* getRTTI() const override;
-		};
+		/** Constructor for serialization use only. */
+		MaterialParamsBase() { }
 
 
-		/** Creates a new material params object and initializes enough room for parameters from the provided shader. */
-		MaterialParams(const HShader& shader);
-		~MaterialParams();
+		virtual ~MaterialParamsBase();
 
 
-		/** 
+		/**
 		 * Returns the value of a shader data parameter with the specified name at the specified array index. If the
 		 * Returns the value of a shader data parameter with the specified name at the specified array index. If the
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	arrayIdx	If the parameter is an array, index of the entry to access.
 		 * @param[in]	arrayIdx	If the parameter is an array, index of the entry to access.
 		 * @param[out]	output		If successful, value of the parameter.
 		 * @param[out]	output		If successful, value of the parameter.
@@ -120,10 +94,10 @@ namespace BansheeEngine
 			memcpy(output, &mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], sizeof(paramTypeSize));
 			memcpy(output, &mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], sizeof(paramTypeSize));
 		}
 		}
 
 
-		/** 
+		/**
 		 * Sets the value of a shader data parameter with the specified name at the specified array index. If the
 		 * Sets the value of a shader data parameter with the specified name at the specified array index. If the
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be set.
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be set.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	arrayIdx	If the parameter is an array, index of the entry to access.
 		 * @param[in]	arrayIdx	If the parameter is an array, index of the entry to access.
 		 * @param[in]	input		New value of the parameter.
 		 * @param[in]	input		New value of the parameter.
@@ -146,10 +120,176 @@ namespace BansheeEngine
 			memcpy(&mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], input, sizeof(paramTypeSize));
 			memcpy(&mDataParamsBuffer[param->index + arrayIdx * paramTypeSize], input, sizeof(paramTypeSize));
 		}
 		}
 
 
-		/** 
+		/**
+		 * Returns data about a parameter and reports an error if there is a type or size mismatch, or if the parameter
+		 * does exist.
+		 *
+		 * @param[in]	name		Name of the shader parameter.
+		 * @param[in]	type		Type of the parameter retrieve. Error will be logged if actual type of the parameter
+		 *							doesn't match.
+		 * @param[in]	dataType	Only relevant if the parameter is a data type. Determines exact data type of the parameter
+		 *							to retrieve.
+		 * @param[in]	arrayIdx	Array index of the entry to retrieve.
+		 * @param[out]	output		Object describing the parameter with an index to its data. If the parameter was not found
+		 *							this value is undefined. This value will still be valid if parameter was found but
+		 *							some other error was reported.
+		 *
+		 * @return					Success or error state of the request.
+		 */
+		GetParamResult getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx,
+			const ParamData** output) const;
+
+		/**
+		 * Logs an error that was reported by getParamData().
+		 *
+		 * @param[in]	errorCode	Information about the error.
+		 * @param[in]	name		Name of the shader parameter for which the error occurred.
+		 * @param[in]	arrayIdx	Array index for which the error occurred.
+		 */
+		void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
+
+		/**
+		 * 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 = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
+
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
+			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
+
+			assert(sizeof(output) == paramTypeSize);
+			memcpy(&output, &mDataParamsBuffer[index + arrayIdx * paramTypeSize], paramTypeSize);
+		}
+
+		/**
+		 * 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 = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
+
+			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
+			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
+
+			assert(sizeof(input) == paramTypeSize);
+			memcpy(&mDataParamsBuffer[index + arrayIdx * paramTypeSize], &input, paramTypeSize);
+		}
+
+	protected:
+		const static UINT32 STATIC_BUFFER_SIZE = 256;
+
+		UnorderedMap<String, ParamData> mParams;
+
+		UINT8* mDataParamsBuffer = nullptr;
+
+		UINT32 mDataSize = 0;
+		UINT32 mNumStructParams = 0;
+		UINT32 mNumTextureParams = 0;
+		UINT32 mNumBufferParams = 0;
+		UINT32 mNumSamplerParams = 0;
+
+		mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
+	};
+
+	/** Raw data for a single structure parameter. */
+	class BS_CORE_EXPORT MaterialParamStructDataCore
+	{
+	public:
+		UINT8* data;
+		UINT32 dataSize;
+	};
+
+	/** Raw data for a single structure parameter. */
+	class BS_CORE_EXPORT MaterialParamStructData : public IReflectable
+	{
+	public:
+		UINT8* data;
+		UINT32 dataSize;
+
+		friend class MaterialParamStructDataRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+	};
+
+	/** Data for a single texture parameter. */
+	class BS_CORE_EXPORT MaterialParamTextureDataCore
+	{
+	public:
+		SPtr<TextureCore> value;
+		bool isLoadStore;
+		TextureSurface surface;
+	};
+
+	/** Data for a single texture parameter. */
+	class BS_CORE_EXPORT MaterialParamTextureData : public IReflectable
+	{
+	public:
+		HTexture value;
+		bool isLoadStore;
+		TextureSurface surface;
+
+		friend class MaterialParamTextureDataRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+	};
+
+	/** Helper typedefs that reference types used by either core or sim thread implementation of TMaterialParams<Core>. */
+	template<bool Core> struct TMaterialParamsTypes { };
+	template<> struct TMaterialParamsTypes < false >
+	{
+		typedef GpuParams GpuParamsType;
+		typedef HTexture TextureType;
+		typedef SPtr<GpuBuffer> BufferType;
+		typedef SPtr<SamplerState> SamplerType;
+		typedef SPtr<GpuParamBlockBuffer> ParamsBufferType;
+		typedef MaterialParamStructData StructParamDataType;
+		typedef MaterialParamTextureData TextureParamDataType;
+		typedef HShader ShaderType;
+	};
+
+	template<> struct TMaterialParamsTypes < true >
+	{
+		typedef GpuParamsCore GpuParamsType;
+		typedef SPtr<TextureCore> TextureType;
+		typedef SPtr<GpuBufferCore> BufferType;
+		typedef SPtr<SamplerStateCore> SamplerType;
+		typedef SPtr<GpuParamBlockBufferCore> ParamsBufferType;
+		typedef MaterialParamStructDataCore StructParamDataType;
+		typedef MaterialParamTextureDataCore TextureParamDataType;
+		typedef SPtr<ShaderCore> ShaderType;
+	};
+
+	/** Common code that may be specialized for both MaterialParams and MaterialParamsCore. */
+	template<bool Core>
+	class BS_CORE_EXPORT TMaterialParams : public MaterialParamsBase
+	{
+	public:
+		typedef typename TMaterialParamsTypes<Core>::GpuParamsType GpuParamsType;
+		typedef typename TMaterialParamsTypes<Core>::TextureType TextureType;
+		typedef typename TMaterialParamsTypes<Core>::BufferType BufferType;
+		typedef typename TMaterialParamsTypes<Core>::SamplerType SamplerType;
+		typedef typename TMaterialParamsTypes<Core>::ParamsBufferType ParamsBufferType;
+		typedef typename TMaterialParamsTypes<Core>::ShaderType ShaderType;
+		typedef typename TMaterialParamsTypes<Core>::StructParamDataType ParamStructDataType;
+		typedef typename TMaterialParamsTypes<Core>::TextureParamDataType ParamTextureDataType;
+
+		/** Creates a new material params object and initializes enough room for parameters from the provided shader. */
+		TMaterialParams(const ShaderType& shader);
+
+		/** Constructor for serialization use only. */
+		TMaterialParams() { }
+
+		virtual ~TMaterialParams();
+
+		/**
 		 * Returns the value of a shader structure parameter with the specified name at the specified array index. If the
 		 * Returns the value of a shader structure parameter with the specified name at the specified array index. If the
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Pre-allocated buffer of @p size bytes where the value will be retrieved.
 		 * @param[out]	value		Pre-allocated buffer of @p size bytes where the value will be retrieved.
 		 * @param[in]	size		Size of the buffer into which to write the value. Must match parameter struct's size.
 		 * @param[in]	size		Size of the buffer into which to write the value. Must match parameter struct's size.
@@ -157,10 +297,10 @@ namespace BansheeEngine
 		 */
 		 */
 		void getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const;
 		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
 		 * Sets the value of a shader structure parameter with the specified name at the specified array index. If the
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
 		 * parameter name, index or type is not valid a warning will be logged and output value will not be retrieved.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	value		Buffer of @p size bytes containing the new value of the structure.
 		 * @param[in]	value		Buffer of @p size bytes containing the new value of the structure.
 		 * @param[in]	size		Size of the buffer from which to retrieve the value. Must match parameter struct's size.
 		 * @param[in]	size		Size of the buffer from which to retrieve the value. Must match parameter struct's size.
@@ -168,259 +308,215 @@ namespace BansheeEngine
 		 */
 		 */
 		void setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx);
 		void setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx);
 
 
-		/** 
-		 * Returns the value of a shader texture parameter with the specified name. If the parameter name or type is not 
+		/**
+		 * Returns the value of a shader texture parameter with the specified name. If the parameter name or type is not
 		 * valid a warning will be logged and output value will not be retrieved.
 		 * valid a warning will be logged and output value will not be retrieved.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 */
 		 */
-		void getTexture(const String& name, HTexture& value) const;
+		void getTexture(const String& name, TextureType& value) const;
 
 
-		/** 
-		 * Sets the value of a shader texture parameter with the specified name. If the parameter name or type is not 
+		/**
+		 * Sets the value of a shader texture parameter with the specified name. If the parameter name or type is not
 		 * valid a warning will be logged and output value will not be set.
 		 * valid a warning will be logged and output value will not be set.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	value		New value of the parameter.
 		 * @param[in]	value		New value of the parameter.
 		 */
 		 */
-		void setTexture(const String& name, const HTexture& value);
+		void setTexture(const String& name, const TextureType& value);
 
 
-		/** 
-		 * Returns the value of a shader load/store texture parameter with the specified name. If the parameter name or 
+		/**
+		 * Returns the value of a shader load/store texture parameter with the specified name. If the parameter name or
 		 * type is not valid a warning will be logged and output value will not be retrieved.
 		 * type is not valid a warning will be logged and output value will not be retrieved.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 * @param[out]	surface		Surface describing which part of the texture is being accessed.
 		 * @param[out]	surface		Surface describing which part of the texture is being accessed.
 		 */
 		 */
-		void getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface) const;
+		void getLoadStoreTexture(const String& name, TextureType& value, TextureSurface& surface) const;
 
 
-		/** 
-		 * Sets the value of a shader load/store texture parameter with the specified name. If the parameter name or 
+		/**
+		 * Sets the value of a shader load/store texture parameter with the specified name. If the parameter name or
 		 * type is not valid a warning will be logged and the value will not be set.
 		 * type is not valid a warning will be logged and the value will not be set.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	value		New value of the parameter.
 		 * @param[in]	value		New value of the parameter.
 		 * @param[in]	surface		Surface describing which part of the texture is being accessed.
 		 * @param[in]	surface		Surface describing which part of the texture is being accessed.
 		 */
 		 */
-		void setLoadStoreTexture(const String& name, const HTexture& value, const TextureSurface& surface);
+		void setLoadStoreTexture(const String& name, const TextureType& value, const TextureSurface& surface);
 
 
-		/** 
-		 * Returns the value of a shader buffer parameter with the specified name. If the parameter name or type is not 
+		/**
+		 * Returns the value of a shader buffer parameter with the specified name. If the parameter name or type is not
 		 * valid a warning will be logged and output value will not be retrieved.
 		 * valid a warning will be logged and output value will not be retrieved.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 */
 		 */
-		void getBuffer(const String& name, SPtr<GpuBuffer>& value) const;
+		void getBuffer(const String& name, BufferType& value) const;
 
 
-		/** 
-		 * Sets the value of a shader buffer parameter with the specified name. If the parameter name or type is not 
+		/**
+		 * Sets the value of a shader buffer parameter with the specified name. If the parameter name or type is not
 		 * valid a warning will be logged and output value will not be set.
 		 * valid a warning will be logged and output value will not be set.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	value		New value of the parameter.
 		 * @param[in]	value		New value of the parameter.
 		 */
 		 */
-		void setBuffer(const String& name, const SPtr<GpuBuffer>& value);
+		void setBuffer(const String& name, const BufferType& value);
 
 
-		/** 
-		 * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not 
+		/**
+		 * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
 		 * valid a warning will be logged and output value will not be set.
 		 * valid a warning will be logged and output value will not be set.
-		 * 
+		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 * @param[out]	value		Output value of the parameter.
 		 */
 		 */
-		void getSamplerState(const String& name, SPtr<SamplerState>& value) const;
+		void getSamplerState(const String& name, SamplerType& value) const;
 
 
-		/** 
-		 * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not 
+		/**
+		 * Sets the value of a shader sampler state parameter with the specified name. If the parameter name or type is not
 		 * valid a warning will be logged and output value will not be set.
 		 * valid a warning will be logged and output value will not be set.
-		 * 
-		 * @param[in]	name		Name of the shader parameter.
-		 * @param[in]	value		New value of the parameter.
-		 */
-		void setSamplerState(const String& name, const SPtr<SamplerState>& value);
-
-		/** 
-		 * Returns data about a parameter and reports an error if there is a type or size mismatch, or if the parameter
-		 * does exist.
 		 *
 		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	name		Name of the shader parameter.
-		 * @param[in]	type		Type of the parameter retrieve. Error will be logged if actual type of the parameter 
-		 *							doesn't match.
-		 * @param[in]	dataType	Only relevant if the parameter is a data type. Determines exact data type of the parameter
-		 *							to retrieve. 
-		 * @param[in]	arrayIdx	Array index of the entry to retrieve. 
-		 * @param[out]	output		Object describing the parameter with an index to its data. If the parameter was not found
-		 *							this value is undefined. This value will still be valid if parameter was found but
-		 *							some other error was reported.
-		 *
-		 * @return					Success or error state of the request.
+		 * @param[in]	value		New value of the parameter.
 		 */
 		 */
-		GetParamResult getParamData(const String& name, ParamType type, GpuParamDataType dataType, UINT32 arrayIdx, 
-			const ParamData** output) const;
+		void setSamplerState(const String& name, const SamplerType& value);
 
 
 		/**
 		/**
-		 * Logs an error that was reported by getParamData().
-		 *
-		 * @param[in]	errorCode	Information about the error.
-		 * @param[in]	name		Name of the shader parameter for which the error occurred.
-		 * @param[in]	arrayIdx	Array index for which the error occurred. 
-		 */
-		void reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const;
-
-		/** 
-		 * 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 = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
-
-			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
-			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
-
-			assert(sizeof(output) == paramTypeSize);
-			memcpy(&output, &mDataParamsBuffer[index + arrayIdx * paramTypeSize], paramTypeSize);
-		}
-
-		/** 
-		 * 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 = (GpuParamDataType)TGpuDataParamInfo<T>::TypeId;
-
-			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[dataType];
-			UINT32 paramTypeSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
-
-			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
 		 * 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.
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
 		void getStructData(UINT32 index, void* value, UINT32 size) const;
 		void getStructData(UINT32 index, void* value, UINT32 size) const;
 
 
-		/** 
+		/**
 		 * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
 		 * Equivalent to setStructData(const String&, UINT32, void*, UINT32) except it uses the internal parameter index
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
 		void setStructData(UINT32 index, const void* value, UINT32 size);
 		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. 
+		/**
+		 * 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;
 		UINT32 getStructSize(UINT32 index) const;
 
 
-		/** 
-		 * Equivalent to getTexture(const String&, HTexture&) except it uses the internal parameter index directly, 
+		/**
+		 * 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.
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void getTexture(UINT32 index, HTexture& value) const;
+		void getTexture(UINT32 index, TextureType& value) const;
 
 
-		/** 
-		 * Equivalent to setTexture(const String&, HTexture&) except it uses the internal parameter index directly, 
+		/**
+		 * Equivalent to setTexture(const String&, HTexture&) except it uses the internal parameter index directly,
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void setTexture(UINT32 index, const HTexture& value);
+		void setTexture(UINT32 index, const TextureType& value);
 
 
-		/** 
-		 * Equivalent to getBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly, 
+		/**
+		 * Equivalent to getBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void getBuffer(UINT32 index, SPtr<GpuBuffer>& value) const;
+		void getBuffer(UINT32 index, BufferType& value) const;
 
 
-		/** 
-		 * Equivalent to setBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly, 
+		/**
+		 * Equivalent to setBuffer(const String&, SPtr<GpuBuffer>&) except it uses the internal parameter index directly,
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 * avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void setBuffer(UINT32 index, const SPtr<GpuBuffer>& value);
+		void setBuffer(UINT32 index, const BufferType& value);
 
 
-		/** 
-		 * Equivalent to getLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal 
+		/**
+		 * 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.
 		 * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface) const;
+		void getLoadStoreTexture(UINT32 index, TextureType& value, TextureSurface& surface) const;
 
 
-		/** 
-		 * Equivalent to setLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal 
+		/**
+		 * Equivalent to setLoadStoreTexture(const String&, HTexture&, TextureSurface&) except it uses the internal
 		 * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 * parameter index directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void setLoadStoreTexture(UINT32 index, const HTexture& value, const TextureSurface& surface);
+		void setLoadStoreTexture(UINT32 index, const TextureType& value, const TextureSurface& surface);
 
 
-		/** 
-		 * Checks is a texture with the specified index a load/store texture or a normal one. Caller must guarantee the 
+		/**
+		 * Checks is a texture with the specified index a load/store texture or a normal one. Caller must guarantee the
 		 * index is valid.
 		 * index is valid.
 		 */
 		 */
 		bool getIsTextureLoadStore(UINT32 index) const;
 		bool getIsTextureLoadStore(UINT32 index) const;
 
 
-		/** 
-		 * Equivalent to getSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index 
+		/**
+		 * Equivalent to getSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void getSamplerState(UINT32 index, SPtr<SamplerState>& value) const;
+		void getSamplerState(UINT32 index, SamplerType& value) const;
 
 
-		/** 
-		 * Equivalent to setSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index 
+		/**
+		 * Equivalent to setSamplerState(const String&, SPtr<SamplerState>&) except it uses the internal parameter index
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 * directly, avoiding the name lookup. Caller must guarantee the index is valid.
 		 */
 		 */
-		void setSamplerState(UINT32 index, const SPtr<SamplerState>& value);
+		void setSamplerState(UINT32 index, const SamplerType& value);
 
 
-		/** 
-		 * Returns the default texture (one assigned when no other is provided), if available for the specified index. 
+		/**
+		 * Returns the default texture (one assigned when no other is provided), if available for the specified index.
 		 * Index is the internal parameter index and the caller must guarantee the index is valid.
 		 * Index is the internal parameter index and the caller must guarantee the index is valid.
 		 */
 		 */
-		void getDefaultTexture(UINT32 index, HTexture& value) const;
+		void getDefaultTexture(UINT32 index, TextureType& value) const;
 
 
-		/** 
+		/**
 		 * Returns the default sampler state (one assigned when no other is provided), if available for the specified index.
 		 * Returns the default sampler state (one assigned when no other is provided), if available for the specified index.
 		 * Index is the internal parameter index and the caller must guarantee the index is valid.
 		 * Index is the internal parameter index and the caller must guarantee the index is valid.
 		 */
 		 */
-		void getDefaultSamplerState(UINT32 index, SPtr<SamplerState>& value) const;
-
-	private:
-		const static UINT32 STATIC_BUFFER_SIZE = 256;
-
-		UnorderedMap<String, ParamData> mParams;
-
-		UINT8* mDataParamsBuffer = nullptr;
-		StructParamData* mStructParams = nullptr;
-		TextureParamData* mTextureParams = nullptr;
-		SPtr<GpuBuffer>* mBufferParams = nullptr;
-		SPtr<SamplerState>* mSamplerStateParams = nullptr;
-		HTexture* mDefaultTextureParams = nullptr;
-		SPtr<SamplerState>* mDefaultSamplerStateParams = nullptr;
+		void getDefaultSamplerState(UINT32 index, SamplerType& value) const;
+
+	protected:
+		ParamStructDataType* mStructParams = nullptr;
+		ParamTextureDataType* mTextureParams = nullptr;
+		BufferType* mBufferParams = nullptr;
+		SamplerType* mSamplerStateParams = nullptr;
+		TextureType* mDefaultTextureParams = nullptr;
+		SamplerType* mDefaultSamplerStateParams = nullptr;
+	};
 
 
-		UINT32 mDataSize = 0;
-		UINT32 mNumStructParams = 0;
-		UINT32 mNumTextureParams = 0;
-		UINT32 mNumBufferParams = 0;
-		UINT32 mNumSamplerParams = 0;
+	/** Core thread version of MaterialParams. */
+	class BS_CORE_EXPORT MaterialParamsCore : public TMaterialParams<true>
+	{
+	public:
+		/** @copydoc TMaterialParams<Core>::TMaterialParams */
+		MaterialParamsCore(const SPtr<ShaderCore>& shader);
+	};
 
 
-		mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
+	/** 
+	 * Contains all parameter values set in a Material. This is similar to GpuParams which also stores parameter values,
+	 * however GpuParams are built for use on the GPU-side and don't store parameters that don't exist in a compiled GPU
+	 * program. This object on the other hand stores all parameters defined in a shader, regardless or not if they actually
+	 * exist in the GPU program. Additionally GpuParams are defined per-program (for example vertex, fragment) while this
+	 * object exists for the entire material.
+	 *
+	 * @note
+	 * This introduces redundancy as parameters stored by GpuParams and this object are duplicated. If this is an issue the
+	 * implementation can be modified to only store parameters not included in GpuParams.
+	 * @note
+	 * The reason why parameters in this class and GpuParams differ is most often compiler optimizations. If a compiler
+	 * optimizes out a variable in a GPU program we should still be able to store it, either for later when the variable
+	 * will be introduced, or for other techniques that might have that variable implemented.
+	 */
+	class BS_CORE_EXPORT MaterialParams : public IReflectable, public TMaterialParams<false>
+	{
+	public:
+		/** @copydoc TMaterialParams<Core>::TMaterialParams */
+		MaterialParams(const HShader& shader);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		/************************************************************************/
-
 	public:
 	public:
 		MaterialParams() { } // Only for serialization
 		MaterialParams() { } // Only for serialization
 
 
 		friend class MaterialParamsRTTI;
 		friend class MaterialParamsRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
+		RTTITypeBase* getRTTI() const override;
 	};
 	};
 
 
 	/** @cond SPECIALIZATIONS */
 	/** @cond SPECIALIZATIONS */
-	BS_ALLOW_MEMCPY_SERIALIZATION(MaterialParams::ParamData);
+	BS_ALLOW_MEMCPY_SERIALIZATION(MaterialParamsBase::ParamData);
 	/** @endcond */
 	/** @endcond */
 
 
 	/** @} */
 	/** @} */

+ 24 - 30
Source/BansheeCore/Include/BsMaterialParamsRTTI.h

@@ -15,24 +15,18 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	class BS_CORE_EXPORT TextureParamDataRTTI : public RTTIType<MaterialParams::TextureParamData, IReflectable, TextureParamDataRTTI>
+	class BS_CORE_EXPORT MaterialParamTextureDataRTTI : public RTTIType<MaterialParamTextureData, IReflectable, MaterialParamTextureDataRTTI>
 	{
 	{
 	public:
 	public:
-		HTexture& getTexture(MaterialParams::TextureParamData* obj) { return obj->value; }
-		void setTexture(MaterialParams::TextureParamData* obj, HTexture& value) { obj->value = value; }
-
-		bool& getIsLoadStore(MaterialParams::TextureParamData* obj) { return obj->isLoadStore; }
-		void setIsLoadStore(MaterialParams::TextureParamData* obj, bool& value) { obj->isLoadStore = value; }
-
-		TextureSurface& getSurface(MaterialParams::TextureParamData* obj) { return obj->surface; }
-		void setSurface(MaterialParams::TextureParamData* obj, TextureSurface& value) { obj->surface = value; }
-
-		TextureParamDataRTTI()
-		{
-			addReflectableField("texture", 0, &TextureParamDataRTTI::getTexture, &TextureParamDataRTTI::setTexture);
-			addPlainField("isLoadStore", 1, &TextureParamDataRTTI::getIsLoadStore, &TextureParamDataRTTI::setIsLoadStore);
-			addPlainField("surface", 2, &TextureParamDataRTTI::getSurface, &TextureParamDataRTTI::setSurface);
-		}
+		BS_BEGIN_RTTI_MEMBERS
+			BS_RTTI_MEMBER_REFL(value, 0)
+			BS_RTTI_MEMBER_PLAIN(isLoadStore, 1)
+			BS_RTTI_MEMBER_PLAIN(surface, 2)
+		BS_END_RTTI_MEMBERS
+		
+		MaterialParamTextureDataRTTI()
+			:mInitMembers(this)
+		{ }
 
 
 		const String& getRTTIName() override
 		const String& getRTTIName() override
 		{
 		{
@@ -47,21 +41,21 @@ namespace BansheeEngine
 
 
 		SPtr<IReflectable> newRTTIObject() override
 		SPtr<IReflectable> newRTTIObject() override
 		{
 		{
-			return bs_shared_ptr_new<MaterialParams::TextureParamData>();
+			return bs_shared_ptr_new<MaterialParamTextureData>();
 		}
 		}
 	};
 	};
 
 
-	class BS_CORE_EXPORT StructParamDataRTTI : public RTTIType<MaterialParams::StructParamData, IReflectable, StructParamDataRTTI>
+	class BS_CORE_EXPORT MaterialParamStructDataRTTI : public RTTIType<MaterialParamStructData, IReflectable, MaterialParamStructDataRTTI>
 	{
 	{
 	public:
 	public:
-		SPtr<DataStream> getDataBuffer(MaterialParams::StructParamData* obj, UINT32& size)
+		SPtr<DataStream> getDataBuffer(MaterialParamStructData* obj, UINT32& size)
 		{
 		{
 			size = obj->dataSize;
 			size = obj->dataSize;
 
 
 			return bs_shared_ptr_new<MemoryDataStream>(obj->data, obj->dataSize, false);
 			return bs_shared_ptr_new<MemoryDataStream>(obj->data, obj->dataSize, false);
 		}
 		}
 
 
-		void setDataBuffer(MaterialParams::StructParamData* obj, const SPtr<DataStream>& value, UINT32 size)
+		void setDataBuffer(MaterialParamStructData* obj, const SPtr<DataStream>& value, UINT32 size)
 		{
 		{
 			obj->data = (UINT8*)bs_alloc(size);
 			obj->data = (UINT8*)bs_alloc(size);
 			value->read(obj->data, size);
 			value->read(obj->data, size);
@@ -69,9 +63,9 @@ namespace BansheeEngine
 			obj->dataSize = size;
 			obj->dataSize = size;
 		}
 		}
 
 
-		StructParamDataRTTI()
+		MaterialParamStructDataRTTI()
 		{
 		{
-			addDataBlockField("dataBuffer", 0, &StructParamDataRTTI::getDataBuffer, &StructParamDataRTTI::setDataBuffer, 0);
+			addDataBlockField("dataBuffer", 0, &MaterialParamStructDataRTTI::getDataBuffer, &MaterialParamStructDataRTTI::setDataBuffer, 0);
 		}
 		}
 
 
 		const String& getRTTIName() override
 		const String& getRTTIName() override
@@ -87,7 +81,7 @@ namespace BansheeEngine
 
 
 		SPtr<IReflectable> newRTTIObject() override
 		SPtr<IReflectable> newRTTIObject() override
 		{
 		{
-			return bs_shared_ptr_new<MaterialParams::StructParamData>();
+			return bs_shared_ptr_new<MaterialParamStructData>();
 		}
 		}
 	};
 	};
 
 
@@ -137,10 +131,10 @@ namespace BansheeEngine
 			obj->mDataSize = size;
 			obj->mDataSize = size;
 		}
 		}
 
 
-		MaterialParams::StructParamData& getStructParam(MaterialParams* obj, UINT32 idx) { return obj->mStructParams[idx]; }
-		void setStructParam(MaterialParams* obj, UINT32 idx, MaterialParams::StructParamData& param)
+		MaterialParamStructData& getStructParam(MaterialParams* obj, UINT32 idx) { return obj->mStructParams[idx]; }
+		void setStructParam(MaterialParams* obj, UINT32 idx, MaterialParamStructData& param)
 		{
 		{
-			MaterialParams::StructParamData& newStructParam = obj->mStructParams[idx];
+			MaterialParamStructData& newStructParam = obj->mStructParams[idx];
 			newStructParam.data = (UINT8*)obj->mAlloc.alloc(param.dataSize);
 			newStructParam.data = (UINT8*)obj->mAlloc.alloc(param.dataSize);
 			memcpy(newStructParam.data, param.data, param.dataSize);
 			memcpy(newStructParam.data, param.data, param.dataSize);
 			newStructParam.dataSize = param.dataSize;
 			newStructParam.dataSize = param.dataSize;
@@ -152,16 +146,16 @@ namespace BansheeEngine
 		void setStructArraySize(MaterialParams* obj, UINT32 size)
 		void setStructArraySize(MaterialParams* obj, UINT32 size)
 		{
 		{
 			obj->mNumStructParams = size;
 			obj->mNumStructParams = size;
-			obj->mStructParams = obj->mAlloc.construct<MaterialParams::StructParamData>(size);
+			obj->mStructParams = obj->mAlloc.construct<MaterialParamStructData>(size);
 		}
 		}
 
 
-		MaterialParams::TextureParamData& getTextureParam(MaterialParams* obj, UINT32 idx) { return obj->mTextureParams[idx]; }
-		void setTextureParam(MaterialParams* obj, UINT32 idx, MaterialParams::TextureParamData& param) { obj->mTextureParams[idx] = param; }
+		MaterialParamTextureData& getTextureParam(MaterialParams* obj, UINT32 idx) { return obj->mTextureParams[idx]; }
+		void setTextureParam(MaterialParams* obj, UINT32 idx, MaterialParamTextureData& param) { obj->mTextureParams[idx] = param; }
 		UINT32 getTextureArraySize(MaterialParams* obj) { return (UINT32)obj->mNumTextureParams; }
 		UINT32 getTextureArraySize(MaterialParams* obj) { return (UINT32)obj->mNumTextureParams; }
 		void setTextureArraySize(MaterialParams* obj, UINT32 size)
 		void setTextureArraySize(MaterialParams* obj, UINT32 size)
 		{
 		{
 			obj->mNumTextureParams = size;
 			obj->mNumTextureParams = size;
-			obj->mTextureParams = obj->mAlloc.construct<MaterialParams::TextureParamData>(size);
+			obj->mTextureParams = obj->mAlloc.construct<MaterialParamTextureData>(size);
 		}
 		}
 
 
 		SPtr<SamplerState> getSamplerStateParam(MaterialParams* obj, UINT32 idx) { return obj->mSamplerStateParams[idx]; }
 		SPtr<SamplerState> getSamplerStateParam(MaterialParams* obj, UINT32 idx) { return obj->mSamplerStateParams[idx]; }

+ 196 - 127
Source/BansheeCore/Source/BsMaterialParams.cpp

@@ -6,11 +6,14 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	MaterialParams::MaterialParams(const HShader& shader)
+	MaterialParamsBase::MaterialParamsBase(
+		const Map<String, SHADER_DATA_PARAM_DESC>& dataParams,
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& textureParams,
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferParams,
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& samplerParams)
 	{
 	{
 		mDataSize = 0;
 		mDataSize = 0;
 
 
-		auto& dataParams = shader->getDataParams();
 		for (auto& param : dataParams)
 		for (auto& param : dataParams)
 		{
 		{
 			UINT32 arraySize = param.second.arraySize > 1 ? param.second.arraySize : 1;
 			UINT32 arraySize = param.second.arraySize > 1 ? param.second.arraySize : 1;
@@ -18,29 +21,16 @@ namespace BansheeEngine
 			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 
 
 			mDataSize += arraySize * paramSize;
 			mDataSize += arraySize * paramSize;
-
 		}
 		}
 
 
-		auto& textureParams = shader->getTextureParams();
-		auto& bufferParams = shader->getBufferParams();
-		auto& samplerParams = shader->getSamplerParams();
-
 		mNumTextureParams = (UINT32)textureParams.size();
 		mNumTextureParams = (UINT32)textureParams.size();
 		mNumBufferParams = (UINT32)bufferParams.size();
 		mNumBufferParams = (UINT32)bufferParams.size();
 		mNumSamplerParams = (UINT32)samplerParams.size();
 		mNumSamplerParams = (UINT32)samplerParams.size();
 
 
 		mDataParamsBuffer = mAlloc.alloc(mDataSize);
 		mDataParamsBuffer = mAlloc.alloc(mDataSize);
 		memset(mDataParamsBuffer, 0, mDataSize);
 		memset(mDataParamsBuffer, 0, mDataSize);
-
-		mStructParams = mAlloc.construct<StructParamData>(mNumStructParams);
-		mTextureParams = mAlloc.construct<TextureParamData>(mNumTextureParams);
-		mBufferParams = mAlloc.construct<SPtr<GpuBuffer>>(mNumBufferParams);
-		mSamplerStateParams = mAlloc.construct<SPtr<SamplerState>>(mNumSamplerParams);
-		mDefaultTextureParams = mAlloc.construct<HTexture>(mNumTextureParams);
-		mDefaultSamplerStateParams = mAlloc.construct<SPtr<SamplerState>>(mNumSamplerParams);
-
+		
 		UINT32 dataBufferIdx = 0;
 		UINT32 dataBufferIdx = 0;
-		UINT32 structIdx = 0;
 		UINT32 textureIdx = 0;
 		UINT32 textureIdx = 0;
 		UINT32 bufferIdx = 0;
 		UINT32 bufferIdx = 0;
 		UINT32 samplerIdx = 0;
 		UINT32 samplerIdx = 0;
@@ -53,25 +43,12 @@ namespace BansheeEngine
 			dataParam.arraySize = arraySize;
 			dataParam.arraySize = arraySize;
 			dataParam.type = ParamType::Data;
 			dataParam.type = ParamType::Data;
 			dataParam.dataType = entry.second.type;
 			dataParam.dataType = entry.second.type;
-			
+
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)dataParam.dataType];
 			const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)dataParam.dataType];
 			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 			UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
 
 
 			dataParam.index = dataBufferIdx;
 			dataParam.index = dataBufferIdx;
 			dataBufferIdx += arraySize * paramSize;
 			dataBufferIdx += arraySize * paramSize;
-
-			if(entry.second.type == GPDT_STRUCT)
-			{
-				for (UINT32 i = 0; i < arraySize; i++)
-				{
-					StructParamData& param = mStructParams[structIdx];
-					param.dataSize = entry.second.elementSize;
-					param.data = mAlloc.alloc(param.dataSize);
-
-					dataParam.index = structIdx;
-					structIdx++;
-				}
-			}
 		}
 		}
 
 
 		for (auto& entry : textureParams)
 		for (auto& entry : textureParams)
@@ -83,12 +60,6 @@ namespace BansheeEngine
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.index = textureIdx;
 			dataParam.index = textureIdx;
 
 
-			TextureParamData& param = mTextureParams[textureIdx];
-			param.isLoadStore = false;
-
-			if (entry.second.defaultValueIdx != (UINT32)-1)
-				mDefaultTextureParams[textureIdx] = shader->getDefaultTexture(entry.second.defaultValueIdx);
-
 			textureIdx++;
 			textureIdx++;
 		}
 		}
 
 
@@ -113,14 +84,137 @@ namespace BansheeEngine
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.dataType = GPDT_UNKNOWN;
 			dataParam.index = samplerIdx;
 			dataParam.index = samplerIdx;
 
 
+			samplerIdx++;
+		}
+	}
+
+	MaterialParamsBase::~MaterialParamsBase()
+	{
+		mAlloc.free(mDataParamsBuffer);
+		
+		mAlloc.clear();
+	}
+
+	MaterialParamsBase::GetParamResult MaterialParamsBase::getParamData(const String& name, ParamType type, GpuParamDataType dataType,
+		UINT32 arrayIdx, const ParamData** output) const
+	{
+		auto iterFind = mParams.find(name);
+		if (iterFind == mParams.end())
+			return GetParamResult::NotFound;
+
+		const ParamData& param = iterFind->second;
+		*output = &param;
+
+		if (param.type != type || (type == ParamType::Data && param.dataType != dataType))
+			return GetParamResult::InvalidType;
+
+		if (arrayIdx >= param.arraySize)
+			return GetParamResult::IndexOutOfBounds;
+
+		return GetParamResult::Success;
+	}
+
+	void MaterialParamsBase::reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const
+	{
+		switch (errorCode)
+		{
+		case GetParamResult::NotFound:
+			LOGWRN("Material doesn't have a parameter named " + name + ".");
+			break;
+		case GetParamResult::InvalidType:
+			LOGWRN("Parameter \"" + name + "\" is not of the requested type.");
+			break;
+		case GetParamResult::IndexOutOfBounds:
+			LOGWRN("Parameter \"" + name + "\" array index " + toString(arrayIdx) + " out of range.");
+			break;
+		default:
+			break;
+		}
+	}
+
+	RTTITypeBase* MaterialParamStructData::getRTTIStatic()
+	{
+		return MaterialParamStructDataRTTI::instance();
+	}
+
+	RTTITypeBase* MaterialParamStructData::getRTTI() const
+	{
+		return getRTTIStatic();
+	}
+
+	RTTITypeBase* MaterialParamTextureData::getRTTIStatic()
+	{
+		return MaterialParamTextureDataRTTI::instance();
+	}
+
+	RTTITypeBase* MaterialParamTextureData::getRTTI() const
+	{
+		return getRTTIStatic();
+	}
+
+	template<bool Core>
+	TMaterialParams<Core>::TMaterialParams(const ShaderType& shader)
+		:MaterialParamsBase(
+			shader->getDataParams(),
+			shader->getTextureParams(),
+			shader->getBufferParams(),
+			shader->getSamplerParams())
+	{
+		auto& dataParams = shader->getDataParams();
+		auto& textureParams = shader->getTextureParams();
+		auto& bufferParams = shader->getBufferParams();
+		auto& samplerParams = shader->getSamplerParams();
+
+		mStructParams = mAlloc.construct<ParamStructDataType>(mNumStructParams);
+		mTextureParams = mAlloc.construct<ParamTextureDataType>(mNumTextureParams);
+		mBufferParams = mAlloc.construct<BufferType>(mNumBufferParams);
+		mSamplerStateParams = mAlloc.construct<SamplerType>(mNumSamplerParams);
+		mDefaultTextureParams = mAlloc.construct<TextureType>(mNumTextureParams);
+		mDefaultSamplerStateParams = mAlloc.construct<SamplerType>(mNumSamplerParams);
+
+		UINT32 structIdx = 0;
+		UINT32 textureIdx = 0;
+		UINT32 bufferIdx = 0;
+		UINT32 samplerIdx = 0;
+
+		for (auto& entry : dataParams)
+		{
+			if(entry.second.type == GPDT_STRUCT)
+			{
+				UINT32 arraySize = entry.second.arraySize > 1 ? entry.second.arraySize : 1;
+				for (UINT32 i = 0; i < arraySize; i++)
+				{
+					ParamStructDataType& param = mStructParams[structIdx];
+					param.dataSize = entry.second.elementSize;
+					param.data = mAlloc.alloc(param.dataSize);
+
+					structIdx++;
+				}
+			}
+		}
+
+		for (auto& entry : textureParams)
+		{
+			ParamTextureDataType& param = mTextureParams[textureIdx];
+			param.isLoadStore = false;
+
 			if (entry.second.defaultValueIdx != (UINT32)-1)
 			if (entry.second.defaultValueIdx != (UINT32)-1)
-				mDefaultSamplerStateParams[textureIdx] = shader->getDefaultSampler(entry.second.defaultValueIdx);
+				mDefaultTextureParams[textureIdx] = shader->getDefaultTexture(entry.second.defaultValueIdx);
+
+			textureIdx++;
+		}
+
+		for (auto& entry : samplerParams)
+		{
+			if (entry.second.defaultValueIdx != (UINT32)-1)
+				mDefaultSamplerStateParams[samplerIdx] = shader->getDefaultSampler(entry.second.defaultValueIdx);
 
 
 			samplerIdx++;
 			samplerIdx++;
 		}
 		}
 	}
 	}
 
 
-	MaterialParams::~MaterialParams()
+	template<bool Core>
+	TMaterialParams<Core>::~TMaterialParams()
 	{
 	{
 		if (mStructParams != nullptr)
 		if (mStructParams != nullptr)
 		{
 		{
@@ -128,7 +222,6 @@ namespace BansheeEngine
 				mAlloc.free(mStructParams[i].data);
 				mAlloc.free(mStructParams[i].data);
 		}
 		}
 
 
-		mAlloc.free(mDataParamsBuffer);
 		mAlloc.destruct(mStructParams, mNumStructParams);
 		mAlloc.destruct(mStructParams, mNumStructParams);
 		mAlloc.destruct(mTextureParams, mNumTextureParams);
 		mAlloc.destruct(mTextureParams, mNumTextureParams);
 		mAlloc.destruct(mBufferParams, mNumBufferParams);
 		mAlloc.destruct(mBufferParams, mNumBufferParams);
@@ -139,11 +232,10 @@ namespace BansheeEngine
 
 
 		if (mDefaultSamplerStateParams != nullptr)
 		if (mDefaultSamplerStateParams != nullptr)
 			mAlloc.destruct(mDefaultSamplerStateParams, mNumSamplerParams);
 			mAlloc.destruct(mDefaultSamplerStateParams, mNumSamplerParams);
-
-		mAlloc.clear();
 	}
 	}
 
 
-	void MaterialParams::getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const
+	template<bool Core>
+	void TMaterialParams<Core>::getStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx) const
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx, &param);
 		GetParamResult result = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx, &param);
@@ -156,7 +248,8 @@ namespace BansheeEngine
 		getStructData(param->index + arrayIdx, value, size);
 		getStructData(param->index + arrayIdx, value, size);
 	}
 	}
 
 
-	void MaterialParams::setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx)
+	template<bool Core>
+	void TMaterialParams<Core>::setStructData(const String& name, const void* value, UINT32 size, UINT32 arrayIdx)
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx, &param);
 		GetParamResult result = getParamData(name, ParamType::Data, GPDT_STRUCT, arrayIdx, &param);
@@ -169,7 +262,8 @@ namespace BansheeEngine
 		setStructData(param->index + arrayIdx, value, size);
 		setStructData(param->index + arrayIdx, value, size);
 	}
 	}
 
 
-	void MaterialParams::getTexture(const String& name, HTexture& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getTexture(const String& name, TextureType& value) const
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
@@ -182,7 +276,8 @@ namespace BansheeEngine
 		getTexture(param->index, value);
 		getTexture(param->index, value);
 	}
 	}
 
 
-	void MaterialParams::setTexture(const String& name, const HTexture& value)
+	template<bool Core>
+	void TMaterialParams<Core>::setTexture(const String& name, const TextureType& value)
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
@@ -195,7 +290,8 @@ namespace BansheeEngine
 		setTexture(param->index, value);
 		setTexture(param->index, value);
 	}
 	}
 
 
-	void MaterialParams::getLoadStoreTexture(const String& name, HTexture& value, TextureSurface& surface) const
+	template<bool Core>
+	void TMaterialParams<Core>::getLoadStoreTexture(const String& name, TextureType& value, TextureSurface& surface) const
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
@@ -208,7 +304,8 @@ namespace BansheeEngine
 		getLoadStoreTexture(param->index, value, surface);
 		getLoadStoreTexture(param->index, value, surface);
 	}
 	}
 
 
-	void MaterialParams::setLoadStoreTexture(const String& name, const HTexture& value, const TextureSurface& surface)
+	template<bool Core>
+	void TMaterialParams<Core>::setLoadStoreTexture(const String& name, const TextureType& value, const TextureSurface& surface)
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Texture, GPDT_UNKNOWN, 0, &param);
@@ -221,7 +318,8 @@ namespace BansheeEngine
 		setLoadStoreTexture(param->index, value, surface);
 		setLoadStoreTexture(param->index, value, surface);
 	}
 	}
 
 
-	void MaterialParams::getBuffer(const String& name, SPtr<GpuBuffer>& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getBuffer(const String& name, BufferType& value) const
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Buffer, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Buffer, GPDT_UNKNOWN, 0, &param);
@@ -234,7 +332,8 @@ namespace BansheeEngine
 		getBuffer(param->index, value);
 		getBuffer(param->index, value);
 	}
 	}
 
 
-	void MaterialParams::setBuffer(const String& name, const SPtr<GpuBuffer>& value)
+	template<bool Core>
+	void TMaterialParams<Core>::setBuffer(const String& name, const BufferType& value)
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Buffer, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Buffer, GPDT_UNKNOWN, 0, &param);
@@ -247,7 +346,8 @@ namespace BansheeEngine
 		setBuffer(param->index, value);
 		setBuffer(param->index, value);
 	}
 	}
 
 
-	void MaterialParams::getSamplerState(const String& name, SPtr<SamplerState>& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getSamplerState(const String& name, SamplerType& value) const
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0, &param);
@@ -260,7 +360,8 @@ namespace BansheeEngine
 		getSamplerState(param->index, value);
 		getSamplerState(param->index, value);
 	}
 	}
 
 
-	void MaterialParams::setSamplerState(const String& name, const SPtr<SamplerState>& value)
+	template<bool Core>
+	void TMaterialParams<Core>::setSamplerState(const String& name, const SamplerType& value)
 	{
 	{
 		const ParamData* param = nullptr;
 		const ParamData* param = nullptr;
 		GetParamResult result = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0, &param);
 		GetParamResult result = getParamData(name, ParamType::Sampler, GPDT_UNKNOWN, 0, &param);
@@ -273,46 +374,10 @@ namespace BansheeEngine
 		setSamplerState(param->index, value);
 		setSamplerState(param->index, value);
 	}
 	}
 
 
-	MaterialParams::GetParamResult MaterialParams::getParamData(const String& name, ParamType type, GpuParamDataType dataType,
-		UINT32 arrayIdx, const ParamData** output) const
-	{
-		auto iterFind = mParams.find(name);
-		if (iterFind == mParams.end())
-			return GetParamResult::NotFound;
-
-		const ParamData& param = iterFind->second;
-		*output = &param;
-
-		if (param.type != type || (type == ParamType::Data && param.dataType != dataType))
-			return GetParamResult::InvalidType;
-
-		if (arrayIdx >= param.arraySize)
-			return GetParamResult::IndexOutOfBounds;
-
-		return GetParamResult::Success;
-	}
-
-	void MaterialParams::reportGetParamError(GetParamResult errorCode, const String& name, UINT32 arrayIdx) const
+	template<bool Core>
+	void TMaterialParams<Core>::getStructData(UINT32 index, void* value, UINT32 size) const
 	{
 	{
-		switch(errorCode)
-		{
-		case GetParamResult::NotFound:
-			LOGWRN("Material doesn't have a parameter named " + name + ".");
-			break;
-		case GetParamResult::InvalidType:
-			LOGWRN("Parameter \"" + name + "\" is not of the requested type.");
-			break;
-		case GetParamResult::IndexOutOfBounds:
-			LOGWRN("Parameter \"" + name + "\" array index " + toString(arrayIdx) + " out of range.");
-			break;
-		default:
-			break;
-		}
-	}
-
-	void MaterialParams::getStructData(UINT32 index, void* value, UINT32 size) const
-	{
-		const StructParamData& structParam = mStructParams[index];
+		const ParamStructDataType& structParam = mStructParams[index];
 		if (structParam.dataSize != size)
 		if (structParam.dataSize != size)
 		{
 		{
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
@@ -323,9 +388,10 @@ namespace BansheeEngine
 		memcpy(value, structParam.data, structParam.dataSize);
 		memcpy(value, structParam.data, structParam.dataSize);
 	}
 	}
 
 
-	void MaterialParams::setStructData(UINT32 index, const void* value, UINT32 size)
+	template<bool Core>
+	void TMaterialParams<Core>::setStructData(UINT32 index, const void* value, UINT32 size)
 	{
 	{
-		const StructParamData& structParam = mStructParams[index];
+		const ParamStructDataType& structParam = mStructParams[index];
 		if (structParam.dataSize != size)
 		if (structParam.dataSize != size)
 		{
 		{
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
 			LOGWRN("Size mismatch when writing to a struct. Provided size was " + toString(size) + " bytes but the "
@@ -336,94 +402,97 @@ namespace BansheeEngine
 		memcpy(structParam.data, value, structParam.dataSize);
 		memcpy(structParam.data, value, structParam.dataSize);
 	}
 	}
 
 
-	UINT32 MaterialParams::getStructSize(UINT32 index) const
+	template<bool Core>
+	UINT32 TMaterialParams<Core>::getStructSize(UINT32 index) const
 	{
 	{
-		const StructParamData& structParam = mStructParams[index];
+		const ParamStructDataType& structParam = mStructParams[index];
 		return structParam.dataSize;
 		return structParam.dataSize;
 	}
 	}
 
 
-	void MaterialParams::getTexture(UINT32 index, HTexture& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getTexture(UINT32 index, TextureType& value) const
 	{
 	{
-		TextureParamData& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[index];
 		value = textureParam.value;
 		value = textureParam.value;
 	}
 	}
-
-	void MaterialParams::setTexture(UINT32 index, const HTexture& value)
+	
+	template<bool Core>
+	void TMaterialParams<Core>::setTexture(UINT32 index, const TextureType& value)
 	{
 	{
-		TextureParamData& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[index];
 		textureParam.value = value;
 		textureParam.value = value;
 		textureParam.isLoadStore = false;
 		textureParam.isLoadStore = false;
 	}
 	}
 
 
-	void MaterialParams::getBuffer(UINT32 index, SPtr<GpuBuffer>& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getBuffer(UINT32 index, BufferType& value) const
 	{
 	{
 		value = mBufferParams[index];
 		value = mBufferParams[index];
 	}
 	}
 
 
-	void MaterialParams::setBuffer(UINT32 index, const SPtr<GpuBuffer>& value)
+	template<bool Core>
+	void TMaterialParams<Core>::setBuffer(UINT32 index, const BufferType& value)
 	{
 	{
 		mBufferParams[index] = value;
 		mBufferParams[index] = value;
 	}
 	}
 
 
-	void MaterialParams::getLoadStoreTexture(UINT32 index, HTexture& value, TextureSurface& surface) const
+	template<bool Core>
+	void TMaterialParams<Core>::getLoadStoreTexture(UINT32 index, TextureType& value, TextureSurface& surface) const
 	{
 	{
-		TextureParamData& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[index];
 		value = textureParam.value;
 		value = textureParam.value;
 		surface = textureParam.surface;
 		surface = textureParam.surface;
 	}
 	}
 
 
-	void MaterialParams::setLoadStoreTexture(UINT32 index, const HTexture& value, const TextureSurface& surface)
+	template<bool Core>
+	void TMaterialParams<Core>::setLoadStoreTexture(UINT32 index, const TextureType& value, const TextureSurface& surface)
 	{
 	{
-		TextureParamData& textureParam = mTextureParams[index];
+		ParamTextureDataType& textureParam = mTextureParams[index];
 		textureParam.value = value;
 		textureParam.value = value;
 		textureParam.isLoadStore = true;
 		textureParam.isLoadStore = true;
 		textureParam.surface = surface;
 		textureParam.surface = surface;
 	}
 	}
 
 
-	bool MaterialParams::getIsTextureLoadStore(UINT32 index) const
+	template<bool Core>
+	bool TMaterialParams<Core>::getIsTextureLoadStore(UINT32 index) const
 	{
 	{
 		return mTextureParams[index].isLoadStore;
 		return mTextureParams[index].isLoadStore;
 	}
 	}
 
 
-	void MaterialParams::getSamplerState(UINT32 index, SPtr<SamplerState>& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getSamplerState(UINT32 index, SamplerType& value) const
 	{
 	{
 		value = mSamplerStateParams[index];
 		value = mSamplerStateParams[index];
 	}
 	}
 
 
-	void MaterialParams::setSamplerState(UINT32 index, const SPtr<SamplerState>& value)
+	template<bool Core>
+	void TMaterialParams<Core>::setSamplerState(UINT32 index, const SamplerType& value)
 	{
 	{
 		mSamplerStateParams[index] = value;
 		mSamplerStateParams[index] = value;
 	}
 	}
 
 
-	void MaterialParams::getDefaultTexture(UINT32 index, HTexture& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getDefaultTexture(UINT32 index, TextureType& value) const
 	{
 	{
 		value = mDefaultTextureParams[index];
 		value = mDefaultTextureParams[index];
 	}
 	}
 
 
-	void MaterialParams::getDefaultSamplerState(UINT32 index, SPtr<SamplerState>& value) const
+	template<bool Core>
+	void TMaterialParams<Core>::getDefaultSamplerState(UINT32 index, SamplerType& value) const
 	{
 	{
 		value = mDefaultSamplerStateParams[index];
 		value = mDefaultSamplerStateParams[index];
 	}
 	}
 
 
-	RTTITypeBase* MaterialParams::TextureParamData::getRTTIStatic()
-	{
-		return TextureParamDataRTTI::instance();
-	}
+	template class TMaterialParams<true>;
+	template class TMaterialParams<false>;
 
 
-	RTTITypeBase* MaterialParams::TextureParamData::getRTTI() const
-	{
-		return getRTTIStatic();
-	}
-
-	RTTITypeBase* MaterialParams::StructParamData::getRTTIStatic()
-	{
-		return StructParamDataRTTI::instance();
-	}
+	MaterialParamsCore::MaterialParamsCore(const SPtr<ShaderCore>& shader)
+		:TMaterialParams(shader)
+	{ }
 
 
-	RTTITypeBase* MaterialParams::StructParamData::getRTTI() const
-	{
-		return getRTTIStatic();
-	}
+	MaterialParams::MaterialParams(const HShader& shader)
+		:TMaterialParams(shader)
+	{ }
 
 
 	RTTITypeBase* MaterialParams::getRTTIStatic()
 	RTTITypeBase* MaterialParams::getRTTIStatic()
 	{
 	{