Browse Source

More work on Material refactor. Moved template implementations to source files for better clarity.

Marko Pintera 11 years ago
parent
commit
5251cd9fa3

+ 1 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -156,6 +156,7 @@ namespace BansheeEngine
 	class PassCore;
 	class PassCore;
 	class TechniqueCore;
 	class TechniqueCore;
 	class MaterialCore;
 	class MaterialCore;
+	class GpuProgramCore;
 	// Asset import
 	// Asset import
 	class SpecificImporter;
 	class SpecificImporter;
 	class Importer;
 	class Importer;

+ 88 - 471
BansheeCore/Include/BsGpuParam.h

@@ -1,10 +1,6 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
-#include "BsGpuParamDesc.h"
-#include "BsGpuParamBlockBuffer.h"
-#include "BsDebug.h"
-#include "BsException.h"
 #include "BsVector2.h"
 #include "BsVector2.h"
 #include "BsVector3.h"
 #include "BsVector3.h"
 #include "BsVector4.h"
 #include "BsVector4.h"
@@ -14,222 +10,10 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	/**
-	 * @brief	Base class containing some non-templated methods for
-	 *			all types for GpuParams
-	 */
-	class BS_CORE_EXPORT GpuParamBase
-	{
-	protected:
-		GpuParamBase();
-		GpuParamBase(const SPtr<GpuParams>& parent);
-
-		/**
-		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
-		 */
-		void markCoreDirty();
-
-	protected:
-		SPtr<GpuParams> mParent;
-	};
-
-	/**
-	 * @brief	Base class containing some non-templated methods for
-	 *			GpuDataParam.
-	 *
-	 * @see		TGpuDataParam
-	 */
-	class BS_CORE_EXPORT GpuDataParamBase : public GpuParamBase
-	{
-	protected:
-		GpuDataParamBase();
-		GpuDataParamBase(GpuParamDataDesc* paramDesc, const SPtr<GpuParams>& parent);
-
-		/**
-		 * @brief	Returns true if matrices need to be transposed when reading/writing them.
-		 */
-		bool getTransposeMatrices() const;
-
-		/**
-		 * @copydoc	GpuParamBlockBuffer::write
-		 */
-		bool write(UINT32 offset, const void* data, UINT32 size);
-
-		/**
-		 * @copydoc	GpuParamBlockBuffer::read
-		 */
-		bool read(UINT32 offset, void* data, UINT32 size);
-
-		/**
-		 * @copydoc	GpuParamBlockBuffer::zeroOut
-		 */
-		void zeroOut(UINT32 offset, UINT32 size);
-
-	protected:
-		GpuParamDataDesc* mParamDesc;
-	};
-
-	/**
-	 * @brief	Base class containing some non-templated methods for
-	 *			GpuObjectParam.
-	 *
-	 * @see		TGpuObjectParam
-	 */
-	class BS_CORE_EXPORT GpuObjectParamBase : public GpuParamBase
-	{
-	protected:
-		GpuObjectParamBase();
-		GpuObjectParamBase(GpuParamObjectDesc* paramDesc, const SPtr<GpuParams>& parent);
-
-		/**
-		 * @brief	Gets a texture bound to the specified slot.
-		 */
-		HTexture getTexture(UINT32 slot);
-
-		/**
-		 * @brief	Gets a sampler state bound to the specified slot.
-		 */
-		HSamplerState getSamplerState(UINT32 slot);
-
-		/**
-		 * @brief	Sets a texture at the specified slot.
-		 */
-		void setTexture(UINT32 slot, const HTexture& texture);
-
-		/**
-		 * @brief	Sets a sampler state at the specified slot.
-		 */
-		void setSamplerState(UINT32 slot, const HSamplerState& sampler);
-
-		/**
-		 * @brief	Sets information that determines which texture surfaces to bind
-		 *			as load/store parameters.
-		 */
-		void setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const;
-
-		/**
-		 * @brief	Changes the type of the texture at the specified slot.
-		 */
-		void setIsLoadStoreTexture(UINT32 slot, bool isLoadStore);
-
-	protected:
-		GpuParamObjectDesc* mParamDesc;
-	};
-
-	/**
-	 * @brief	Base class containing some non-templated methods for
-	 *			all types for GpuParamCore params
-	 */
-	class BS_CORE_EXPORT GpuParamCoreBase
-	{
-	protected:
-		GpuParamCoreBase();
-		GpuParamCoreBase(const SPtr<GpuParamsCore>& parent);
-
-		/**
-		 * @brief	Marks the core data as dirty, signifying the core thread it should update it.
-		 */
-		void markCoreDirty();
-
-	protected:
-		SPtr<GpuParamsCore> mParent;
-	};
-
-	/**
-	 * @brief	Base class containing some non-templated methods for
-	 *			GpuDataParam.
-	 *
-	 * @see		TGpuDataParam
-	 */
-	class BS_CORE_EXPORT GpuDataParamCoreBase : public GpuParamCoreBase
-	{
-	protected:
-		GpuDataParamCoreBase();
-		GpuDataParamCoreBase(GpuParamDataDesc* paramDesc, const SPtr<GpuParamsCore>& parent);
-
-		/**
-		 * @brief	Returns true if matrices need to be transposed when reading/writing them.
-		 */
-		bool getTransposeMatrices() const;
-
-		/**
-		 * @copydoc	GpuParamBlockBuffer::write
-		 */
-		bool write(UINT32 offset, const void* data, UINT32 size);
-
-		/**
-		 * @copydoc	GpuParamBlockBuffer::read
-		 */
-		bool read(UINT32 offset, void* data, UINT32 size);
-
-		/**
-		 * @copydoc	GpuParamBlockBuffer::zeroOut
-		 */
-		void zeroOut(UINT32 offset, UINT32 size);
-
-	protected:
-		GpuParamDataDesc* mParamDesc;
-	};
-
-	/**
-	 * @brief	Base class containing some non-templated methods for
-	 *			GpuObjectParam.
-	 *
-	 * @see		TGpuObjectParam
-	 */
-	class BS_CORE_EXPORT GpuObjectParamCoreBase : public GpuParamCoreBase
-	{
-	protected:
-		GpuObjectParamCoreBase();
-		GpuObjectParamCoreBase(GpuParamObjectDesc* paramDesc, const SPtr<GpuParamsCore>& parent);
-
-		/**
-		 * @brief	Gets a texture bound to the specified slot.
-		 */
-		SPtr<TextureCore> getTexture(UINT32 slot);
-
-		/**
-		 * @brief	Gets a sampler state bound to the specified slot.
-		 */
-		SPtr<SamplerStateCore> getSamplerState(UINT32 slot);
-
-		/**
-		 * @brief	Sets a texture at the specified slot.
-		 */
-		void setTexture(UINT32 slot, const SPtr<TextureCore>& texture);
-
-		/**
-		 * @brief	Sets a sampler state at the specified slot.
-		 */
-		void setSamplerState(UINT32 slot, const SPtr<SamplerStateCore>& sampler);
-
-		/**
-		 * @brief	Sets information that determines which texture surfaces to bind
-		 *			as load/store parameters.
-		 */
-		void setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const;
-
-		/**
-		 * @brief	Changes the type of the texture at the specified slot.
-		 */
-		void setIsLoadStoreTexture(UINT32 slot, bool isLoadStore);
-
-	protected:
-		GpuParamObjectDesc* mParamDesc;
-	};
-
 	template<bool Core> struct TGpuParamsPtrType { };
 	template<bool Core> struct TGpuParamsPtrType { };
 	template<> struct TGpuParamsPtrType<false> { typedef SPtr<GpuParams> Type; };
 	template<> struct TGpuParamsPtrType<false> { typedef SPtr<GpuParams> Type; };
 	template<> struct TGpuParamsPtrType<true> { typedef SPtr<GpuParamsCore> Type; };
 	template<> struct TGpuParamsPtrType<true> { typedef SPtr<GpuParamsCore> Type; };
 
 
-	template<bool Core> struct TGpuDataParamBaseType { };
-	template<> struct TGpuDataParamBaseType<false> { typedef GpuDataParamBase Type; };
-	template<> struct TGpuDataParamBaseType<true> { typedef GpuDataParamCoreBase Type;	};
-
-	template<bool Core> struct TGpuObjectParamBaseType { };
-	template<> struct TGpuObjectParamBaseType<false> { typedef GpuObjectParamBase Type; };
-	template<> struct TGpuObjectParamBaseType<true> { typedef GpuObjectParamCoreBase Type; };
-
 	template<bool Core> struct TGpuParamTextureType { };
 	template<bool Core> struct TGpuParamTextureType { };
 	template<> struct TGpuParamTextureType < false > { typedef HTexture Type; };
 	template<> struct TGpuParamTextureType < false > { typedef HTexture Type; };
 	template<> struct TGpuParamTextureType < true > { typedef SPtr<TextureCore> Type; };
 	template<> struct TGpuParamTextureType < true > { typedef SPtr<TextureCore> Type; };
@@ -256,9 +40,16 @@ namespace BansheeEngine
 	 * @see		Material
 	 * @see		Material
 	 */
 	 */
 	template<class T, bool Core>
 	template<class T, bool Core>
-	class BS_CORE_EXPORT TGpuDataParam : public TGpuDataParamBaseType<Core>::Type
+	class BS_CORE_EXPORT TGpuDataParam
 	{
 	{
 	private:
 	private:
+		template<bool Core> struct TGpuParamBufferType { };
+		template<> struct TGpuParamBufferType < false > { typedef SPtr<GpuParamBlockBuffer> Type; };
+		template<> struct TGpuParamBufferType < true > { typedef SPtr<GpuParamBlockBufferCore> Type; };
+
+		typedef typename TGpuParamBufferType<Core>::Type GpuParamBufferType;
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+
 		/**
 		/**
 		 * @brief	Policy class that allows us to re-use this template class for matrices which might
 		 * @brief	Policy class that allows us to re-use this template class for matrices which might
 		 *			need transposing, and other types which do not. Matrix needs to be transposed for
 		 *			need transposing, and other types which do not. Matrix needs to be transposed for
@@ -292,12 +83,8 @@ namespace BansheeEngine
 		};
 		};
 
 
 	public:
 	public:
-		TGpuDataParam()
-		{ }
-
-		TGpuDataParam(GpuParamDataDesc* paramDesc, const typename TGpuParamsPtrType<Core>::Type& parent)
-			:TGpuDataParamBaseType<Core>::Type(paramDesc, parent)
-		{ }
+		TGpuDataParam();
+		TGpuDataParam(GpuParamDataDesc* paramDesc, const GpuParamsType& parent);
 
 
 		/**
 		/**
 		 * @brief	Sets a parameter value at the specified array index. If parameter does not
 		 * @brief	Sets a parameter value at the specified array index. If parameter does not
@@ -306,39 +93,7 @@ namespace BansheeEngine
 		 * @note	Like with all GPU parameters, the actual GPU buffer will not be updated until rendering
 		 * @note	Like with all GPU parameters, the actual GPU buffer will not be updated until rendering
 		 *			with material this parameter was created from starts on the core thread.
 		 *			with material this parameter was created from starts on the core thread.
 		 */
 		 */
-		void set(const T& value, UINT32 arrayIdx = 0)
-		{
-			if (mParent == nullptr)
-				return;
-
-#if BS_DEBUG_MODE
-			if (arrayIdx >= mParamDesc->arraySize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " + 
-					toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
-			}
-#endif
-
-			UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
-			UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T)); // Truncate if it doesn't fit within parameter size
-
-			if (TransposePolicy<T>::transposeEnabled(getTransposeMatrices()))
-			{
-				T transposed = TransposePolicy<T>::transpose(value);
-				write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &transposed, sizeBytes);
-			}
-			else
-				write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
-
-			// Set unused bytes to 0
-			if(sizeBytes < elementSizeBytes)
-			{
-				UINT32 diffSize = elementSizeBytes - sizeBytes;
-				zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32)+sizeBytes, diffSize);
-			}
-
-			markCoreDirty();
-		}
+		void set(const T& value, UINT32 arrayIdx = 0);
 
 
 		/**
 		/**
 		 * @brief	Returns a value of a parameter at the specified array index. If parameter does not
 		 * @brief	Returns a value of a parameter at the specified array index. If parameter does not
@@ -346,310 +101,172 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @note	No GPU reads are done. Data returned was cached when it was written. 
 		 * @note	No GPU reads are done. Data returned was cached when it was written. 
 		 */
 		 */
-		T get(UINT32 arrayIdx = 0)
-		{
-			if (mParent == nullptr)
-				return T();
-
-#if BS_DEBUG_MODE
-			if (arrayIdx >= mParamDesc->arraySize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " + 
-					toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
-			}
-#endif
-
-			UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
-			UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T));
-
-			T value;
-			read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
-
-			if (TransposePolicy<T>::transposeEnabled(getTransposeMatrices()))
-				return TransposePolicy<T>::transpose(value);
-			else
-				return value;
-		}
-	};
-
-	typedef TGpuDataParam<float, false> GpuParamFloat;
-	typedef TGpuDataParam<Color, false> GpuParamColor;
-	typedef TGpuDataParam<Vector2, false> GpuParamVec2;
-	typedef TGpuDataParam<Vector3, false> GpuParamVec3;
-	typedef TGpuDataParam<Vector4, false> GpuParamVec4;
-	typedef TGpuDataParam<Matrix3, false> GpuParamMat3;
-	typedef TGpuDataParam<Matrix4, false> GpuParamMat4;
+		T get(UINT32 arrayIdx = 0);
 
 
-	template class TGpuDataParam<float, false>;
-	template class TGpuDataParam<Color, false>;
-	template class TGpuDataParam<Vector2, false>;
-	template class TGpuDataParam<Vector3, false>;
-	template class TGpuDataParam<Vector4, false>;
-	template class TGpuDataParam<Matrix3, false>;
-	template class TGpuDataParam<Matrix4, false>;
-
-	typedef TGpuDataParam<float, true> GpuParamFloatCore;
-	typedef TGpuDataParam<Color, true> GpuParamColorCore;
-	typedef TGpuDataParam<Vector2, true> GpuParamVec2Core;
-	typedef TGpuDataParam<Vector3, true> GpuParamVec3Core;
-	typedef TGpuDataParam<Vector4, true> GpuParamVec4Core;
-	typedef TGpuDataParam<Matrix3, true> GpuParamMat3Core;
-	typedef TGpuDataParam<Matrix4, true> GpuParamMat4Core;
-
-	template class TGpuDataParam<float, true>;
-	template class TGpuDataParam<Color, true>;
-	template class TGpuDataParam<Vector2, true>;
-	template class TGpuDataParam<Vector3, true>;
-	template class TGpuDataParam<Vector4, true>;
-	template class TGpuDataParam<Matrix3, true>;
-	template class TGpuDataParam<Matrix4, true>;
+	protected:
+		GpuParamsType mParent;
+		GpuParamDataDesc* mParamDesc;
+	};
 
 
 	/**
 	/**
 	 * @copydoc TGpuDataParam
 	 * @copydoc TGpuDataParam
 	 */
 	 */
 	template<bool Core>
 	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamStruct : public TGpuDataParamBaseType<Core>::Type
+	class BS_CORE_EXPORT TGpuParamStruct
 	{
 	{
 	public:
 	public:
-		TGpuParamStruct()
-		{ }
+		template<bool Core> struct TGpuParamBufferType { };
+		template<> struct TGpuParamBufferType < false > { typedef SPtr<GpuParamBlockBuffer> Type; };
+		template<> struct TGpuParamBufferType < true > { typedef SPtr<GpuParamBlockBufferCore> Type; };
 
 
-		TGpuParamStruct(GpuParamDataDesc* paramDesc, const typename TGpuParamsPtrType<Core>::Type& parent)
-			:TGpuDataParamBaseType<Core>::Type(paramDesc, parent)
-		{ }
+		typedef typename TGpuParamBufferType<Core>::Type GpuParamBufferType;
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+
+		TGpuParamStruct();
+		TGpuParamStruct(GpuParamDataDesc* paramDesc, const GpuParamsType& parent);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 * @copydoc	TGpuDataParam::set
 		 */
 		 */
-		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0)
-		{
-			if (mParent == nullptr)
-				return;
-
-			UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
-
-#if BS_DEBUG_MODE
-			if (sizeBytes > elementSizeBytes)
-			{
-				LOGWRN("Provided element size larger than maximum element size. Maximum size: " +
-					toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
-			}
-
-			if (arrayIdx >= mParamDesc->arraySize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
-					toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
-			}
-#endif
-
-			sizeBytes = std::min(elementSizeBytes, sizeBytes);
-
-			write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
-
-			// Set unused bytes to 0
-			if (sizeBytes < elementSizeBytes)
-			{
-				UINT32 diffSize = elementSizeBytes - sizeBytes;
-				zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32) + sizeBytes, diffSize);
-			}
-
-			markCoreDirty();
-		}
+		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::get
 		 * @copydoc	TGpuDataParam::get
 		 */
 		 */
-		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0)
-		{
-			if (mParent == nullptr)
-				return;
-
-			UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
-
-#if BS_DEBUG_MODE
-			if (sizeBytes > elementSizeBytes)
-			{
-				LOGWRN("Provided element size larger than maximum element size. Maximum size: " +
-					toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
-			}
-
-			if (arrayIdx >= mParamDesc->arraySize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
-					toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
-			}
-#endif
-			sizeBytes = std::min(elementSizeBytes, sizeBytes);
-
-			read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
-		}
+		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
 
 
 
 
 		/**
 		/**
 		 * @brief	Returns the size of the struct in bytes.
 		 * @brief	Returns the size of the struct in bytes.
 		 */
 		 */
-		UINT32 getElementSize() const
-		{
-			if (mParent == nullptr)
-				return 0;
+		UINT32 getElementSize() const;
 
 
-			return mParamDesc->elementSize * sizeof(UINT32);
-		}
+	protected:
+		GpuParamsType mParent;
+		GpuParamDataDesc* mParamDesc;
 	};
 	};
 
 
-	typedef TGpuParamStruct<false> GpuParamStruct;
-	typedef TGpuParamStruct<true> GpuParamStructCore;
-
-	template class TGpuParamStruct<false>;
-	template class TGpuParamStruct<true>;
-
 	/**
 	/**
 	 * @copydoc TGpuObjectParam
 	 * @copydoc TGpuObjectParam
 	 */
 	 */
 	template<bool Core>
 	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamTexture : public TGpuObjectParamBaseType<Core>::Type
+	class BS_CORE_EXPORT TGpuParamTexture
 	{
 	{
 	private:
 	private:
 		friend class GpuParams;
 		friend class GpuParams;
 		friend class GpuParamsCore;
 		friend class GpuParamsCore;
 
 
-	public:
-		TGpuParamTexture()
-		{ }
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 
 
-		TGpuParamTexture(GpuParamObjectDesc* paramDesc, const typename TGpuParamsPtrType<Core>::Type& parent)
-			:TGpuObjectParamBaseType<Core>::Type(paramDesc, parent)
-		{ }
+	public:
+		TGpuParamTexture();
+		TGpuParamTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 * @copydoc	TGpuDataParam::set
 		 */
 		 */
-		void set(const typename TGpuParamTextureType<Core>::Type& texture)
-		{
-			if (mParent == nullptr)
-				return;
-
-			setTexture(mParamDesc->slot, texture);
-			setIsLoadStoreTexture(mParamDesc->slot, false);
-
-			markCoreDirty();
-		}
+		void set(const TextureType& texture);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::get
 		 * @copydoc	TGpuDataParam::get
 		 */
 		 */
-		typename TGpuParamTextureType<Core>::Type get()
-		{
-			if (mParent == nullptr)
-				return TGpuParamTextureType<Core>::Type();
+		TextureType get();
 
 
-			return getTexture(mParamDesc->slot);
-		}
+	protected:
+		GpuParamsType mParent;
+		GpuParamObjectDesc* mParamDesc;
 	};
 	};
 
 
-	typedef TGpuParamTexture<false> GpuParamTexture;
-	typedef TGpuParamTexture<true> GpuParamTextureCore;
-
-	template class TGpuParamTexture<false>;
-	template class TGpuParamTexture<true>;
-
 	/**
 	/**
 	 * @copydoc TGpuObjectParam
 	 * @copydoc TGpuObjectParam
 	 */
 	 */
 	template<bool Core>
 	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamLoadStoreTexture : public TGpuObjectParamBaseType<Core>::Type
+	class BS_CORE_EXPORT TGpuParamLoadStoreTexture
 	{
 	{
 	private:
 	private:
 		friend class GpuParams;
 		friend class GpuParams;
 		friend class GpuParamsCore;
 		friend class GpuParamsCore;
 
 
-	public:
-		TGpuParamLoadStoreTexture()
-		{ }
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 
 
-		TGpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const typename TGpuParamsPtrType<Core>::Type& parent)
-			:TGpuObjectParamBaseType<Core>::Type(paramDesc, parent)
-		{ }
+	public:
+		TGpuParamLoadStoreTexture();
+		TGpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 * @copydoc	TGpuDataParam::set
 		 */
 		 */
-		void set(const typename TGpuParamTextureType<Core>::Type& texture, const TextureSurface& surface)
-		{
-			if (mParent == nullptr)
-				return;
-
-			setTexture(mParamDesc->slot, texture);
-			setIsLoadStoreTexture(mParamDesc->slot, true);
-			setLoadStoreSurface(mParamDesc->slot, surface);
-
-			markCoreDirty();
-		}
+		void set(const TextureType& texture, const TextureSurface& surface);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::get
 		 * @copydoc	TGpuDataParam::get
 		 */
 		 */
-		typename TGpuParamTextureType<Core>::Type get()
-		{
-			if (mParent == nullptr)
-				return TGpuParamTextureType<Core>::Type();
+		TextureType get();
 
 
-			return getTexture(mParamDesc->slot);
-		}
+	protected:
+		GpuParamsType mParent;
+		GpuParamObjectDesc* mParamDesc;
 	};
 	};
 
 
-	typedef TGpuParamLoadStoreTexture<false> GpuParamLoadStoreTexture;
-	typedef TGpuParamLoadStoreTexture<true> GpuParamLoadStoreTextureCore;
-
-	template class TGpuParamLoadStoreTexture<false>;
-	template class TGpuParamLoadStoreTexture<true>;
-
 	/**
 	/**
 	 * @copydoc TGpuObjectParam
 	 * @copydoc TGpuObjectParam
 	 */
 	 */
 	template<bool Core>
 	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamSampState : public TGpuObjectParamBaseType<Core>::Type
+	class BS_CORE_EXPORT TGpuParamSampState
 	{
 	{
 	private:
 	private:
 		friend class GpuParams;
 		friend class GpuParams;
 		friend class GpuParamsCore;
 		friend class GpuParamsCore;
 
 
-	public:
-		TGpuParamSampState()
-		{ }
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerStateType;
 
 
-		TGpuParamSampState(GpuParamObjectDesc* paramDesc, const typename TGpuParamsPtrType<Core>::Type& parent)
-			:TGpuObjectParamBaseType<Core>::Type(paramDesc, parent)
-		{ }
+	public:
+		TGpuParamSampState();
+		TGpuParamSampState(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 * @copydoc	TGpuDataParam::set
 		 */
 		 */
-		void set(const typename TGpuParamSamplerStateType<Core>::Type& samplerState)
-		{
-			if (mParent == nullptr)
-				return;
-
-			setSamplerState(mParamDesc->slot, samplerState);
-
-			markCoreDirty();
-		}
+		void set(const SamplerStateType& samplerState);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::get
 		 * @copydoc	TGpuDataParam::get
 		 */
 		 */
-		typename TGpuParamSamplerStateType<Core>::Type get()
-		{
-			if (mParent == nullptr)
-				return TGpuParamSamplerStateType<Core>::Type();
+		SamplerStateType get();
 
 
-			return getSamplerState(mParamDesc->slot);
-		}
+	protected:
+		GpuParamsType mParent;
+		GpuParamObjectDesc* mParamDesc;
 	};
 	};
 
 
+	typedef TGpuDataParam<float, false> GpuParamFloat;
+	typedef TGpuDataParam<Color, false> GpuParamColor;
+	typedef TGpuDataParam<Vector2, false> GpuParamVec2;
+	typedef TGpuDataParam<Vector3, false> GpuParamVec3;
+	typedef TGpuDataParam<Vector4, false> GpuParamVec4;
+	typedef TGpuDataParam<Matrix3, false> GpuParamMat3;
+	typedef TGpuDataParam<Matrix4, false> GpuParamMat4;
+
+	typedef TGpuDataParam<float, true> GpuParamFloatCore;
+	typedef TGpuDataParam<Color, true> GpuParamColorCore;
+	typedef TGpuDataParam<Vector2, true> GpuParamVec2Core;
+	typedef TGpuDataParam<Vector3, true> GpuParamVec3Core;
+	typedef TGpuDataParam<Vector4, true> GpuParamVec4Core;
+	typedef TGpuDataParam<Matrix3, true> GpuParamMat3Core;
+	typedef TGpuDataParam<Matrix4, true> GpuParamMat4Core;
+
+	typedef TGpuParamStruct<false> GpuParamStruct;
+	typedef TGpuParamStruct<true> GpuParamStructCore;
+
+	typedef TGpuParamTexture<false> GpuParamTexture;
+	typedef TGpuParamTexture<true> GpuParamTextureCore;
+
 	typedef TGpuParamSampState<false> GpuParamSampState;
 	typedef TGpuParamSampState<false> GpuParamSampState;
 	typedef TGpuParamSampState<true> GpuParamSampStateCore;
 	typedef TGpuParamSampState<true> GpuParamSampStateCore;
 
 
-	template class TGpuParamSampState<false>;
-	template class TGpuParamSampState<true>;
+	typedef TGpuParamLoadStoreTexture<false> GpuParamLoadStoreTexture;
+	typedef TGpuParamLoadStoreTexture<true> GpuParamLoadStoreTextureCore;
 }
 }

+ 57 - 284
BansheeCore/Include/BsGpuParams.h

@@ -4,10 +4,10 @@
 #include "BsGpuParam.h"
 #include "BsGpuParam.h"
 #include "BsCoreObject.h"
 #include "BsCoreObject.h"
 
 
+#include "BsDebug.h"
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	struct GpuParamsInternalData;
-
 	/**
 	/**
 	 * @brief	Stores information needed for binding a texture to the pipeline.
 	 * @brief	Stores information needed for binding a texture to the pipeline.
 	 */
 	 */
@@ -131,40 +131,43 @@ namespace BansheeEngine
 		bool mTransposeMatrices;
 		bool mTransposeMatrices;
 	};
 	};
 
 
-	template<bool Core> struct TGpuParamsBaseType { };
-	template<> struct TGpuParamsBaseType<true> { typedef CoreObjectCore Type; };
-	template<> struct TGpuParamsBaseType<false> { typedef CoreObject Type; };
-
-	template<bool Core> struct TGpuParamsType { };
-	template<> struct TGpuParamsType<false> { typedef GpuParams Type; };
-	template<> struct TGpuParamsType<true>{ typedef GpuParamsCore Type; };
-
 	/**
 	/**
 	 * @brief	Templated version of GpuParams that contains functionality for both
 	 * @brief	Templated version of GpuParams that contains functionality for both
 	 *			sim and core thread versions of stored data.
 	 *			sim and core thread versions of stored data.
 	 */
 	 */
-	template <class TParamsBuffer, class TTexture, class TSampler, bool Core>
-	class TGpuParams : public TGpuParamsBaseType<Core>::Type, public GpuParamsBase
+	template <bool Core>
+	class BS_CORE_EXPORT TGpuParams : public GpuParamsBase
 	{
 	{
 	public:
 	public:
+		template<bool Core> struct TTypes { };
+
+		template<> struct TTypes < false > 
+		{ 
+			typedef GpuParams GpuParamsType; 
+			typedef HTexture TextureType;
+			typedef HSamplerState SamplerType;
+			typedef SPtr<GpuParamBlockBuffer> ParamsBufferType;
+		};
+
+		template<> struct TTypes < true > 
+		{ 
+			typedef GpuParamsCore GpuParamsType;
+			typedef SPtr<TextureCore> TextureType;
+			typedef SPtr<SamplerStateCore> SamplerType;
+			typedef SPtr<GpuParamBlockBufferCore> ParamsBufferType;
+		};
+
+		typedef typename TTypes<Core>::GpuParamsType GpuParamsType;
+		typedef typename TTypes<Core>::TextureType TextureType;
+		typedef typename TTypes<Core>::SamplerType SamplerType;
+		typedef typename TTypes<Core>::ParamsBufferType ParamsBufferType;
+
 		/**
 		/**
 		 * @copydoc	GpuParamsBase::GpuParamsBase(const GpuParamDescPtr&, bool)
 		 * @copydoc	GpuParamsBase::GpuParamsBase(const GpuParamDescPtr&, bool)
 		 */
 		 */
-		TGpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices)
-			:GpuParamsBase(paramDesc, transposeMatrices), mParamBlockBuffers(nullptr), mTextures(nullptr), 
-			mSamplerStates(nullptr)
-		{
-			mParamBlockBuffers = bs_newN<TParamsBuffer>(mNumParamBlocks);
-			mTextures = bs_newN<TTexture>(mNumTextures);
-			mSamplerStates = bs_newN<TSampler>(mNumSamplerStates);
-		}
+		TGpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
 
 
-		virtual ~TGpuParams()
-		{
-			bs_deleteN(mParamBlockBuffers, mNumParamBlocks);
-			bs_deleteN(mTextures, mNumTextures);
-			bs_deleteN(mSamplerStates, mNumSamplerStates);
-		}
+		virtual ~TGpuParams();
 
 
 		/**
 		/**
 		 * @brief	Binds a new parameter buffer to the specified slot. Any following parameter reads or
 		 * @brief	Binds a new parameter buffer to the specified slot. Any following parameter reads or
@@ -176,18 +179,7 @@ namespace BansheeEngine
 		 *			It is up to the caller to guarantee the provided buffer matches parameter block
 		 *			It is up to the caller to guarantee the provided buffer matches parameter block
 		 *			descriptor for this slot.
 		 *			descriptor for this slot.
 		 */
 		 */
-		void setParamBlockBuffer(UINT32 slot, const TParamsBuffer& paramBlockBuffer)
-		{
-			if (slot < 0 || slot >= mNumParamBlocks)
-			{
-				BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
-					toString(mNumParamBlocks - 1) + ". Requested: " + toString(slot));
-			}
-
-			mParamBlockBuffers[slot] = paramBlockBuffer;
-
-			_markCoreDirty();
-		}
+		void setParamBlockBuffer(UINT32 slot, const ParamsBufferType& paramBlockBuffer);
 
 
 		/**
 		/**
 		 * @brief	Replaces the parameter buffer with the specified name. Any following parameter reads or
 		 * @brief	Replaces the parameter buffer with the specified name. Any following parameter reads or
@@ -199,20 +191,7 @@ namespace BansheeEngine
 		 *			It is up to the caller to guarantee the provided buffer matches parameter block
 		 *			It is up to the caller to guarantee the provided buffer matches parameter block
 		 *			descriptor for this slot.
 		 *			descriptor for this slot.
 		 */
 		 */
-		void setParamBlockBuffer(const String& name, const TParamsBuffer& paramBlockBuffer)
-		{
-			auto iterFind = mParamDesc->paramBlocks.find(name);
-
-			if (iterFind == mParamDesc->paramBlocks.end())
-			{
-				LOGWRN("Cannot find parameter block with the name: " + name);
-				return;
-			}
-
-			mParamBlockBuffers[iterFind->second.slot] = paramBlockBuffer;
-
-			_markCoreDirty();
-		}
+		void setParamBlockBuffer(const String& name, const ParamsBufferType& paramBlockBuffer);
 
 
 		/**
 		/**
 		* @brief	Returns a handle for the parameter with the specified name.
 		* @brief	Returns a handle for the parameter with the specified name.
@@ -223,278 +202,62 @@ namespace BansheeEngine
 		*
 		*
 		*			Parameter handles will be invalidated when their parent GpuParams object changes.
 		*			Parameter handles will be invalidated when their parent GpuParams object changes.
 		*/
 		*/
-		template<class T> void getParam(const String& name, TGpuDataParam<T, Core>& output) const
-		{
-			BS_EXCEPT(InvalidParametersException, "Unsupported parameter type");
-		}
-
-		/**
-		* @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		*/
-		template<>
-		void getParam<float>(const String& name, TGpuDataParam<float, Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_FLOAT1)
-			{
-				output = TGpuDataParam<float, Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find float parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuDataParam<float, Core>(&iterFind->second, _getThisPtr());
-		}
-
-		/**
-		* @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		*/
-		template<>
-		void getParam<Vector2>(const String& name, TGpuDataParam<Vector2, Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_FLOAT2)
-			{
-				output = TGpuDataParam<Vector2, Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find vector (2) parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuDataParam<Vector2, Core>(&iterFind->second, _getThisPtr());
-		}
-
-		/**
-		* @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		*/
-		template<>
-		void getParam<Vector3>(const String& name, TGpuDataParam<Vector3, Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_FLOAT3)
-			{
-				output = TGpuDataParam<Vector3, Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find vector (3) parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuDataParam<Vector3, Core>(&iterFind->second, _getThisPtr());
-		}
-
-		/**
-		* @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		*/
-		template<>
-		void getParam<Vector4>(const String& name, TGpuDataParam<Vector4, Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_FLOAT4)
-			{
-				output = TGpuDataParam<Vector4, Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find vector (4) parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuDataParam<Vector4, Core>(&iterFind->second, _getThisPtr());
-		}
-
-		/**
-		* @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		*/
-		template<>
-		void getParam<Color>(const String& name, TGpuDataParam<Color, Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_FLOAT4)
-			{
-				output = TGpuDataParam<Color, Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find color parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuDataParam<Color, Core>(&iterFind->second, _getThisPtr());
-		}
-
-		/**
-		* @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		*/
-		template<>
-		void getParam<Matrix3>(const String& name, TGpuDataParam<Matrix3, Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_MATRIX_3X3)
-			{
-				output = TGpuDataParam<Matrix3, Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find matrix (3x3) parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuDataParam<Matrix3, Core>(&iterFind->second, _getThisPtr());
-		}
-
-		/**
-		* @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
-		*/
-		template<>
-		void getParam<Matrix4>(const String& name, TGpuDataParam<Matrix4, Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_MATRIX_4X4)
-			{
-				output = TGpuDataParam<Matrix4, Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find matrix (4x4) parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuDataParam<Matrix4, Core>(&iterFind->second, _getThisPtr());
-		}
+		template<class T> void getParam(const String& name, TGpuDataParam<T, Core>& output) const;
 
 
 		/**
 		/**
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 */
 		 */
-		void getStructParam(const String& name, TGpuParamStruct<Core>& output) const
-		{
-			auto iterFind = mParamDesc->params.find(name);
-
-			if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_STRUCT)
-			{
-				output = TGpuParamStruct<Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find struct parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuParamStruct<Core>(&iterFind->second, _getThisPtr());
-		}
+		void getStructParam(const String& name, TGpuParamStruct<Core>& output) const;
 
 
 		/**
 		/**
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 */
 		 */
-		void getTextureParam(const String& name, TGpuParamTexture<Core>& output) const
-		{
-			auto iterFind = mParamDesc->textures.find(name);
-
-			if (iterFind == mParamDesc->textures.end())
-			{
-				output = TGpuParamTexture<Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find texture parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuParamTexture<Core>(&iterFind->second, _getThisPtr());
-		}
+		void getTextureParam(const String& name, TGpuParamTexture<Core>& output) const;
 
 
 		/**
 		/**
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 */
 		 */
-		void getLoadStoreTextureParam(const String& name, TGpuParamLoadStoreTexture<Core>& output) const
-		{
-			auto iterFind = mParamDesc->textures.find(name);
-
-			if (iterFind == mParamDesc->textures.end())
-			{
-				output = TGpuParamLoadStoreTexture<Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find texture parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuParamLoadStoreTexture<Core>(&iterFind->second, _getThisPtr());
-		}
+		void getLoadStoreTextureParam(const String& name, TGpuParamLoadStoreTexture<Core>& output) const;
 
 
 		/**
 		/**
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 * @copydoc	getParam(const String&, TGpuDataParam<T, Core>&)
 		 */
 		 */
-		void getSamplerStateParam(const String& name, TGpuParamSampState<Core>& output) const
-		{
-			auto iterFind = mParamDesc->samplers.find(name);
-
-			if (iterFind == mParamDesc->samplers.end())
-			{
-				output = TGpuParamSampState<Core>(&iterFind->second, nullptr);
-				LOGWRN("Cannot find sampler state parameter with the name '" + name + "'");
-			}
-			else
-				output = TGpuParamSampState<Core>(&iterFind->second, _getThisPtr());
-		}
+		void getSamplerStateParam(const String& name, TGpuParamSampState<Core>& output) const;
 
 
 		/**
 		/**
 		 * @brief	Gets a parameter block buffer from the specified slot.
 		 * @brief	Gets a parameter block buffer from the specified slot.
 		 */
 		 */
-		TParamsBuffer getParamBlockBuffer(UINT32 slot) const
-		{
-			if (slot < 0 || slot >= mNumParamBlocks)
-			{
-				BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
-					toString(mNumParamBlocks - 1) + ". Requested: " + toString(slot));
-			}
-
-			return mParamBlockBuffers[slot];
-		}
+		ParamsBufferType getParamBlockBuffer(UINT32 slot) const;
 
 
 		/**
 		/**
 		 * @brief	Gets a texture bound to the specified slot.
 		 * @brief	Gets a texture bound to the specified slot.
 		 */
 		 */
-		TTexture getTexture(UINT32 slot)
-		{
-			if (slot < 0 || slot >= mNumTextures)
-			{
-				BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
-					toString(mNumTextures - 1) + ". Requested: " + toString(slot));
-			}
-
-			return mTextures[slot];
-		}
+		TextureType getTexture(UINT32 slot);
 
 
 		/**
 		/**
 		 * @brief	Gets a sampler state bound to the specified slot.
 		 * @brief	Gets a sampler state bound to the specified slot.
 		 */
 		 */
-		TSampler getSamplerState(UINT32 slot)
-		{
-			if (slot < 0 || slot >= mNumSamplerStates)
-			{
-				BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
-					toString(mNumSamplerStates - 1) + ". Requested: " + toString(slot));
-			}
-
-			return mSamplerStates[slot];
-		}
+		SamplerType getSamplerState(UINT32 slot);
 
 
 		/**
 		/**
 		 * @brief	Sets a texture at the specified slot.
 		 * @brief	Sets a texture at the specified slot.
 		 */
 		 */
-		void setTexture(UINT32 slot, const TTexture& texture)
-		{
-			if (slot < 0 || slot >= mNumTextures)
-			{
-				BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
-					toString(mNumTextures - 1) + ". Requested: " + toString(slot));
-			}
-
-			mTextures[slot] = texture;
-			_markCoreDirty();
-		}
+		void setTexture(UINT32 slot, const TextureType& texture);
 
 
 		/**
 		/**
 		 * @brief	Sets a sampler state at the specified slot.
 		 * @brief	Sets a sampler state at the specified slot.
 		 */
 		 */
-		void setSamplerState(UINT32 slot, const TSampler& sampler)
-		{
-			if (slot < 0 || slot >= mNumSamplerStates)
-			{
-				BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
-					toString(mNumSamplerStates - 1) + ". Requested: " + toString(slot));
-			}
-
-			mSamplerStates[slot] = sampler;
-			_markCoreDirty();
-		}
+		void setSamplerState(UINT32 slot, const SamplerType& sampler);
 
 
 	protected:
 	protected:
 		/**
 		/**
 		 * @copydoc	CoreObject::getThisPtr
 		 * @copydoc	CoreObject::getThisPtr
 		 */
 		 */
-		SPtr<typename TGpuParamsType<Core>::Type> _getThisPtr() const
-		{
-			return std::static_pointer_cast<typename TGpuParamsType<Core>::Type>(getThisPtr());
-		}
+		virtual SPtr<GpuParamsType> _getThisPtr() const = 0;
 
 
-		TParamsBuffer* mParamBlockBuffers;
-		TTexture* mTextures;
-		TSampler* mSamplerStates;
+		ParamsBufferType* mParamBlockBuffers;
+		TextureType* mTextures;
+		SamplerType* mSamplerStates;
 	};
 	};
 
 
 	/**
 	/**
@@ -504,7 +267,7 @@ namespace BansheeEngine
 	 *
 	 *
 	 * @note	Core thread only.
 	 * @note	Core thread only.
 	 */
 	 */
-	class BS_CORE_EXPORT GpuParamsCore : public TGpuParams<SPtr<GpuParamBlockBufferCore>, SPtr<TextureCore>, SPtr<SamplerStateCore>, true>
+	class BS_CORE_EXPORT GpuParamsCore : public CoreObjectCore, public TGpuParams<true>
 	{
 	{
 	public:
 	public:
 		~GpuParamsCore() { }
 		~GpuParamsCore() { }
@@ -527,6 +290,11 @@ namespace BansheeEngine
 		 */
 		 */
 		GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
 		GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
 
 
+		/**
+		 * @copydoc	CoreObject::getThisPtr
+		 */
+		SPtr<GpuParamsCore> _getThisPtr() const;
+
 		/**
 		/**
 		 * @copydoc	CoreObjectCore::syncToCore
 		 * @copydoc	CoreObjectCore::syncToCore
 		 */
 		 */
@@ -543,7 +311,7 @@ namespace BansheeEngine
 	 *
 	 *
 	 * @note	Sim thread only.
 	 * @note	Sim thread only.
 	 */
 	 */
-	class BS_CORE_EXPORT GpuParams : public TGpuParams<GpuParamBlockBufferPtr, HTexture, HSamplerState, false>
+	class BS_CORE_EXPORT GpuParams : public CoreObject, public TGpuParams<false>
 	{
 	{
 	public:
 	public:
 		~GpuParams() { }
 		~GpuParams() { }
@@ -572,6 +340,11 @@ namespace BansheeEngine
 		 */
 		 */
 		GpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
 		GpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices);
 
 
+		/**
+		 * @copydoc	CoreObject::getThisPtr
+		 */
+		SPtr<GpuParams> _getThisPtr() const;
+
 		/**
 		/**
 		 * @copydoc	CoreObject::createCore
 		 * @copydoc	CoreObject::createCore
 		 */
 		 */

+ 19 - 241
BansheeCore/Include/BsMaterial.h

@@ -9,13 +9,6 @@
 #include "BsMatrix3.h"
 #include "BsMatrix3.h"
 #include "BsMatrix4.h"
 #include "BsMatrix4.h"
 
 
-// TOOD REMOVE THIS
-#include "BsShader.h"
-#include "BsGpuParams.h"
-#include "BsTechnique.h"
-#include "BsPass.h"
-#include "BsHardwareBufferManager.h"
-
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	/**
 	/**
@@ -28,13 +21,6 @@ namespace BansheeEngine
 	public:
 	public:
 		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
 		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
 
 
-		GpuParamsType mVertParams;
-		GpuParamsType mFragParams;
-		GpuParamsType mGeomParams;
-		GpuParamsType mHullParams;
-		GpuParamsType mDomainParams;
-		GpuParamsType mComputeParams;
-
 		/**
 		/**
 		 * @brief	Returns a set of GPU parameters based on an index.
 		 * @brief	Returns a set of GPU parameters based on an index.
 		 *
 		 *
@@ -64,6 +50,13 @@ namespace BansheeEngine
 		 * 			GPU parameters in this object.
 		 * 			GPU parameters in this object.
 		 */
 		 */
 		UINT32 getNumParams() const { return 6; }
 		UINT32 getNumParams() const { return 6; }
+
+		GpuParamsType mVertParams;
+		GpuParamsType mFragParams;
+		GpuParamsType mGeomParams;
+		GpuParamsType mHullParams;
+		GpuParamsType mDomainParams;
+		GpuParamsType mComputeParams;
 	};
 	};
 
 
 	template<bool Core> struct TGpuParamBlockBufferPtrType { };
 	template<bool Core> struct TGpuParamBlockBufferPtrType { };
@@ -180,13 +173,7 @@ namespace BansheeEngine
 		 * 			dependent upon (render system, renderer, etc), you will need to call this 
 		 * 			dependent upon (render system, renderer, etc), you will need to call this 
 		 * 			method again on all your Materials to make sure technique used is updated.
 		 * 			method again on all your Materials to make sure technique used is updated.
 		 */
 		 */
-		void setShader(ShaderType shader)
-		{
-			mShader = shader;
-
-			initBestTechnique();
-			_markCoreDirty();
-		}
+		void setShader(ShaderType shader);
 
 
 		/**
 		/**
 		 * @brief	Returns the currently active shader.
 		 * @brief	Returns the currently active shader.
@@ -197,23 +184,12 @@ namespace BansheeEngine
 		 * @brief	Returns the number of passes that are used
 		 * @brief	Returns the number of passes that are used
 		 * 			by the shader used in the material.
 		 * 			by the shader used in the material.
 		 */
 		 */
-		UINT32 getNumPasses() const
-		{
-			throwIfNotInitialized();
-
-			return mShader->getBestTechnique()->getNumPasses();
-		}
+		UINT32 getNumPasses() const;
 
 
 		/**
 		/**
 		 * @brief	Retrieves a specific shader pass.
 		 * @brief	Retrieves a specific shader pass.
 		 */
 		 */
-		PassType getPass(UINT32 passIdx) const
-		{
-			if (passIdx < 0 || passIdx >= mShader->getBestTechnique()->getNumPasses())
-				BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
-
-			return mShader->getBestTechnique()->getPass(passIdx);
-		}
+		PassType getPass(UINT32 passIdx) const;
 
 
 		/**   
 		/**   
 		 *  @brief	Assigns a float value to the shader parameter with the specified name. 
 		 *  @brief	Assigns a float value to the shader parameter with the specified name. 
@@ -506,40 +482,7 @@ namespace BansheeEngine
 		 * 			
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 *			If material shader changes this handle will be invalidated.
 		 */
 		 */
-		TMaterialParamStruct<Core> getParamStruct(const String& name) const
-		{
-			throwIfNotInitialized();
-
-			auto iterFind = mValidParams.find(name);
-			if (iterFind == mValidParams.end())
-			{
-				LOGWRN("Material doesn't have a parameter named " + name);
-				return TMaterialParamStruct<Core>();
-			}
-
-			const String& gpuVarName = iterFind->second;
-			Vector<TGpuParamStruct<Core>> gpuParams;
-
-			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				SPtr<TPassParameters<Core>> params = *iter;
-
-				for (UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsType& paramPtr = params->getParamByIdx(i);
-					if (paramPtr)
-					{
-						if (paramPtr->hasParam(gpuVarName))
-						{
-							gpuParams.push_back(TGpuParamStruct<Core>());
-							paramPtr->getStructParam(gpuVarName, gpuParams.back());
-						}
-					}
-				}
-			}
-
-			return TMaterialParamStruct<Core>(gpuParams);
-		}
+		TMaterialParamStruct<Core> getParamStruct(const String& name) const;
 
 
 		/**
 		/**
 		 * @brief	Returns a texture GPU parameter. This parameter may be used for
 		 * @brief	Returns a texture GPU parameter. This parameter may be used for
@@ -552,40 +495,7 @@ namespace BansheeEngine
 		 * 			
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 *			If material shader changes this handle will be invalidated.
 		 */
 		 */
-		TMaterialParamTexture<Core> getParamTexture(const String& name) const
-		{
-			throwIfNotInitialized();
-
-			auto iterFind = mValidParams.find(name);
-			if (iterFind == mValidParams.end())
-			{
-				LOGWRN("Material doesn't have a parameter named " + name);
-				return TMaterialParamTexture<Core>();
-			}
-
-			const String& gpuVarName = iterFind->second;
-			Vector<TGpuParamTexture<Core>> gpuParams;
-
-			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				SPtr<TPassParameters<Core>> params = *iter;
-
-				for (UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsType& paramPtr = params->getParamByIdx(i);
-					if (paramPtr)
-					{
-						if (paramPtr->hasTexture(gpuVarName))
-						{
-							gpuParams.push_back(TGpuParamTexture<Core>());
-							paramPtr->getTextureParam(gpuVarName, gpuParams.back());
-						}
-					}
-				}
-			}
-
-			return TMaterialParamTexture<Core>(gpuParams);
-		}
+		TMaterialParamTexture<Core> getParamTexture(const String& name) const;
 
 
 		/**
 		/**
 		 * @brief	Returns a GPU parameter for binding a load/store texture. This parameter 
 		 * @brief	Returns a GPU parameter for binding a load/store texture. This parameter 
@@ -598,40 +508,7 @@ namespace BansheeEngine
 		 * 			
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 *			If material shader changes this handle will be invalidated.
 		 */
 		 */
-		TMaterialParamLoadStoreTexture<Core> getParamLoadStoreTexture(const String& name) const
-		{
-			throwIfNotInitialized();
-
-			auto iterFind = mValidParams.find(name);
-			if (iterFind == mValidParams.end())
-			{
-				LOGWRN("Material doesn't have a parameter named " + name);
-				return TMaterialParamLoadStoreTexture<Core>();
-			}
-
-			const String& gpuVarName = iterFind->second;
-			Vector<TGpuParamLoadStoreTexture<Core>> gpuParams;
-
-			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				SPtr<TPassParameters<Core>> params = *iter;
-
-				for (UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsType& paramPtr = params->getParamByIdx(i);
-					if (paramPtr)
-					{
-						if (paramPtr->hasTexture(gpuVarName))
-						{
-							gpuParams.push_back(TGpuParamLoadStoreTexture<Core>());
-							paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams.back());
-						}
-					}
-				}
-			}
-
-			return TMaterialParamLoadStoreTexture<Core>(gpuParams);
-		}
+		TMaterialParamLoadStoreTexture<Core> getParamLoadStoreTexture(const String& name) const;
 
 
 		/**
 		/**
 		 * @brief	Returns a sampler state GPU parameter. This parameter may be used for
 		 * @brief	Returns a sampler state GPU parameter. This parameter may be used for
@@ -644,39 +521,7 @@ namespace BansheeEngine
 		 * 			
 		 * 			
 		 *			If material shader changes this handle will be invalidated.
 		 *			If material shader changes this handle will be invalidated.
 		 */
 		 */
-		TMaterialParamSampState<Core> getParamSamplerState(const String& name) const
-		{
-			throwIfNotInitialized();
-
-			auto iterFind = mValidParams.find(name);
-			if (iterFind == mValidParams.end())
-			{
-				LOGWRN("Material doesn't have a parameter named " + name);
-				return TMaterialParamSampState<Core>();
-			}
-
-			const String& gpuVarName = iterFind->second;
-			Vector<TGpuParamSampState<Core>> gpuParams;
-			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				SPtr<TPassParameters<Core>> params = *iter;
-
-				for (UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsType& paramPtr = params->getParamByIdx(i);
-					if (paramPtr)
-					{
-						if (paramPtr->hasSamplerState(gpuVarName))
-						{
-							gpuParams.push_back(TGpuParamSampState<Core>());
-							paramPtr->getSamplerStateParam(gpuVarName, gpuParams.back());
-						}
-					}
-				}
-			}
-
-			return TMaterialParamSampState<Core>(gpuParams);
-		}
+		TMaterialParamSampState<Core> getParamSamplerState(const String& name) const;
 
 
 		/**
 		/**
 		 * @brief	Returns a set of parameters for all GPU programs
 		 * @brief	Returns a set of parameters for all GPU programs
@@ -691,30 +536,7 @@ namespace BansheeEngine
 		 * 			potentially sharing parameters between multiple materials. This reduces driver overhead as the parameters
 		 * 			potentially sharing parameters between multiple materials. This reduces driver overhead as the parameters
 		 * 			in the buffers need only be set once and then reused multiple times.
 		 * 			in the buffers need only be set once and then reused multiple times.
 		 */
 		 */
-		void setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
-		{
-			auto iterFind = mValidShareableParamBlocks.find(name);
-			if (iterFind == mValidShareableParamBlocks.end())
-			{
-				LOGWRN("Material doesn't have a parameter block named " + name);
-				return;
-			}
-
-			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				SPtr<TPassParameters<Core>> params = *iter;
-
-				for (UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsType& paramPtr = params->getParamByIdx(i);
-					if (paramPtr)
-					{
-						if (paramPtr->hasParamBlock(name))
-							paramPtr->setParamBlockBuffer(name, paramBlock);
-					}
-				}
-			}
-		}
+		void setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock);
 
 
 	protected:
 	protected:
 		/**
 		/**
@@ -726,40 +548,7 @@ namespace BansheeEngine
 		 * 			caller to keep track of that.
 		 * 			caller to keep track of that.
 		 */
 		 */
 		template <typename T>
 		template <typename T>
-		void getParam(const String& name, TMaterialDataParam<T, Core>& output) const
-		{
-			throwIfNotInitialized();
-
-			auto iterFind = mValidParams.find(name);
-			if(iterFind == mValidParams.end())
-			{
-				LOGWRN("Material doesn't have a parameter named " + name);
-				return;
-			}
-
-			const String& gpuVarName = iterFind->second;
-			Vector<TGpuDataParam<T, Core>> gpuParams;
-
-			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				SPtr<TPassParameters<Core>> params = *iter;
-
-				for (UINT32 i = 0; i < params->getNumParams(); i++)
-				{
-					GpuParamsType& paramPtr = params->getParamByIdx(i);
-					if (paramPtr)
-					{
-						if (paramPtr->hasParam(gpuVarName))
-						{
-							gpuParams.push_back(TGpuDataParam<T, Core>());
-							paramPtr->getParam<T>(gpuVarName, gpuParams.back());
-						}
-					}
-				}
-			}
-
-			output = TMaterialDataParam<T, Core>(gpuParams);
-		}
+		void getParam(const String& name, TMaterialDataParam<T, Core>& output) const;
 
 
 		/**
 		/**
 		 * @brief	Initializes the material by using the best technique from the currently set shader. Shader
 		 * @brief	Initializes the material by using the best technique from the currently set shader. Shader
@@ -771,18 +560,7 @@ namespace BansheeEngine
 		 * @brief	Throw an exception if no shader is set, or no acceptable
 		 * @brief	Throw an exception if no shader is set, or no acceptable
 		 * 			technique was found.
 		 * 			technique was found.
 		 */
 		 */
-		void throwIfNotInitialized() const
-		{
-			if (mShader == nullptr)
-			{
-				BS_EXCEPT(InternalErrorException, "Material does not have shader set.");
-			}
-
-			if (mBestTechnique == nullptr)
-			{
-				BS_EXCEPT(InternalErrorException, "Shader does not contain a supported technique.");
-			}
-		}
+		void throwIfNotInitialized() const;
 
 
 		Vector<SPtr<TPassParameters<Core>>> mParametersPerPass;
 		Vector<SPtr<TPassParameters<Core>>> mParametersPerPass;
 		ShaderType mShader;
 		ShaderType mShader;
@@ -809,7 +587,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT Material : public Resource, public TMaterial<false>
 	class BS_CORE_EXPORT Material : public Resource, public TMaterial<false>
 	{
 	{
 	public:
 	public:
-		~Material();
+		~Material() { }
 
 
 		/**
 		/**
 		 * @brief	Retrieves an implementation of a material usable only from the
 		 * @brief	Retrieves an implementation of a material usable only from the
@@ -832,7 +610,7 @@ namespace BansheeEngine
 	private:
 	private:
 		friend class MaterialManager;
 		friend class MaterialManager;
 
 
-		Material();
+		Material() { }
 
 
 		/**
 		/**
 		 * @copydoc	CoreObject::createCore
 		 * @copydoc	CoreObject::createCore

+ 41 - 115
BansheeCore/Include/BsMaterialParam.h

@@ -15,52 +15,23 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialDataParam
 	class BS_CORE_EXPORT TMaterialDataParam
 	{
 	{
 	public:
 	public:
-		TMaterialDataParam(const Vector<TGpuDataParam<T, Core>>& params)
-			:mParams(params)
-		{ }
-
+		TMaterialDataParam(const Vector<TGpuDataParam<T, Core>>& params);
 		TMaterialDataParam() { }
 		TMaterialDataParam() { }
 		
 		
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 * @copydoc	TGpuDataParam::set
 		 */
 		 */
-		void set(const T& value, UINT32 arrayIdx = 0)
-		{
-			for (auto& param : mParams)
-				param.set(value, arrayIdx);
-		}
+		void set(const T& value, UINT32 arrayIdx = 0);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuDataParam::set
 		 * @copydoc	TGpuDataParam::set
 		 */
 		 */
-		T get(UINT32 arrayIdx = 0)
-		{
-			if (mParams.size() == 0)
-				return T();
-
-			return mParams[0].get(arrayIdx); // They should all have the same value
-		}
+		T get(UINT32 arrayIdx = 0);
 
 
 	protected:
 	protected:
 		Vector<TGpuDataParam<T, Core>> mParams;
 		Vector<TGpuDataParam<T, Core>> mParams;
 	};
 	};
 
 
-	typedef TMaterialDataParam<float, false> MaterialParamFloat;
-	typedef TMaterialDataParam<Color, false> MaterialParamColor;
-	typedef TMaterialDataParam<Vector2, false> MaterialParamVec2;
-	typedef TMaterialDataParam<Vector3, false> MaterialParamVec3;
-	typedef TMaterialDataParam<Vector4, false> MaterialParamVec4;
-	typedef TMaterialDataParam<Matrix3, false> MaterialParamMat3;
-	typedef TMaterialDataParam<Matrix4, false> MaterialParamMat4;
-
-	typedef TMaterialDataParam<float, true> MaterialParamFloatCore;
-	typedef TMaterialDataParam<Color, true> MaterialParamColorCore;
-	typedef TMaterialDataParam<Vector2, true> MaterialParamVec2Core;
-	typedef TMaterialDataParam<Vector3, true> MaterialParamVec3Core;
-	typedef TMaterialDataParam<Vector4, true> MaterialParamVec4Core;
-	typedef TMaterialDataParam<Matrix3, true> MaterialParamMat3Core;
-	typedef TMaterialDataParam<Matrix4, true> MaterialParamMat4Core;
-
 	/**
 	/**
 	 * @copydoc	TMaterialDataParam
 	 * @copydoc	TMaterialDataParam
 	 */
 	 */
@@ -68,53 +39,28 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterialParamStruct
 	class BS_CORE_EXPORT TMaterialParamStruct
 	{
 	{
 	public:
 	public:
-		TMaterialParamStruct(const Vector<TGpuParamStruct<Core>>& params)
-			:mParams(params)
-		{ }
-
+		TMaterialParamStruct(const Vector<TGpuParamStruct<Core>>& params);
 		TMaterialParamStruct() { }
 		TMaterialParamStruct() { }
 
 
 		/**
 		/**
 		 * @copydoc	TGpuParamStruct::set
 		 * @copydoc	TGpuParamStruct::set
 		 */
 		 */
-		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0)
-		{
-			for (auto& param : mParams)
-				param.set(value, sizeBytes, arrayIdx);
-		}
+		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuParamStruct::get
 		 * @copydoc	TGpuParamStruct::get
 		 */
 		 */
-		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0)
-		{
-			if (mParams.size() == 0)
-			{
-				value = nullptr;
-				return;
-			}
-
-			return mParams[0].get(value, sizeBytes, arrayIdx); // They should all have the same value
-		}
+		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
 
 
 		/**
 		/**
 		 * @copydoc	TGpuParamStruct::getElementSize
 		 * @copydoc	TGpuParamStruct::getElementSize
 		 */
 		 */
-		UINT32 getElementSize() const
-		{
-			if (mParams.size() == 0)
-				return 0;
-
-			return mParams[0].getElementSize();
-		}
+		UINT32 getElementSize() const;
 
 
 	protected:
 	protected:
 		Vector<TGpuParamStruct<Core>> mParams;
 		Vector<TGpuParamStruct<Core>> mParams;
 	};
 	};
 
 
-	typedef TMaterialParamStruct<false> MaterialParamStruct;
-	typedef TMaterialParamStruct<true> MaterialParamStructCore;
-
 	/**
 	/**
 	 * @copydoc	TMaterialDataParam
 	 * @copydoc	TMaterialDataParam
 	 */
 	 */
@@ -124,39 +70,23 @@ namespace BansheeEngine
 	public:
 	public:
 		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 
 
-		TMaterialParamTexture(const Vector<TGpuParamTexture<Core>>& params)
-			:mParams(params)
-		{ }
-
+		TMaterialParamTexture(const Vector<TGpuParamTexture<Core>>& params);
 		TMaterialParamTexture() { }
 		TMaterialParamTexture() { }
 
 
 		/**
 		/**
 		 * @copydoc	GpuParamTexture::set
 		 * @copydoc	GpuParamTexture::set
 		 */
 		 */
-		void set(const TextureType& texture)
-		{
-			for (auto& param : mParams)
-				param.set(texture);
-		}
+		void set(const TextureType& texture);
 
 
 		/**
 		/**
 		 * @copydoc	GpuParamTexture::get
 		 * @copydoc	GpuParamTexture::get
 		 */
 		 */
-		TextureType get()
-		{
-			if (mParams.size() == 0)
-				return TextureType();
-
-			return mParams[0].get(); // They should all have the same value
-		}
+		TextureType get();
 
 
 	protected:
 	protected:
 		Vector<TGpuParamTexture<Core>> mParams;
 		Vector<TGpuParamTexture<Core>> mParams;
 	};
 	};
 
 
-	typedef TMaterialParamTexture<false> MaterialParamTexture;
-	typedef TMaterialParamTexture<true> MaterialParamTextureCore;
-
 	/**
 	/**
 	 * @copydoc	TMaterialDataParam
 	 * @copydoc	TMaterialDataParam
 	 */
 	 */
@@ -166,39 +96,23 @@ namespace BansheeEngine
 	public:
 	public:
 		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 
 
-		TMaterialParamLoadStoreTexture(const Vector<TGpuParamLoadStoreTexture<Core>>& params)
-			:mParams(params)
-		{ }
-
+		TMaterialParamLoadStoreTexture(const Vector<TGpuParamLoadStoreTexture<Core>>& params);
 		TMaterialParamLoadStoreTexture() { }
 		TMaterialParamLoadStoreTexture() { }
 
 
 		/**
 		/**
 		 * @copydoc	GpuParamLoadStoreTexture::set
 		 * @copydoc	GpuParamLoadStoreTexture::set
 		 */
 		 */
-		void set(const TextureType& texture, const TextureSurface& surface)
-		{
-			for (auto& param : mParams)
-				param.set(texture, surface);
-		}
+		void set(const TextureType& texture, const TextureSurface& surface);
 
 
 		/**
 		/**
 		 * @copydoc	GpuParamLoadStoreTexture::get
 		 * @copydoc	GpuParamLoadStoreTexture::get
 		 */
 		 */
-		TextureType get()
-		{
-			if (mParams.size() == 0)
-				return TextureType();
-
-			return mParams[0].get(); // They should all have the same value
-		}
+		TextureType get();
 
 
 	protected:
 	protected:
 		Vector<TGpuParamLoadStoreTexture<Core>> mParams;
 		Vector<TGpuParamLoadStoreTexture<Core>> mParams;
 	};
 	};
 
 
-	typedef TMaterialParamLoadStoreTexture<false> MaterialParamLoadStoreTexture;
-	typedef TMaterialParamLoadStoreTexture<true> MaterialParamLoadStoreTextureCore;
-
 	/**
 	/**
 	 * @copydoc	TMaterialDataParam
 	 * @copydoc	TMaterialDataParam
 	 */
 	 */
@@ -208,36 +122,48 @@ namespace BansheeEngine
 	public:
 	public:
 		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerType;
 		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerType;
 
 
-		TMaterialParamSampState(const Vector<TGpuParamSampState<Core>>& params)
-			:mParams(params)
-		{ }
-
+		TMaterialParamSampState(const Vector<TGpuParamSampState<Core>>& params);
 		TMaterialParamSampState() { }
 		TMaterialParamSampState() { }
 
 
 		/**
 		/**
 		 * @copydoc	GpuParamSampState::set
 		 * @copydoc	GpuParamSampState::set
 		 */
 		 */
-		void set(const SamplerType& sampState)
-		{
-			for (auto& param : mParams)
-				param.set(sampState);
-		}
+		void set(const SamplerType& sampState);
 
 
 		/**
 		/**
 		 * @copydoc	GpuParamSampState::get
 		 * @copydoc	GpuParamSampState::get
 		 */
 		 */
-		SamplerType get()
-		{
-			if (mParams.size() == 0)
-				return SamplerType();
-
-			return mParams[0].get(); // They should all have the same value
-		}
+		SamplerType get();
 
 
 	protected:
 	protected:
 		Vector<TGpuParamSampState<Core>> mParams;
 		Vector<TGpuParamSampState<Core>> mParams;
 	};
 	};
 
 
+	typedef TMaterialDataParam<float, false> MaterialParamFloat;
+	typedef TMaterialDataParam<Color, false> MaterialParamColor;
+	typedef TMaterialDataParam<Vector2, false> MaterialParamVec2;
+	typedef TMaterialDataParam<Vector3, false> MaterialParamVec3;
+	typedef TMaterialDataParam<Vector4, false> MaterialParamVec4;
+	typedef TMaterialDataParam<Matrix3, false> MaterialParamMat3;
+	typedef TMaterialDataParam<Matrix4, false> MaterialParamMat4;
+
+	typedef TMaterialDataParam<float, true> MaterialParamFloatCore;
+	typedef TMaterialDataParam<Color, true> MaterialParamColorCore;
+	typedef TMaterialDataParam<Vector2, true> MaterialParamVec2Core;
+	typedef TMaterialDataParam<Vector3, true> MaterialParamVec3Core;
+	typedef TMaterialDataParam<Vector4, true> MaterialParamVec4Core;
+	typedef TMaterialDataParam<Matrix3, true> MaterialParamMat3Core;
+	typedef TMaterialDataParam<Matrix4, true> MaterialParamMat4Core;
+
+	typedef TMaterialParamStruct<false> MaterialParamStruct;
+	typedef TMaterialParamStruct<true> MaterialParamStructCore;
+
+	typedef TMaterialParamTexture<false> MaterialParamTexture;
+	typedef TMaterialParamTexture<true> MaterialParamTextureCore;
+
+	typedef TMaterialParamLoadStoreTexture<false> MaterialParamLoadStoreTexture;
+	typedef TMaterialParamLoadStoreTexture<true> MaterialParamLoadStoreTextureCore;
+
 	typedef TMaterialParamSampState<false> MaterialParamSampState;
 	typedef TMaterialParamSampState<false> MaterialParamSampState;
 	typedef TMaterialParamSampState<true> MaterialParamSampStateCore;
 	typedef TMaterialParamSampState<true> MaterialParamSampStateCore;
 }
 }

+ 3 - 17
BansheeCore/Include/BsPass.h

@@ -1,7 +1,6 @@
 #pragma once
 #pragma once
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
-#include "BsCoreThreadAccessor.h"
 #include "BsColor.h"
 #include "BsColor.h"
 #include "BsIReflectable.h"
 #include "BsIReflectable.h"
 #include "BsCoreObject.h"
 #include "BsCoreObject.h"
@@ -75,16 +74,6 @@ namespace BansheeEngine
 		 * @copydoc	CoreObject::markCoreDirty
 		 * @copydoc	CoreObject::markCoreDirty
 		 */
 		 */
 		virtual void _markCoreDirty() { }
 		virtual void _markCoreDirty() { }
-
-		/**
-		 * @brief	Returns true if the provided blend state has some element of transparency.
-		 */
-		static bool hasBlending(const HBlendState& blendState);
-
-		/**
-		 * @brief	Returns true if the provided blend state has some element of transparency.
-		 */
-		static bool hasBlending(const SPtr<BlendStateCore>& blendState);
 	};
 	};
 
 
 	/**
 	/**
@@ -93,7 +82,7 @@ namespace BansheeEngine
 	 * @note	Templated so it can be used for both core and non-core versions of a pass.
 	 * @note	Templated so it can be used for both core and non-core versions of a pass.
 	 */
 	 */
 	template<bool Core>
 	template<bool Core>
-	class TPass : public PassBase
+	class BS_CORE_EXPORT TPass : public PassBase
     {
     {
     public:
     public:
 		typedef typename PassData<Core>::BlendStateType BlendStateType;
 		typedef typename PassData<Core>::BlendStateType BlendStateType;
@@ -113,7 +102,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Returns true if this pass has some element of transparency.
 		 * @brief	Returns true if this pass has some element of transparency.
 		 */
 		 */
-		bool hasBlending() const { return PassBase::hasBlending(mData.mBlendState); }
+		bool hasBlending() const;
 
 
 		void setBlendState(const BlendStateType& blendState) { mData.mBlendState = blendState; _markCoreDirty(); }
 		void setBlendState(const BlendStateType& blendState) { mData.mBlendState = blendState; _markCoreDirty(); }
 		BlendStateType getBlendState() const { return mData.mBlendState; }
 		BlendStateType getBlendState() const { return mData.mBlendState; }
@@ -155,10 +144,7 @@ namespace BansheeEngine
 		const GpuProgramType& getComputeProgram(void) const { return mData.mComputeProgram; }
 		const GpuProgramType& getComputeProgram(void) const { return mData.mComputeProgram; }
 
 
 	protected:
 	protected:
-		TPass()
-		{
-			mData.mStencilRefValue = 0;
-		}
+		TPass();
 
 
 		PassData<Core> mData;
 		PassData<Core> mData;
     };
     };

+ 6 - 60
BansheeCore/Include/BsShader.h

@@ -222,21 +222,6 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual void _markCoreDirty() { }
 		virtual void _markCoreDirty() { }
 
 
-		/**
-		 * @copydoc	Technique::isSupported
-		 */
-		bool isTechniqueSupported(const SPtr<Technique> technique) const;
-
-		/**
-		 * @copydoc	Technique::isSupported
-		 */
-		bool isTechniqueSupported(const SPtr<TechniqueCore> technique) const;
-
-		/**
-		 * @brief	Checks is the index between 0 and provided bound and throws an exception if its not.
-		 */
-		void checkBounds(UINT32 idx, UINT32 bound) const;
-
 		QueueSortType mQueueSortType;
 		QueueSortType mQueueSortType;
 		UINT32 mQueuePriority;
 		UINT32 mQueuePriority;
 		bool mSeparablePasses;
 		bool mSeparablePasses;
@@ -255,7 +240,7 @@ namespace BansheeEngine
 	 *			sim and core thread variants.
 	 *			sim and core thread variants.
 	 */
 	 */
 	template<bool Core>
 	template<bool Core>
-	class TShader : public ShaderBase
+	class BS_CORE_EXPORT TShader : public ShaderBase
 	{
 	{
 	public:
 	public:
 		template<bool Core> struct TTechniqueType {};
 		template<bool Core> struct TTechniqueType {};
@@ -264,44 +249,18 @@ namespace BansheeEngine
 
 
 		typedef typename TTechniqueType<Core>::Type TechniqueType;
 		typedef typename TTechniqueType<Core>::Type TechniqueType;
 
 
-		TShader(const String& name)
-			:ShaderBase(name)
-		{ }
-
-		virtual ~TShader() { }
+		TShader(const String& name);
+		virtual ~TShader();
 	
 	
 		/**
 		/**
 		 * @brief	Removes a technique at the specified index.
 		 * @brief	Removes a technique at the specified index.
 		 */
 		 */
-		void removeTechnique(UINT32 idx)
-		{
-			checkBounds(idx, (UINT32)mTechniques.size());
-
-			int count = 0;
-			auto iter = mTechniques.begin();
-			while (count != idx)
-			{
-				++count;
-				++iter;
-			}
-
-			mTechniques.erase(iter);
-			_markCoreDirty();
-		}
+		void removeTechnique(UINT32 idx);
 
 
 		/**
 		/**
 		 * @brief	Removes the specified technique.
 		 * @brief	Removes the specified technique.
 		 */
 		 */
-		void removeTechnique(SPtr<TechniqueType> technique)
-		{
-			auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
-
-			if (iterFind != mTechniques.end())
-			{
-				mTechniques.erase(iterFind);
-				_markCoreDirty();
-			}
-		}
+		void removeTechnique(SPtr<TechniqueType> technique);
 
 
 		/**
 		/**
 		 * @brief	Returns the total number of techniques in this shader.
 		 * @brief	Returns the total number of techniques in this shader.
@@ -312,20 +271,7 @@ namespace BansheeEngine
 		 * @brief	Gets the best supported technique based on current render and other systems.
 		 * @brief	Gets the best supported technique based on current render and other systems.
 		 * 			Returns null if not a single technique is supported.
 		 * 			Returns null if not a single technique is supported.
 		 */
 		 */
-		SPtr<TechniqueType> getBestTechnique() const
-		{
-			for (auto iter = mTechniques.begin(); iter != mTechniques.end(); ++iter)
-			{
-				if (isTechniqueSupported(*iter))
-				{
-					return *iter;
-				}
-			}
-
-			return nullptr;
-
-			// TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
-		}
+		SPtr<TechniqueType> getBestTechnique() const;
 
 
 	protected:
 	protected:
 		Vector<SPtr<TechniqueType>> mTechniques;
 		Vector<SPtr<TechniqueType>> mTechniques;

+ 3 - 30
BansheeCore/Include/BsTechnique.h

@@ -28,11 +28,6 @@ namespace BansheeEngine
 		bool isSupported() const;
 		bool isSupported() const;
 
 
 	protected:
 	protected:
-		/**
-		 * @brief	Checks is the index between 0 and provided bound and throws an exception if its not.
-		 */
-		void checkBounds(UINT32 idx, UINT32 bound) const;
-
 		/**
 		/**
 		 * @copydoc	CoreObject::markCoreDirty
 		 * @copydoc	CoreObject::markCoreDirty
 		 */
 		 */
@@ -58,40 +53,18 @@ namespace BansheeEngine
 
 
 		typedef typename TPassType<Core>::Type PassType;
 		typedef typename TPassType<Core>::Type PassType;
 		
 		
-		TTechnique(const String& renderSystem, const String& renderer)
-			:TechniqueBase(renderSystem, renderer)
-		{ }
-
+		TTechnique(const String& renderSystem, const String& renderer);
 		virtual ~TTechnique() { }
 		virtual ~TTechnique() { }
 
 
 		/**
 		/**
 		 * @brief	Removes a pass with the specified index.
 		 * @brief	Removes a pass with the specified index.
 		 */
 		 */
-		void removePass(UINT32 idx)
-		{
-			checkBounds(idx, (UINT32)mPasses.size());
-
-			int count = 0;
-			auto iter = mPasses.begin();
-			while (count != idx)
-			{
-				++count;
-				++iter;
-			}
-
-			mPasses.erase(iter);
-			_markCoreDirty();
-		}
+		void removePass(UINT32 idx);
 
 
 		/**
 		/**
 		 * @brief	Returns a pass with the specified index.
 		 * @brief	Returns a pass with the specified index.
 		 */
 		 */
-		SPtr<PassType> getPass(UINT32 idx) const
-		{
-			checkBounds(idx, (UINT32)mPasses.size());
-
-			return mPasses[idx];
-		}
+		SPtr<PassType> getPass(UINT32 idx) const;
 
 
 		/**
 		/**
 		 * @brief	Returns total number of passes.
 		 * @brief	Returns total number of passes.

+ 221 - 137
BansheeCore/Source/BsGpuParam.cpp

@@ -1,214 +1,298 @@
 #include "BsGpuParam.h"
 #include "BsGpuParam.h"
 #include "BsGpuParams.h"
 #include "BsGpuParams.h"
 #include "BsGpuParamBlockBuffer.h"
 #include "BsGpuParamBlockBuffer.h"
+#include "BsGpuParamDesc.h"
+#include "BsDebug.h"
+#include "BsException.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	/************************************************************************/
-	/* 							GPU PARAMS BASE                      		*/
-	/************************************************************************/
-
-	GpuParamBase::GpuParamBase()
+	template<class T, bool Core>
+	TGpuDataParam<T, Core>::TGpuDataParam()
+		:mParamDesc(nullptr)
 	{ }
 	{ }
 
 
-	GpuParamBase::GpuParamBase(const SPtr<GpuParams>& parent)
-		:mParent(parent)
+	template<class T, bool Core>
+	TGpuDataParam<T, Core>::TGpuDataParam(GpuParamDataDesc* paramDesc, const GpuParamsType& parent)
+		:mParamDesc(paramDesc), mParent(parent)
 	{ }
 	{ }
 
 
-	void GpuParamBase::markCoreDirty()
+	template<class T, bool Core>
+	void TGpuDataParam<T, Core>::set(const T& value, UINT32 arrayIdx)
 	{
 	{
-		mParent->_markCoreDirty();
-	}
-
-	/************************************************************************/
-	/* 							GPU DATA PARAMS BASE                      	*/
-	/************************************************************************/
+		if (mParent == nullptr)
+			return;
 
 
-	GpuDataParamBase::GpuDataParamBase()
-		: GpuParamBase(), mParamDesc(nullptr)
-	{ }
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		if (paramBlock == nullptr)
+			return;
 
 
-	GpuDataParamBase::GpuDataParamBase(GpuParamDataDesc* paramDesc, const SPtr<GpuParams>& parent)
-		: GpuParamBase(parent), mParamDesc(paramDesc)
-	{ }
+#if BS_DEBUG_MODE
+		if (arrayIdx >= mParamDesc->arraySize)
+		{
+			BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
+				toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+		}
+#endif
+
+		UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
+		UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T)); // Truncate if it doesn't fit within parameter size
+
+		if (TransposePolicy<T>::transposeEnabled(mParent->getTransposeMatrices()))
+		{
+			T transposed = TransposePolicy<T>::transpose(value);
+			paramBlock->write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &transposed, sizeBytes);
+		}
+		else
+			paramBlock->write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
+
+		// Set unused bytes to 0
+		if (sizeBytes < elementSizeBytes)
+		{
+			UINT32 diffSize = elementSizeBytes - sizeBytes;
+			paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32) + sizeBytes, diffSize);
+		}
 
 
-	bool GpuDataParamBase::getTransposeMatrices() const
-	{
-		return mParent->getTransposeMatrices();
+		mParent->_markCoreDirty();
 	}
 	}
 
 
-	bool GpuDataParamBase::write(UINT32 offset, const void* data, UINT32 size)
+	template<class T, bool Core>
+	T TGpuDataParam<T, Core>::get(UINT32 arrayIdx)
 	{
 	{
-		GpuParamBlockBufferPtr paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
-		if (paramBlock == nullptr)
-			return false;
+		if (mParent == nullptr)
+			return T();
 
 
-		paramBlock->write(offset, data, size);
-		return true;
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		if (paramBlock == nullptr)
+			return T();
+
+#if BS_DEBUG_MODE
+		if (arrayIdx >= mParamDesc->arraySize)
+		{
+			BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
+				toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+		}
+#endif
+
+		UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
+		UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T));
+
+		T value;
+		paramBlock->read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);
+
+		if (TransposePolicy<T>::transposeEnabled(mParent->getTransposeMatrices()))
+			return TransposePolicy<T>::transpose(value);
+		else
+			return value;
 	}
 	}
 
 
-	bool GpuDataParamBase::read(UINT32 offset, void* data, UINT32 size)
-	{
-		GpuParamBlockBufferPtr paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
-		if (paramBlock == nullptr)
-			return false;
+	template<bool Core>
+	TGpuParamStruct<Core>::TGpuParamStruct()
+		:mParamDesc(nullptr)
+	{ }
 
 
-		paramBlock->read(offset, data, size);
-		return true;
-	}
+	template<bool Core>
+	TGpuParamStruct<Core>::TGpuParamStruct(GpuParamDataDesc* paramDesc, const GpuParamsType& parent)
+		:mParamDesc(paramDesc), mParent(parent)
+	{ }
 
 
-	void GpuDataParamBase::zeroOut(UINT32 offset, UINT32 size)
+	template<bool Core>
+	void TGpuParamStruct<Core>::set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx)
 	{
 	{
-		GpuParamBlockBufferPtr paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		if (mParent == nullptr)
+			return;
+
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
 		if (paramBlock == nullptr)
 		if (paramBlock == nullptr)
 			return;
 			return;
 
 
-		paramBlock->zeroOut(offset, size);
-	}
+		UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
 
 
-	/************************************************************************/
-	/* 						GPU OBJECT PARAMS BASE                      	*/
-	/************************************************************************/
+#if BS_DEBUG_MODE
+		if (sizeBytes > elementSizeBytes)
+		{
+			LOGWRN("Provided element size larger than maximum element size. Maximum size: " +
+				toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
+		}
 
 
-	GpuObjectParamBase::GpuObjectParamBase()
-		: GpuParamBase(), mParamDesc(nullptr)
-	{ }
+		if (arrayIdx >= mParamDesc->arraySize)
+		{
+			BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
+				toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+		}
+#endif
 
 
-	GpuObjectParamBase::GpuObjectParamBase(GpuParamObjectDesc* paramDesc, const SPtr<GpuParams>& parent)
-		: GpuParamBase(parent), mParamDesc(paramDesc)
-	{ }
+		sizeBytes = std::min(elementSizeBytes, sizeBytes);
 
 
-	HTexture GpuObjectParamBase::getTexture(UINT32 slot)
-	{
-		return mParent->getTexture(slot);
-	}
+		paramBlock->write((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
 
 
-	HSamplerState GpuObjectParamBase::getSamplerState(UINT32 slot)
-	{
-		return mParent->getSamplerState(slot);
-	}
+		// Set unused bytes to 0
+		if (sizeBytes < elementSizeBytes)
+		{
+			UINT32 diffSize = elementSizeBytes - sizeBytes;
+			paramBlock->zeroOut((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride)  * sizeof(UINT32) + sizeBytes, diffSize);
+		}
 
 
-	void GpuObjectParamBase::setTexture(UINT32 slot, const HTexture& texture)
-	{
-		mParent->setTexture(slot, texture);
+		mParent->_markCoreDirty();
 	}
 	}
 
 
-	void GpuObjectParamBase::setSamplerState(UINT32 slot, const HSamplerState& sampler)
+	template<bool Core>
+	void TGpuParamStruct<Core>::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx)
 	{
 	{
-		mParent->setSamplerState(slot, sampler);
-	}
+		if (mParent == nullptr)
+			return;
 
 
-	void GpuObjectParamBase::setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const
-	{
-		mParent->setLoadStoreSurface(slot, surface);
-	}
+		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
+		if (paramBlock == nullptr)
+			return;
 
 
-	void GpuObjectParamBase::setIsLoadStoreTexture(UINT32 slot, bool isLoadStore)
-	{
-		mParent->setIsLoadStoreTexture(slot, isLoadStore);
-	}
+		UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
 
 
-	/************************************************************************/
-	/* 							GPU PARAMS CORE BASE                      	*/
-	/************************************************************************/
+#if BS_DEBUG_MODE
+		if (sizeBytes > elementSizeBytes)
+		{
+			LOGWRN("Provided element size larger than maximum element size. Maximum size: " +
+				toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
+		}
 
 
-	GpuParamCoreBase::GpuParamCoreBase()
-	{ }
+		if (arrayIdx >= mParamDesc->arraySize)
+		{
+			BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
+				toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
+		}
+#endif
+		sizeBytes = std::min(elementSizeBytes, sizeBytes);
 
 
-	GpuParamCoreBase::GpuParamCoreBase(const SPtr<GpuParamsCore>& parent)
-		:mParent(parent)
-	{ }
+		paramBlock->read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
+	}
 
 
-	void GpuParamCoreBase::markCoreDirty()
+	template<bool Core>
+	UINT32 TGpuParamStruct<Core>::getElementSize() const
 	{
 	{
-		mParent->_markCoreDirty();
-	}
+		if (mParent == nullptr)
+			return 0;
 
 
-	/************************************************************************/
-	/* 						GPU DATA PARAMS CORE BASE                      	*/
-	/************************************************************************/
+		return mParamDesc->elementSize * sizeof(UINT32);
+	}
 
 
-	GpuDataParamCoreBase::GpuDataParamCoreBase()
-		: GpuParamCoreBase(), mParamDesc(nullptr)
+	template<bool Core>
+	TGpuParamTexture<Core>::TGpuParamTexture()
+		:mParamDesc(nullptr)
 	{ }
 	{ }
 
 
-	GpuDataParamCoreBase::GpuDataParamCoreBase(GpuParamDataDesc* paramDesc, const SPtr<GpuParamsCore>& parent)
-		: GpuParamCoreBase(parent), mParamDesc(paramDesc)
+	template<bool Core>
+	TGpuParamTexture<Core>::TGpuParamTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent)
+		:mParamDesc(paramDesc), mParent(parent)
 	{ }
 	{ }
 
 
-	bool GpuDataParamCoreBase::getTransposeMatrices() const
+	template<bool Core>
+	void TGpuParamTexture<Core>::set(const TextureType& texture)
 	{
 	{
-		return mParent->getTransposeMatrices();
-	}
+		if (mParent == nullptr)
+			return;
 
 
-	bool GpuDataParamCoreBase::write(UINT32 offset, const void* data, UINT32 size)
-	{
-		SPtr<GpuParamBlockBufferCore> paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
-		if (paramBlock == nullptr)
-			return false;
+		mParent->setTexture(mParamDesc->slot, texture);
+		mParent->setIsLoadStoreTexture(mParamDesc->slot, false);
 
 
-		paramBlock->write(offset, data, size);
-		return true;
+		mParent->_markCoreDirty();
 	}
 	}
 
 
-	bool GpuDataParamCoreBase::read(UINT32 offset, void* data, UINT32 size)
+	template<bool Core>
+	typename TGpuParamTexture<Core>::TextureType TGpuParamTexture<Core>::get()
 	{
 	{
-		SPtr<GpuParamBlockBufferCore> paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
-		if (paramBlock == nullptr)
-			return false;
+		if (mParent == nullptr)
+			return TextureType();
 
 
-		paramBlock->read(offset, data, size);
-		return true;
+		return mParent->getTexture(mParamDesc->slot);
 	}
 	}
 
 
-	void GpuDataParamCoreBase::zeroOut(UINT32 offset, UINT32 size)
+	template<bool Core>
+	TGpuParamLoadStoreTexture<Core>::TGpuParamLoadStoreTexture()
+		:mParamDesc(nullptr)
+	{ }
+
+	template<bool Core>
+	TGpuParamLoadStoreTexture<Core>::TGpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent)
+		:mParamDesc(paramDesc), mParent(parent)
+	{ }
+
+	template<bool Core>
+	void TGpuParamLoadStoreTexture<Core>::set(const TextureType& texture, const TextureSurface& surface)
 	{
 	{
-		SPtr<GpuParamBlockBufferCore> paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSlot);
-		if (paramBlock == nullptr)
+		if (mParent == nullptr)
 			return;
 			return;
 
 
-		paramBlock->zeroOut(offset, size);
+		mParent->setTexture(mParamDesc->slot, texture);
+		mParent->setIsLoadStoreTexture(mParamDesc->slot, true);
+		mParent->setLoadStoreSurface(mParamDesc->slot, surface);
+
+		mParent->_markCoreDirty();
 	}
 	}
 
 
-	/************************************************************************/
-	/* 						GPU OBJECT PARAMS CORE BASE                    	*/
-	/************************************************************************/
+	template<bool Core>
+	typename TGpuParamLoadStoreTexture<Core>::TextureType TGpuParamLoadStoreTexture<Core>::get()
+	{
+		if (mParent == nullptr)
+			return TextureType();
 
 
-	GpuObjectParamCoreBase::GpuObjectParamCoreBase()
-		: GpuParamCoreBase(), mParamDesc(nullptr)
+		return mParent->getTexture(mParamDesc->slot);
+	}
+
+	template<bool Core>
+	TGpuParamSampState<Core>::TGpuParamSampState()
+		:mParamDesc(nullptr)
 	{ }
 	{ }
 
 
-	GpuObjectParamCoreBase::GpuObjectParamCoreBase(GpuParamObjectDesc* paramDesc, const SPtr<GpuParamsCore>& parent)
-		: GpuParamCoreBase(parent), mParamDesc(paramDesc)
+	template<bool Core>
+	TGpuParamSampState<Core>::TGpuParamSampState(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent)
+		:mParamDesc(paramDesc), mParent(parent)
 	{ }
 	{ }
 
 
-	SPtr<TextureCore> GpuObjectParamCoreBase::getTexture(UINT32 slot)
+	template<bool Core>
+	void TGpuParamSampState<Core>::set(const SamplerStateType& samplerState)
 	{
 	{
-		return mParent->getTexture(slot);
-	}
+		if (mParent == nullptr)
+			return;
 
 
-	SPtr<SamplerStateCore> GpuObjectParamCoreBase::getSamplerState(UINT32 slot)
-	{
-		return mParent->getSamplerState(slot);
-	}
+		mParent->setSamplerState(mParamDesc->slot, samplerState);
 
 
-	void GpuObjectParamCoreBase::setTexture(UINT32 slot, const SPtr<TextureCore>& texture)
-	{
-		mParent->setTexture(slot, texture);
+		mParent->_markCoreDirty();
 	}
 	}
 
 
-	void GpuObjectParamCoreBase::setSamplerState(UINT32 slot, const SPtr<SamplerStateCore>& sampler)
+	template<bool Core>
+	typename TGpuParamSampState<Core>::SamplerStateType TGpuParamSampState<Core>::get()
 	{
 	{
-		mParent->setSamplerState(slot, sampler);
-	}
+		if (mParent == nullptr)
+			return SamplerStateType();
 
 
-	void GpuObjectParamCoreBase::setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const
-	{
-		mParent->setLoadStoreSurface(slot, surface);
+		return mParent->getSamplerState(mParamDesc->slot);
 	}
 	}
 
 
-	void GpuObjectParamCoreBase::setIsLoadStoreTexture(UINT32 slot, bool isLoadStore)
-	{
-		mParent->setIsLoadStoreTexture(slot, isLoadStore);
-	}
+	template class TGpuDataParam < float, false > ;
+	template class TGpuDataParam < Color, false > ;
+	template class TGpuDataParam < Vector2, false > ;
+	template class TGpuDataParam < Vector3, false > ;
+	template class TGpuDataParam < Vector4, false > ;
+	template class TGpuDataParam < Matrix3, false > ;
+	template class TGpuDataParam < Matrix4, false > ;
+
+	template class TGpuDataParam < float, true > ;
+	template class TGpuDataParam < Color, true > ;
+	template class TGpuDataParam < Vector2, true > ;
+	template class TGpuDataParam < Vector3, true > ;
+	template class TGpuDataParam < Vector4, true > ;
+	template class TGpuDataParam < Matrix3, true > ;
+	template class TGpuDataParam < Matrix4, true > ;
+
+	template class TGpuParamStruct < false > ;
+	template class TGpuParamStruct < true > ;
+
+	template class TGpuParamTexture < false > ;
+	template class TGpuParamTexture < true > ;
+
+	template class TGpuParamSampState < false > ;
+	template class TGpuParamSampState < true > ;
+
+	template class TGpuParamLoadStoreTexture < false > ;
+	template class TGpuParamLoadStoreTexture < true > ;
 }
 }

+ 219 - 0
BansheeCore/Source/BsGpuParams.cpp

@@ -134,12 +134,226 @@ UINT32 GpuParamsBase::getDataParamSize(const String& name) const
 		mTextureInfo[slot].surface = surface;
 		mTextureInfo[slot].surface = surface;
 	}
 	}
 
 
+	template<bool Core>
+	TGpuParams<Core>::TGpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices)
+		:GpuParamsBase(paramDesc, transposeMatrices), mParamBlockBuffers(nullptr), mTextures(nullptr),
+		mSamplerStates(nullptr)
+	{
+		mParamBlockBuffers = bs_newN<ParamsBufferType>(mNumParamBlocks);
+		mTextures = bs_newN<TextureType>(mNumTextures);
+		mSamplerStates = bs_newN<SamplerType>(mNumSamplerStates);
+	}
+
+	template<bool Core>
+	TGpuParams<Core>::~TGpuParams()
+	{
+		bs_deleteN(mParamBlockBuffers, mNumParamBlocks);
+		bs_deleteN(mTextures, mNumTextures);
+		bs_deleteN(mSamplerStates, mNumSamplerStates);
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::setParamBlockBuffer(UINT32 slot, const ParamsBufferType& paramBlockBuffer)
+	{
+		if (slot < 0 || slot >= mNumParamBlocks)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mNumParamBlocks - 1) + ". Requested: " + toString(slot));
+		}
+
+		mParamBlockBuffers[slot] = paramBlockBuffer;
+
+		_markCoreDirty();
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::setParamBlockBuffer(const String& name, const ParamsBufferType& paramBlockBuffer)
+	{
+		auto iterFind = mParamDesc->paramBlocks.find(name);
+
+		if (iterFind == mParamDesc->paramBlocks.end())
+		{
+			LOGWRN("Cannot find parameter block with the name: " + name);
+			return;
+		}
+
+		mParamBlockBuffers[iterFind->second.slot] = paramBlockBuffer;
+
+		_markCoreDirty();
+	}
+
+	template<class T> struct TDataParamInfo { };
+	template<> struct TDataParamInfo < float > { enum { TypeId = GPDT_FLOAT1 }; };
+	template<> struct TDataParamInfo < Color > { enum { TypeId = GPDT_FLOAT4 }; };
+	template<> struct TDataParamInfo < Vector2 > { enum { TypeId = GPDT_FLOAT2 }; };
+	template<> struct TDataParamInfo < Vector3 > { enum { TypeId = GPDT_FLOAT3 }; };
+	template<> struct TDataParamInfo < Vector4 > { enum { TypeId = GPDT_FLOAT4 }; };
+	template<> struct TDataParamInfo < Matrix3 > { enum { TypeId = GPDT_MATRIX_3X3 }; };
+	template<> struct TDataParamInfo < Matrix4 > { enum { TypeId = GPDT_MATRIX_4X4 }; };
+
+	template<bool Core>
+	template<class T> 
+	void TGpuParams<Core>::getParam(const String& name, TGpuDataParam<T, Core>& output) const
+	{
+		auto iterFind = mParamDesc->params.find(name);
+
+		if (iterFind == mParamDesc->params.end())
+		{
+			output = TGpuDataParam<T, Core>(&iterFind->second, nullptr);
+			LOGWRN("Cannot find parameter with the name '" + name + "'");
+		}
+		else
+			output = TGpuDataParam<T, Core>(&iterFind->second, _getThisPtr());
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::getStructParam(const String& name, TGpuParamStruct<Core>& output) const
+	{
+		auto iterFind = mParamDesc->params.find(name);
+
+		if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_STRUCT)
+		{
+			output = TGpuParamStruct<Core>(&iterFind->second, nullptr);
+			LOGWRN("Cannot find struct parameter with the name '" + name + "'");
+		}
+		else
+			output = TGpuParamStruct<Core>(&iterFind->second, _getThisPtr());
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::getTextureParam(const String& name, TGpuParamTexture<Core>& output) const
+	{
+		auto iterFind = mParamDesc->textures.find(name);
+
+		if (iterFind == mParamDesc->textures.end())
+		{
+			output = TGpuParamTexture<Core>(&iterFind->second, nullptr);
+			LOGWRN("Cannot find texture parameter with the name '" + name + "'");
+		}
+		else
+			output = TGpuParamTexture<Core>(&iterFind->second, _getThisPtr());
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::getLoadStoreTextureParam(const String& name, TGpuParamLoadStoreTexture<Core>& output) const
+	{
+		auto iterFind = mParamDesc->textures.find(name);
+
+		if (iterFind == mParamDesc->textures.end())
+		{
+			output = TGpuParamLoadStoreTexture<Core>(&iterFind->second, nullptr);
+			LOGWRN("Cannot find texture parameter with the name '" + name + "'");
+		}
+		else
+			output = TGpuParamLoadStoreTexture<Core>(&iterFind->second, _getThisPtr());
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::getSamplerStateParam(const String& name, TGpuParamSampState<Core>& output) const
+	{
+		auto iterFind = mParamDesc->samplers.find(name);
+
+		if (iterFind == mParamDesc->samplers.end())
+		{
+			output = TGpuParamSampState<Core>(&iterFind->second, nullptr);
+			LOGWRN("Cannot find sampler state parameter with the name '" + name + "'");
+		}
+		else
+			output = TGpuParamSampState<Core>(&iterFind->second, _getThisPtr());
+	}
+
+	template<bool Core>
+	typename TGpuParams<Core>::ParamsBufferType TGpuParams<Core>::getParamBlockBuffer(UINT32 slot) const
+	{
+		if (slot < 0 || slot >= mNumParamBlocks)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mNumParamBlocks - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mParamBlockBuffers[slot];
+	}
+
+	template<bool Core>
+	typename TGpuParams<Core>::TextureType TGpuParams<Core>::getTexture(UINT32 slot)
+	{
+		if (slot < 0 || slot >= mNumTextures)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mNumTextures - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mTextures[slot];
+	}
+
+	template<bool Core>
+	typename TGpuParams<Core>::SamplerType TGpuParams<Core>::getSamplerState(UINT32 slot)
+	{
+		if (slot < 0 || slot >= mNumSamplerStates)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mNumSamplerStates - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mSamplerStates[slot];
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::setTexture(UINT32 slot, const TextureType& texture)
+	{
+		if (slot < 0 || slot >= mNumTextures)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mNumTextures - 1) + ". Requested: " + toString(slot));
+		}
+
+		mTextures[slot] = texture;
+		_markCoreDirty();
+	}
+
+	template<bool Core>
+	void TGpuParams<Core>::setSamplerState(UINT32 slot, const SamplerType& sampler)
+	{
+		if (slot < 0 || slot >= mNumSamplerStates)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mNumSamplerStates - 1) + ". Requested: " + toString(slot));
+		}
+
+		mSamplerStates[slot] = sampler;
+		_markCoreDirty();
+	}
+
+	template class TGpuParams < false > ;
+	template class TGpuParams < true > ;
+
+	template BS_CORE_EXPORT void TGpuParams<false>::getParam<float>(const String&, TGpuDataParam<float, false>&) const;
+	template BS_CORE_EXPORT void TGpuParams<false>::getParam<Color>(const String&, TGpuDataParam<Color, false>&) const;
+	template BS_CORE_EXPORT void TGpuParams<false>::getParam<Vector2>(const String&, TGpuDataParam<Vector2, false>&) const;
+	template BS_CORE_EXPORT void TGpuParams<false>::getParam<Vector3>(const String&, TGpuDataParam<Vector3, false>&) const;
+	template BS_CORE_EXPORT void TGpuParams<false>::getParam<Vector4>(const String&, TGpuDataParam<Vector4, false>&) const;
+	template BS_CORE_EXPORT void TGpuParams<false>::getParam<Matrix3>(const String&, TGpuDataParam<Matrix3, false>&) const;
+	template BS_CORE_EXPORT void TGpuParams<false>::getParam<Matrix4>(const String&, TGpuDataParam<Matrix4, false>&) const;
+
+	template BS_CORE_EXPORT void TGpuParams<true>::getParam<float>(const String&, TGpuDataParam<float, true>&) const;
+	template BS_CORE_EXPORT void TGpuParams<true>::getParam<Color>(const String&, TGpuDataParam<Color, true>&) const;
+	template BS_CORE_EXPORT void TGpuParams<true>::getParam<Vector2>(const String&, TGpuDataParam<Vector2, true>&) const;
+	template BS_CORE_EXPORT void TGpuParams<true>::getParam<Vector3>(const String&, TGpuDataParam<Vector3, true>&) const;
+	template BS_CORE_EXPORT void TGpuParams<true>::getParam<Vector4>(const String&, TGpuDataParam<Vector4, true>&) const;
+	template BS_CORE_EXPORT void TGpuParams<true>::getParam<Matrix3>(const String&, TGpuDataParam<Matrix3, true>&) const;
+	template BS_CORE_EXPORT void TGpuParams<true>::getParam<Matrix4>(const String&, TGpuDataParam<Matrix4, true>&) const;
+
 	GpuParamsCore::GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices)
 	GpuParamsCore::GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices)
 		: TGpuParams(paramDesc, transposeMatrices)
 		: TGpuParams(paramDesc, transposeMatrices)
 	{
 	{
 
 
 	}
 	}
 
 
+	SPtr<GpuParamsCore> GpuParamsCore::_getThisPtr() const
+	{
+		return std::static_pointer_cast<GpuParamsCore>(getThisPtr());
+	}
+
 	void GpuParamsCore::updateHardwareBuffers()
 	void GpuParamsCore::updateHardwareBuffers()
 	{
 	{
 		for (UINT32 i = 0; i < mNumParamBlocks; i++)
 		for (UINT32 i = 0; i < mNumParamBlocks; i++)
@@ -212,6 +426,11 @@ UINT32 GpuParamsBase::getDataParamSize(const String& name) const
 
 
 	}
 	}
 
 
+	SPtr<GpuParams> GpuParams::_getThisPtr() const
+	{
+		return std::static_pointer_cast<GpuParams>(getThisPtr());
+	}
+
 	SPtr<GpuParamsCore> GpuParams::getCore() const
 	SPtr<GpuParamsCore> GpuParams::getCore() const
 	{
 	{
 		return std::static_pointer_cast<GpuParamsCore>(mCoreSpecific);
 		return std::static_pointer_cast<GpuParamsCore>(mCoreSpecific);

+ 257 - 10
BansheeCore/Source/BsMaterial.cpp

@@ -398,6 +398,201 @@ namespace BansheeEngine
 		return allParamDescs;
 		return allParamDescs;
 	}
 	}
 
 
+	template<bool Core>
+	void TMaterial<Core>::setShader(ShaderType shader)
+	{
+		mShader = shader;
+
+		initBestTechnique();
+		_markCoreDirty();
+	}
+
+	template<bool Core>
+	UINT32 TMaterial<Core>::getNumPasses() const
+	{
+		throwIfNotInitialized();
+
+		return mShader->getBestTechnique()->getNumPasses();
+	}
+
+	template<bool Core>
+	typename TMaterial<Core>::PassType TMaterial<Core>::getPass(UINT32 passIdx) const
+	{
+		if (passIdx < 0 || passIdx >= mShader->getBestTechnique()->getNumPasses())
+			BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
+
+		return mShader->getBestTechnique()->getPass(passIdx);
+	}
+
+	template<bool Core>
+	TMaterialParamStruct<Core> TMaterial<Core>::getParamStruct(const String& name) const
+	{
+		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if (iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return TMaterialParamStruct<Core>();
+		}
+
+		const String& gpuVarName = iterFind->second;
+		Vector<TGpuParamStruct<Core>> gpuParams;
+
+		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			SPtr<TPassParameters<Core>> params = *iter;
+
+			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsType& paramPtr = params->getParamByIdx(i);
+				if (paramPtr)
+				{
+					if (paramPtr->hasParam(gpuVarName))
+					{
+						gpuParams.push_back(TGpuParamStruct<Core>());
+						paramPtr->getStructParam(gpuVarName, gpuParams.back());
+					}
+				}
+			}
+		}
+
+		return TMaterialParamStruct<Core>(gpuParams);
+	}
+
+	template<bool Core>
+	TMaterialParamTexture<Core> TMaterial<Core>::getParamTexture(const String& name) const
+	{
+		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if (iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return TMaterialParamTexture<Core>();
+		}
+
+		const String& gpuVarName = iterFind->second;
+		Vector<TGpuParamTexture<Core>> gpuParams;
+
+		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			SPtr<TPassParameters<Core>> params = *iter;
+
+			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsType& paramPtr = params->getParamByIdx(i);
+				if (paramPtr)
+				{
+					if (paramPtr->hasTexture(gpuVarName))
+					{
+						gpuParams.push_back(TGpuParamTexture<Core>());
+						paramPtr->getTextureParam(gpuVarName, gpuParams.back());
+					}
+				}
+			}
+		}
+
+		return TMaterialParamTexture<Core>(gpuParams);
+	}
+
+	template<bool Core>
+	TMaterialParamLoadStoreTexture<Core> TMaterial<Core>::getParamLoadStoreTexture(const String& name) const
+	{
+		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if (iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return TMaterialParamLoadStoreTexture<Core>();
+		}
+
+		const String& gpuVarName = iterFind->second;
+		Vector<TGpuParamLoadStoreTexture<Core>> gpuParams;
+
+		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			SPtr<TPassParameters<Core>> params = *iter;
+
+			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsType& paramPtr = params->getParamByIdx(i);
+				if (paramPtr)
+				{
+					if (paramPtr->hasTexture(gpuVarName))
+					{
+						gpuParams.push_back(TGpuParamLoadStoreTexture<Core>());
+						paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams.back());
+					}
+				}
+			}
+		}
+
+		return TMaterialParamLoadStoreTexture<Core>(gpuParams);
+	}
+
+	template<bool Core>
+	TMaterialParamSampState<Core> TMaterial<Core>::getParamSamplerState(const String& name) const
+	{
+		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if (iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return TMaterialParamSampState<Core>();
+		}
+
+		const String& gpuVarName = iterFind->second;
+		Vector<TGpuParamSampState<Core>> gpuParams;
+		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			SPtr<TPassParameters<Core>> params = *iter;
+
+			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsType& paramPtr = params->getParamByIdx(i);
+				if (paramPtr)
+				{
+					if (paramPtr->hasSamplerState(gpuVarName))
+					{
+						gpuParams.push_back(TGpuParamSampState<Core>());
+						paramPtr->getSamplerStateParam(gpuVarName, gpuParams.back());
+					}
+				}
+			}
+		}
+
+		return TMaterialParamSampState<Core>(gpuParams);
+	}
+
+	template<bool Core>
+	void TMaterial<Core>::setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
+	{
+		auto iterFind = mValidShareableParamBlocks.find(name);
+		if (iterFind == mValidShareableParamBlocks.end())
+		{
+			LOGWRN("Material doesn't have a parameter block named " + name);
+			return;
+		}
+
+		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			SPtr<TPassParameters<Core>> params = *iter;
+
+			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsType& paramPtr = params->getParamByIdx(i);
+				if (paramPtr)
+				{
+					if (paramPtr->hasParamBlock(name))
+						paramPtr->setParamBlockBuffer(name, paramBlock);
+				}
+			}
+		}
+	}
+
 	template<bool Core>
 	template<bool Core>
 	void TMaterial<Core>::initBestTechnique()
 	void TMaterial<Core>::initBestTechnique()
 	{
 	{
@@ -506,19 +701,76 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	template class TMaterial < false > ;
-	template class TMaterial < true > ;
-
-	Material::Material()
+	template <bool Core>
+	template <typename T>
+	void TMaterial<Core>::getParam(const String& name, TMaterialDataParam<T, Core>& output) const
 	{
 	{
+		throwIfNotInitialized();
+
+		auto iterFind = mValidParams.find(name);
+		if (iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return;
+		}
+
+		const String& gpuVarName = iterFind->second;
+		Vector<TGpuDataParam<T, Core>> gpuParams;
 
 
+		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
+		{
+			SPtr<TPassParameters<Core>> params = *iter;
+
+			for (UINT32 i = 0; i < params->getNumParams(); i++)
+			{
+				GpuParamsType& paramPtr = params->getParamByIdx(i);
+				if (paramPtr)
+				{
+					if (paramPtr->hasParam(gpuVarName))
+					{
+						gpuParams.push_back(TGpuDataParam<T, Core>());
+						paramPtr->getParam<T>(gpuVarName, gpuParams.back());
+					}
+				}
+			}
+		}
+
+		output = TMaterialDataParam<T, Core>(gpuParams);
 	}
 	}
 
 
-	Material::~Material()
+	template<bool Core>
+	void TMaterial<Core>::throwIfNotInitialized() const
 	{
 	{
+		if (mShader == nullptr)
+		{
+			BS_EXCEPT(InternalErrorException, "Material does not have shader set.");
+		}
 
 
+		if (mBestTechnique == nullptr)
+		{
+			BS_EXCEPT(InternalErrorException, "Shader does not contain a supported technique.");
+		}
 	}
 	}
 
 
+	template class TMaterial < false > ;
+	template class TMaterial < true > ;
+
+	template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<float, false>&) const;
+	template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Color, false>&) const;
+	template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector2, false>&) const;
+	template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector3, false>&) const;
+	template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector4, false>&) const;
+	template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix3, false>&) const;
+	template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix4, false>&) const;
+
+	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<float, true>&) const;
+	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Color, true>&) const;
+	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector2, true>&) const;
+	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector3, true>&) const;
+	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector4, true>&) const;
+	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix3, true>&) const;
+	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix4, true>&) const;
+
 	void Material::_markCoreDirty()
 	void Material::_markCoreDirty()
 	{
 	{
 		markCoreDirty();
 		markCoreDirty();
@@ -538,11 +790,6 @@ namespace BansheeEngine
 		return materialPtr;
 		return materialPtr;
 	}
 	}
 
 
-	void Material::_markCoreDirty()
-	{
-		markCoreDirty();
-	}
-
 	HMaterial Material::create()
 	HMaterial Material::create()
 	{
 	{
 		MaterialPtr materialPtr = MaterialManager::instance().create();
 		MaterialPtr materialPtr = MaterialManager::instance().create();

+ 143 - 0
BansheeCore/Source/BsMaterialParam.cpp

@@ -2,5 +2,148 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	template<class T, bool Core>
+	TMaterialDataParam<T, Core>::TMaterialDataParam(const Vector<TGpuDataParam<T, Core>>& params)
+		:mParams(params)
+	{ }
 
 
+	template<class T, bool Core>
+	void TMaterialDataParam<T, Core>::set(const T& value, UINT32 arrayIdx)
+	{
+		for (auto& param : mParams)
+			param.set(value, arrayIdx);
+	}
+
+	template<class T, bool Core>
+	T TMaterialDataParam<T, Core>::get(UINT32 arrayIdx)
+	{
+		if (mParams.size() == 0)
+			return T();
+
+		return mParams[0].get(arrayIdx); // They should all have the same value
+	}
+
+	template<bool Core>
+	TMaterialParamStruct<Core>::TMaterialParamStruct(const Vector<TGpuParamStruct<Core>>& params)
+		:mParams(params)
+	{ }
+
+	template<bool Core>
+	void TMaterialParamStruct<Core>::set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx)
+	{
+		for (auto& param : mParams)
+			param.set(value, sizeBytes, arrayIdx);
+	}
+
+	template<bool Core>
+	void TMaterialParamStruct<Core>::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx)
+	{
+		if (mParams.size() == 0)
+		{
+			value = nullptr;
+			return;
+		}
+
+		return mParams[0].get(value, sizeBytes, arrayIdx); // They should all have the same value
+	}
+
+	template<bool Core>
+	UINT32 TMaterialParamStruct<Core>::getElementSize() const
+	{
+		if (mParams.size() == 0)
+			return 0;
+
+		return mParams[0].getElementSize();
+	}
+
+	template<bool Core>
+	TMaterialParamTexture<Core>::TMaterialParamTexture(const Vector<TGpuParamTexture<Core>>& params)
+		:mParams(params)
+	{ }
+
+	template<bool Core>
+	void TMaterialParamTexture<Core>::set(const TextureType& texture)
+	{
+		for (auto& param : mParams)
+			param.set(texture);
+	}
+
+	template<bool Core>
+	typename TMaterialParamTexture<Core>::TextureType TMaterialParamTexture<Core>::get()
+	{
+		if (mParams.size() == 0)
+			return TextureType();
+
+		return mParams[0].get(); // They should all have the same value
+	}
+
+	template<bool Core>
+	TMaterialParamLoadStoreTexture<Core>::TMaterialParamLoadStoreTexture(const Vector<TGpuParamLoadStoreTexture<Core>>& params)
+		:mParams(params)
+	{ }
+
+	template<bool Core>
+	void TMaterialParamLoadStoreTexture<Core>::set(const TextureType& texture, const TextureSurface& surface)
+	{
+		for (auto& param : mParams)
+			param.set(texture, surface);
+	}
+
+	template<bool Core>
+	typename TMaterialParamLoadStoreTexture<Core>::TextureType TMaterialParamLoadStoreTexture<Core>::get()
+	{
+		if (mParams.size() == 0)
+			return TextureType();
+
+		return mParams[0].get(); // They should all have the same value
+	}
+
+	template<bool Core>
+	TMaterialParamSampState<Core>::TMaterialParamSampState(const Vector<TGpuParamSampState<Core>>& params)
+		:mParams(params)
+	{ }
+
+	template<bool Core>
+	void TMaterialParamSampState<Core>::set(const SamplerType& sampState)
+	{
+		for (auto& param : mParams)
+			param.set(sampState);
+	}
+
+	template<bool Core>
+	typename TMaterialParamSampState<Core>::SamplerType TMaterialParamSampState<Core>::get()
+	{
+		if (mParams.size() == 0)
+			return SamplerType();
+
+		return mParams[0].get(); // They should all have the same value
+	}
+
+	template class TMaterialDataParam<float, false>;
+	template class TMaterialDataParam<Color, false>;
+	template class TMaterialDataParam<Vector2, false>;
+	template class TMaterialDataParam<Vector3, false>;
+	template class TMaterialDataParam<Vector4, false>;
+	template class TMaterialDataParam<Matrix3, false>;
+	template class TMaterialDataParam<Matrix4, false>;
+
+	template class TMaterialDataParam<float, true>;
+	template class TMaterialDataParam<Color, true>;
+	template class TMaterialDataParam<Vector2, true>;
+	template class TMaterialDataParam<Vector3, true>;
+	template class TMaterialDataParam<Vector4, true>;
+	template class TMaterialDataParam<Matrix3, true>;
+	template class TMaterialDataParam<Matrix4, true>;
+
+	template class TMaterialParamStruct<false>;
+	template class TMaterialParamStruct<true>;
+
+	template class TMaterialParamTexture<false>;
+	template class TMaterialParamTexture<true>;
+
+	template class TMaterialParamLoadStoreTexture<false>;
+	template class TMaterialParamLoadStoreTexture<true>;
+
+	template class TMaterialParamSampState<false>;
+	template class TMaterialParamSampState<true>;
 }
 }

+ 12 - 16
BansheeCore/Source/BsPass.cpp

@@ -6,14 +6,23 @@
 #include "BsMaterial.h"
 #include "BsMaterial.h"
 #include "BsGpuParams.h"
 #include "BsGpuParams.h"
 #include "BsFrameAlloc.h"
 #include "BsFrameAlloc.h"
+#include "BsGpuProgram.h"
 #include "BsException.h"
 #include "BsException.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	bool propertiesHaveBlending(const BlendProperties& bsProps)
+	template<bool Core>
+	TPass<Core>::TPass()
 	{
 	{
+		mData.mStencilRefValue = 0;
+	}
+
+	template<bool Core>
+	bool TPass<Core>::hasBlending() const 
+	{ 
 		bool transparent = false;
 		bool transparent = false;
 
 
+		const BlendProperties& bsProps = mData.mBlendState->getProperties();
 		for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
 		for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
 		{
 		{
 			// Transparent if destination color is taken into account
 			// Transparent if destination color is taken into account
@@ -30,21 +39,8 @@ namespace BansheeEngine
 		return transparent;
 		return transparent;
 	}
 	}
 
 
-	bool PassBase::hasBlending(const HBlendState& blendState)
-	{
-		if (blendState != nullptr)
-			return propertiesHaveBlending(blendState->getProperties());
-
-		return false;
-	}
-
-	bool PassBase::hasBlending(const SPtr<BlendStateCore>& blendState)
-	{
-		if (blendState != nullptr)
-			return propertiesHaveBlending(blendState->getProperties());
-
-		return false;
-	}
+	template class TPass < false > ;
+	template class TPass < true >;
 
 
 	void PassCore::syncToCore(const CoreSyncData& data)
 	void PassCore::syncToCore(const CoreSyncData& data)
 	{
 	{

+ 58 - 16
BansheeCore/Source/BsShader.cpp

@@ -14,22 +14,6 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	bool ShaderBase::isTechniqueSupported(const SPtr<Technique> technique) const
-	{
-		return technique->isSupported();
-	}
-
-	bool ShaderBase::isTechniqueSupported(const SPtr<TechniqueCore> technique) const
-	{
-		return technique->isSupported();
-	}
-
-	void ShaderBase::checkBounds(UINT32 idx, UINT32 bound) const
-	{
-		if (idx < 0 || idx >= bound)
-			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
-	}
-
 	void ShaderBase::setQueueSortType(QueueSortType sortType) 
 	void ShaderBase::setQueueSortType(QueueSortType sortType) 
 	{ 
 	{ 
 		mQueueSortType = sortType;
 		mQueueSortType = sortType;
@@ -181,6 +165,64 @@ namespace BansheeEngine
 		_markCoreDirty();
 		_markCoreDirty();
 	}
 	}
 
 
+	template<bool Core>
+	TShader<Core>::TShader(const String& name)
+		:ShaderBase(name)
+	{ }
+
+	template<bool Core>
+	TShader<Core>::~TShader() 
+	{ }
+
+	template<bool Core>
+	void TShader<Core>::removeTechnique(UINT32 idx)
+	{
+		if (idx < 0 || idx >= (UINT32)mTechniques.size())
+			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+
+		int count = 0;
+		auto iter = mTechniques.begin();
+		while (count != idx)
+		{
+			++count;
+			++iter;
+		}
+
+		mTechniques.erase(iter);
+		_markCoreDirty();
+	}
+
+	template<bool Core>
+	void TShader<Core>::removeTechnique(SPtr<TechniqueType> technique)
+	{
+		auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
+
+		if (iterFind != mTechniques.end())
+		{
+			mTechniques.erase(iterFind);
+			_markCoreDirty();
+		}
+	}
+
+	template<bool Core>
+	SPtr<typename TShader<Core>::TechniqueType> TShader<Core>::getBestTechnique() const
+	{
+		for (auto iter = mTechniques.begin(); iter != mTechniques.end(); ++iter)
+		{
+			if ((*iter)->isSupported())
+			{
+				return *iter;
+			}
+		}
+
+		return nullptr;
+
+		// TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
+	}
+
+	template class TShader < false > ;
+	template class TShader < true >;
+
 	ShaderCore::ShaderCore(const String& name)
 	ShaderCore::ShaderCore(const String& name)
 		:TShader(name)
 		:TShader(name)
 	{
 	{

+ 28 - 2
BansheeCore/Source/BsTechnique.cpp

@@ -27,10 +27,36 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
-	void TechniqueBase::checkBounds(UINT32 idx, UINT32 bound) const
+	template<bool Core>
+	TTechnique<Core>::TTechnique(const String& renderSystem, const String& renderer)
+		:TechniqueBase(renderSystem, renderer)
+	{ }
+
+	template<bool Core>
+	void TTechnique<Core>::removePass(UINT32 idx)
+	{
+		if (idx < 0 || idx >= (UINT32)mPasses.size())
+			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+
+		int count = 0;
+		auto iter = mPasses.begin();
+		while (count != idx)
+		{
+			++count;
+			++iter;
+		}
+
+		mPasses.erase(iter);
+		_markCoreDirty();
+	}
+
+	template<bool Core>
+	SPtr<typename TTechnique<Core>::PassType> TTechnique<Core>::getPass(UINT32 idx) const
 	{
 	{
-		if (idx < 0 || idx >= bound)
+		if (idx < 0 || idx >= (UINT32)mPasses.size())
 			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
 			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+
+		return mPasses[idx];
 	}
 	}
 
 
 	template class TTechnique < false > ;
 	template class TTechnique < false > ;

+ 1 - 1
BansheeEngine/Include/BsRenderableProxy.h

@@ -18,7 +18,7 @@ namespace BansheeEngine
 		 * @brief	Contains a hardware GPU parameter buffer and index of the parameters and the slot
 		 * @brief	Contains a hardware GPU parameter buffer and index of the parameters and the slot
 		 *			it binds to in a material proxy.
 		 *			it binds to in a material proxy.
 		 */
 		 */
-		struct BS_CORE_EXPORT BufferBindInfo
+		struct BS_EXPORT BufferBindInfo
 		{
 		{
 			BufferBindInfo(UINT32 passIdx, UINT32 paramsIdx, UINT32 slotIdx, const SPtr<GpuParamBlockBufferCore>& buffer)
 			BufferBindInfo(UINT32 passIdx, UINT32 paramsIdx, UINT32 slotIdx, const SPtr<GpuParamBlockBufferCore>& buffer)
 				:passIdx(passIdx), paramsIdx(paramsIdx), slotIdx(slotIdx), buffer(buffer)
 				:passIdx(passIdx), paramsIdx(paramsIdx), slotIdx(slotIdx), buffer(buffer)

+ 1 - 0
BansheeEngine/Source/BsCursor.cpp

@@ -2,6 +2,7 @@
 #include "BsPlatform.h"
 #include "BsPlatform.h"
 #include "BsException.h"
 #include "BsException.h"
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
+#include "BsDebug.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {