Browse Source

Material refactor WIP

BearishSun 9 years ago
parent
commit
96bdac041e
32 changed files with 921 additions and 1009 deletions
  1. 2 0
      Source/BansheeCore/CMakeSources.cmake
  2. 3 1
      Source/BansheeCore/Include/BsCorePrerequisites.h
  3. 132 0
      Source/BansheeCore/Include/BsGpuParamsSet.h
  4. 59 87
      Source/BansheeCore/Include/BsMaterial.h
  5. 12 24
      Source/BansheeCore/Include/BsMaterialParam.h
  6. 374 0
      Source/BansheeCore/Source/BsGpuParamsSet.cpp
  7. 27 596
      Source/BansheeCore/Source/BsMaterial.cpp
  8. 13 54
      Source/BansheeCore/Source/BsMaterialParam.cpp
  9. 1 0
      Source/BansheeEditor/Include/BsDockManager.h
  10. 16 12
      Source/BansheeEditor/Include/BsGizmoManager.h
  11. 3 0
      Source/BansheeEditor/Include/BsHandleDrawManager.h
  12. 1 0
      Source/BansheeEditor/Include/BsSceneGrid.h
  13. 2 4
      Source/BansheeEditor/Include/BsScenePicking.h
  14. 1 0
      Source/BansheeEditor/Include/BsSelectionRenderer.h
  15. 4 1
      Source/BansheeEditor/Source/BsDockManager.cpp
  16. 65 58
      Source/BansheeEditor/Source/BsGizmoManager.cpp
  17. 20 6
      Source/BansheeEditor/Source/BsHandleDrawManager.cpp
  18. 4 0
      Source/BansheeEditor/Source/BsSceneGrid.cpp
  19. 17 21
      Source/BansheeEditor/Source/BsScenePicking.cpp
  20. 5 2
      Source/BansheeEditor/Source/BsSelectionRenderer.cpp
  21. 5 0
      Source/BansheeEngine/Include/BsRendererMaterial.h
  22. 5 11
      Source/BansheeEngine/Include/BsRendererUtility.h
  23. 27 60
      Source/BansheeEngine/Source/BsRendererUtility.cpp
  24. 2 1
      Source/RenderBeast/Include/BsLightRendering.h
  25. 11 2
      Source/RenderBeast/Include/BsRenderBeast.h
  26. 3 0
      Source/RenderBeast/Include/BsRendererObject.h
  27. 3 3
      Source/RenderBeast/Include/BsSamplerOverrides.h
  28. 13 11
      Source/RenderBeast/Source/BsLightRendering.cpp
  29. 4 3
      Source/RenderBeast/Source/BsObjectRendering.cpp
  30. 20 12
      Source/RenderBeast/Source/BsPostProcessing.cpp
  31. 58 30
      Source/RenderBeast/Source/BsRenderBeast.cpp
  32. 9 10
      Source/RenderBeast/Source/BsSamplerOverrides.cpp

+ 2 - 0
Source/BansheeCore/CMakeSources.cmake

@@ -182,6 +182,7 @@ set(BS_BANSHEECORE_INC_MATERIAL
 	"Include/BsShaderManager.h"
 	"Include/BsMaterialParams.h"
 	"Include/BsShaderDefines.h"
+	"Include/BsGpuParamsSet.h"
 )
 
 set(BS_BANSHEECORE_INC_RESOURCES
@@ -380,6 +381,7 @@ set(BS_BANSHEECORE_SRC_MATERIAL
 	"Source/BsShaderManager.cpp"
 	"Source/BsMaterialParams.cpp"
 	"Source/BsShaderDefines.cpp"
+	"Source/BsGpuParamsSet.cpp"
 )
 
 set(BS_BANSHEECORE_SRC_INPUT

+ 3 - 1
Source/BansheeCore/Include/BsCorePrerequisites.h

@@ -311,7 +311,7 @@ namespace BansheeEngine
 	class ShaderCore;
 	class ViewportCore;
 	class PassCore;
-	class PassParametersCore;
+	class GpuParamsSetCore;
 	class TechniqueCore;
 	class MaterialCore;
 	class GpuProgramCore;
@@ -369,6 +369,8 @@ namespace BansheeEngine
 	struct AnimationCurves;
 	class Skeleton;
 	class Animation;
+	class GpuParamsSet;
+	class GpuParamsSetCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;

+ 132 - 0
Source/BansheeCore/Include/BsGpuParamsSet.h

@@ -0,0 +1,132 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsMaterial.h"
+#include "BsShader.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Implementation
+	 *  @{
+	 */
+
+	/** Contains a set of GpuParams used for a single technique within a Material. */
+	template<bool Core>
+	class BS_CORE_EXPORT TGpuParamsSet
+	{
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TMaterialParamsType<Core>::Type MaterialParamsType;
+		typedef typename TGpuParamBlockBufferPtrType<Core>::Type ParamBlockPtrType;
+		typedef typename TTechniqueType<Core>::Type TechniqueType;
+		typedef typename TShaderType<Core>::Type ShaderType;
+		typedef typename TPassType<Core>::Type PassType;
+		typedef typename TGpuProgramType<Core>::Type GpuProgramPtrType;
+		typedef typename TGpuParamBlockBufferType<Core>::Type ParamBlockType;
+
+		/** Contains all parameters for a single pass. */
+		struct PassParams
+		{
+			GpuParamsType vertex;
+			GpuParamsType fragment;
+			GpuParamsType geometry;
+			GpuParamsType hull;
+			GpuParamsType domain;
+			GpuParamsType compute;
+		};
+
+	public:
+		TGpuParamsSet() {}
+		TGpuParamsSet(const SPtr<TechniqueType>& technique, const ShaderType& shader);
+
+		/**
+		 * Returns a GPU parameters for a specific shader stage and pass.
+		 *
+		 * @param[in]	idx			Sequential index of the shader stage to retrieve the parameters for.
+		 * @param[in]	passIdx		Pass for which to retrieve the parameters for.
+		 * @return					GPU parameters object that can be used for setting parameters of a GPU program 
+		 *							individually.
+		 *
+		 * @note	Useful when needing to iterate over all sets of GPU parameters.
+		 */
+		GpuParamsType getParamByIdx(UINT32 idx, UINT32 passIdx = 0)
+		{
+			GpuParamsType* paramArray[] = { &mPassParams[passIdx].vertex, &mPassParams[passIdx].fragment,
+				&mPassParams[passIdx].geometry, &mPassParams[passIdx].hull, &mPassParams[passIdx].domain, 
+				&mPassParams[passIdx].compute };
+
+			return *paramArray[idx];
+		}
+
+		/**
+		 * Sets GPU parameters for a specific shader stage and pass.
+		 *
+		 * @param[in]	idx			Sequential index of the shader stage to set the parameters for.
+		 * @param[in]	params		GPU parameters object to assign.
+		 * @param[in]	passIdx		Pass for which to set the parameters for.
+		 *
+		 * @note	Useful when needing to iterate over all sets of GPU parameters.
+		 */
+		void setParamByIdx(UINT32 idx, const GpuParamsType& params, UINT32 passIdx = 0)
+		{
+			GpuParamsType* paramArray[] = { &mPassParams[passIdx].vertex, &mPassParams[passIdx].fragment,
+				&mPassParams[passIdx].geometry, &mPassParams[passIdx].hull, &mPassParams[passIdx].domain,
+				&mPassParams[passIdx].compute };
+
+			(*paramArray[idx]) = params;
+		}
+
+		/** 
+		 * Returns a set of GPU parameters for an individual GPU program of the specified pass. 
+		 *
+		 * @param[in]	type		Type of the program to retrieve parameters for.
+		 * @param[in]	passIdx		Pass in which to look the GPU program for in.
+		 * @return					GPU parameters object that can be used for setting parameters of a GPU program 
+		 *							individually. Returns null if program or pass doesn't exist.
+		 */
+		GpuParamsType getGpuParams(GpuProgramType type, UINT32 passIdx = 0);
+
+
+		/**
+		 * Assign a parameter block buffer with the specified name to all the relevant child GpuParams.
+		 *
+		 * @note	
+		 * Parameter block buffers can be used as quick way of setting multiple parameters on a material at once, or
+		 * 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.
+		 */
+		void setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock);
+
+		/** Returns the number of passes the set contains the parameters for. */
+		UINT32 getNumPasses() const { return (UINT32)mPassParams.size(); }
+
+		static const UINT32 NUM_PARAMS;
+	private:
+		template<bool Core2> friend class TMaterial;
+
+		Vector<PassParams> mPassParams;
+	};
+
+	/** Sim thread version of TGpuParamsSet<Core>. */
+	class BS_CORE_EXPORT GpuParamsSet : public TGpuParamsSet<false>
+	{
+	public:
+		GpuParamsSet() { }
+		GpuParamsSet(const SPtr<Technique>& technique, const HShader& shader)
+			:TGpuParamsSet(technique, shader)
+		{ }
+	};
+
+	/** Core thread version of TGpuParamsSet<Core>. */
+	class BS_CORE_EXPORT GpuParamsSetCore : public TGpuParamsSet<true>
+	{
+	public:
+		GpuParamsSetCore() { }
+		GpuParamsSetCore(const SPtr<TechniqueCore>& technique, const SPtr<ShaderCore>& shader)
+			:TGpuParamsSet(technique, shader)
+		{ }
+	};
+
+	/** @} */
+}

+ 59 - 87
Source/BansheeCore/Include/BsMaterial.h

@@ -20,59 +20,6 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/** Helper class containing parameters for all types of GPU programs used in a pass. */
-	template<bool Core>
-	class TPassParameters
-	{
-	public:
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
-
-		/**
-		 * Returns a set of GPU parameters based on an index.
-		 *
-		 * @note	Useful when needing to iterate over all sets of GPU parameters.
-		 */
-		GpuParamsType& getParamByIdx(UINT32 idx)
-		{
-			GpuParamsType* paramArray[] = { &mVertParams, &mFragParams, &mGeomParams, &mHullParams, &mDomainParams, &mComputeParams };
-
-			return *paramArray[idx];
-		}
-
-		/**
-		 * Sets GPU parameters based on an index.
-		 *
-		 * @note	Useful when needing to iterate over all sets of GPU parameters.
-		 */
-		void setParamByIdx(UINT32 idx, const GpuParamsType& params)
-		{
-			GpuParamsType* paramArray[] = { &mVertParams, &mFragParams, &mGeomParams, &mHullParams, &mDomainParams, &mComputeParams };
-
-			(*paramArray[idx]) = params;
-		}
-
-		GpuParamsType mVertParams;
-		GpuParamsType mFragParams;
-		GpuParamsType mGeomParams;
-		GpuParamsType mHullParams;
-		GpuParamsType mDomainParams;
-		GpuParamsType mComputeParams;
-	};
-
-	/** Contains sim thread pass parameters for each shader stage. */
-	class BS_CORE_EXPORT PassParameters : public TPassParameters<false>
-	{
-	public:
-		static const UINT32 NUM_PARAMS;
-	};
-
-	/** Contains core thread pass parameters for each shader stage. */
-	class BS_CORE_EXPORT PassParametersCore : public TPassParameters<true>
-	{
-	public:
-		static const UINT32 NUM_PARAMS;
-	};
-
 	template<bool Core> struct TGpuParamBlockBufferPtrType { };
 	template<> struct TGpuParamBlockBufferPtrType<false> { typedef SPtr<GpuParamBlockBuffer> Type; };
 	template<> struct TGpuParamBlockBufferPtrType<true> { typedef SPtr<GpuParamBlockBufferCore> Type; };
@@ -88,10 +35,10 @@ namespace BansheeEngine
 	template<bool Core> struct TGpuParamBlockBufferType {};
 	template<> struct TGpuParamBlockBufferType < false > { typedef GpuParamBlockBuffer Type; };
 	template<> struct TGpuParamBlockBufferType < true > { typedef GpuParamBlockBufferCore Type; };
-
-	template<bool Core> struct TPassParamsType {};
-	template<> struct TPassParamsType < false > { typedef PassParameters Type; };
-	template<> struct TPassParamsType < true > { typedef PassParametersCore Type; };
+	
+	template<bool Core> struct TGpuParamsSetType {};
+	template<> struct TGpuParamsSetType < false > { typedef GpuParamsSet Type; };
+	template<> struct TGpuParamsSetType < true > { typedef GpuParamsSetCore Type; };
 
 	/**
 	 * Material that controls how objects are rendered. It is represented by a shader and parameters used to set up that
@@ -99,7 +46,6 @@ namespace BansheeEngine
 	 */
 	class BS_CORE_EXPORT MaterialBase
 	{
-
 	public:
 		/** Data used to describe a structure defined within a shader. */
 		struct StructData
@@ -108,8 +54,6 @@ namespace BansheeEngine
 				:data(nullptr), size(0)
 			{ }
 
-
-
 			StructData(UINT32 _size)
 				:size(_size)
 			{
@@ -140,12 +84,6 @@ namespace BansheeEngine
 
 		/** @copydoc IResourceListener::markListenerResourcesDirty */
 		virtual void _markResourcesDirty() { }
-
-		/** Returns all GPU parameter descriptions in the specified technique. */
-		static Vector<SPtr<GpuParamDesc>> getAllParamDescs(const SPtr<Technique>& technique);
-
-		/** Returns all GPU parameter descriptions in the specified technique. */
-		static Vector<SPtr<GpuParamDesc>> getAllParamDescs(const SPtr<TechniqueCore>& technique);
 	};
 
 	/** @copydoc MaterialBase */
@@ -153,17 +91,14 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TMaterial : public MaterialBase
 	{
 	public:
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
 		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 		typedef typename TGpuBufferType<Core>::Type BufferType;
 		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerStateType;
-		typedef typename TGpuParamBlockBufferPtrType<Core>::Type ParamBlockPtrType;
-		typedef typename TGpuParamBlockBufferType<Core>::Type ParamBlockType;
 		typedef typename TGpuProgramType<Core>::Type GpuProgramType;
 		typedef typename TPassType<Core>::Type PassType;
 		typedef typename TTechniqueType<Core>::Type TechniqueType;
 		typedef typename TShaderType<Core>::Type ShaderType;
-		typedef typename TPassParamsType<Core>::Type PassParamsType;
+		typedef typename TGpuParamsSetType<Core>::Type GpuParamsSetType;
 		typedef typename TMaterialParamsType<Core>::Type MaterialParamsType;
 
 		TMaterial() { }
@@ -195,7 +130,29 @@ namespace BansheeEngine
 		 *								the default technique.
 		 * @return						Pass if found, null otherwise.
 		 */
-		SPtr<PassType> getPass(UINT32 passIdx, UINT32 techniqueIdx = 0) const;
+		SPtr<PassType> getPass(UINT32 passIdx = 0, UINT32 techniqueIdx = 0) const;
+
+		/**
+		 * Creates a set of GpuParams that may be used for binding material parameters to the GPU. The expected behaviour
+		 * is to create a set of GpuParams per-technique once, and then before binding them to the GPU call
+		 * updateParamsSet() to ensure any dirty parameters are transfered from the material to GpuParams. You may also
+		 * use the parameter set to manually modify parameters on a per-program basis, in which case no further updates from
+		 * the material are necessary.
+		 */
+		SPtr<GpuParamsSetType> createParamsSet(UINT32 techniqueIdx = 0);
+
+		/**
+		 * Updates the provided parameter set by recording in it any changes that were made since the last call. It is
+		 * assumed only a single parameter set exists per-material per-technique. If there are multiple the material
+		 * will not be able to track which parameters were updated since the last call.
+		 *
+		 * @param[in]	paramsSet		Parameter set to update.
+		 * @param[in]	technique		Technique to update the parameters for. The parameter set provided must have been
+		 *								created using createParamsSet() using this same technique index.
+		 * @param[in]	forceRefresh	If true all material parameters will be assigned to the params set, regardless if
+		 *								they are marked dirty or not.
+		 */
+		void updateParamsSet(const SPtr<GpuParamsSetType>& paramsSet, UINT32 techniqueIdx = 0, bool forceRefresh = false);
 
 		/**   
 		 * Assigns a float value to the shader parameter with the specified name. 
@@ -526,19 +483,6 @@ namespace BansheeEngine
 		 */
 		TMaterialParamSampState<Core> getParamSamplerState(const String& name) const;
 
-		/** Returns a set of parameters for all GPU programs in the specified shader pass. */
-		SPtr<PassParamsType> getPassParameters(UINT32 passIdx) const { return mParametersPerPass[passIdx]; }
-
-		/**
-		 * Assign a parameter block buffer with the specified name.
-		 *
-		 * @note	
-		 * Parameter block buffers can be used as quick way of setting multiple parameters on a material at once, or
-		 * 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.
-		 */
-		void setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock);
-
 		/**
 		 * Allows you to retrieve a handle to a parameter that you can then use for quickly setting and retrieving parameter
 		 * data. This allows you to set/get parameter data without all the cost of extra lookups otherwise required.
@@ -550,6 +494,18 @@ namespace BansheeEngine
 		template <typename T>
 		void getParam(const String& name, TMaterialDataParam<T, Core>& output) const;
 
+		/**
+		 * @name Internal
+		 * @{
+		 */
+
+		/** 
+		 * Returns an object containg all of material's parameters. Allows the caller to manipulate the parameters more
+		 * directly. 
+		 */
+		SPtr<MaterialParamsType> _getInternalParams() const { return mParams; }
+
+		/** @} */
 	protected:
 		/**
 		 * Assigns a value from a raw buffer to the parameter with the specified name. Buffer must be of sizeof(T) * 
@@ -575,8 +531,6 @@ namespace BansheeEngine
 		ShaderType mShader;
 		SPtr<MaterialParamsType> mParams;
 		Vector<SPtr<TechniqueType>> mTechniques;
-
-		Vector<SPtr<PassParamsType>> mParametersPerPass;
 	};
 
 	/** @} */
@@ -594,6 +548,21 @@ namespace BansheeEngine
 		/** @copydoc Material::setShader */
 		void setShader(const SPtr<ShaderCore>& shader);
 
+		/** Returns any custom data set by the renderer. */
+		const Any& getRendererData() const { return mRendererData; }
+
+		/** 
+		 * Sets renderer-specific data on the material. This can by anything the renderer requires, as its not used by the
+		 * material directly. 
+		 */
+		void setRendererData(const Any& data) { mRendererData = data; }
+
+		/** 
+		 * Returns a version number that increments whenever the material's shader changes. Allows external systems to know
+		 * when they need to rebuild relevant cached data.
+		 */
+		UINT32 getVersion() const { return mVersion; }
+
 		/** Creates a new material with the specified shader. */
 		static SPtr<MaterialCore> create(const SPtr<ShaderCore>& shader);
 
@@ -603,10 +572,13 @@ namespace BansheeEngine
 		MaterialCore() { }
 		MaterialCore(const SPtr<ShaderCore>& shader);
 		MaterialCore(const SPtr<ShaderCore>& shader, const Vector<SPtr<TechniqueCore>>& techniques,
-			const SPtr<MaterialParamsCore>& materialParams, const Vector<SPtr<PassParametersCore>>& passParams);
+			const SPtr<MaterialParamsCore>& materialParams);
 
 		/** @copydoc CoreObjectCore::syncToCore */
 		void syncToCore(const CoreSyncData& data) override;
+
+		Any mRendererData;
+		UINT32 mVersion;
 	};
 
 	/** @} */

+ 12 - 24
Source/BansheeCore/Include/BsMaterialParam.h

@@ -40,8 +40,7 @@ namespace BansheeEngine
 		typedef typename TMaterialParamsType<Core>::Type MaterialParamsType;
 
 	public:
-		TMaterialDataParam(const String& name, const SPtr<MaterialParamsType>& params,
-			const SPtr<Vector<TGpuDataParam<T, Core>>>& gpuParams);
+		TMaterialDataParam(const String& name, const SPtr<MaterialParamsType>& params);
 		TMaterialDataParam() { }
 
 		/** @copydoc TGpuDataParam::set */
@@ -53,14 +52,13 @@ namespace BansheeEngine
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t& nullval) const
 		{
-			return mGPUParams == nullptr;
+			return mMaterialParams == nullptr;
 		}
 
 	protected:
 		UINT32 mParamIndex;
 		UINT32 mArraySize;
 		SPtr<MaterialParamsType> mMaterialParams;
-		SPtr<Vector<TGpuDataParam<T, Core>>> mGPUParams;
 	};
 	
 	/** @copydoc TMaterialDataParam */
@@ -70,8 +68,7 @@ namespace BansheeEngine
 		typedef typename TMaterialParamsType<Core>::Type MaterialParamsType;
 
 	public:
-		TMaterialParamStruct(const String& name, const SPtr<MaterialParamsType>& params,
-			const SPtr<Vector<TGpuParamStruct<Core>>>& gpuParams);
+		TMaterialParamStruct(const String& name, const SPtr<MaterialParamsType>& params);
 		TMaterialParamStruct() { }
 
 		/** @copydoc TGpuParamStruct::set */
@@ -86,14 +83,13 @@ namespace BansheeEngine
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t& nullval) const
 		{
-			return mGPUParams == nullptr;
+			return mMaterialParams == nullptr;
 		}
 
 	protected:
 		UINT32 mParamIndex;
 		UINT32 mArraySize;
 		SPtr<MaterialParamsType> mMaterialParams;
-		SPtr<Vector<TGpuParamStruct<Core>>> mGPUParams;
 	};
 
 	/** @copydoc TMaterialDataParam */
@@ -104,8 +100,7 @@ namespace BansheeEngine
 		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 
 	public:
-		TMaterialParamTexture(const String& name, const SPtr<MaterialParamsType>& params,
-			const SPtr<Vector<TGpuParamTexture<Core>>>& gpuParams);
+		TMaterialParamTexture(const String& name, const SPtr<MaterialParamsType>& params);
 		TMaterialParamTexture() { }
 
 		/** @copydoc GpuParamTexture::set */
@@ -117,13 +112,12 @@ namespace BansheeEngine
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t& nullval) const
 		{
-			return mGPUParams == nullptr;
+			return mMaterialParams == nullptr;
 		}
 
 	protected:
 		UINT32 mParamIndex;
 		SPtr<MaterialParamsType> mMaterialParams;
-		SPtr<Vector<TGpuParamTexture<Core>>> mGPUParams;
 	};
 
 	/** @copydoc TMaterialDataParam */
@@ -134,8 +128,7 @@ namespace BansheeEngine
 		typedef typename TGpuParamTextureType<Core>::Type TextureType;
 
 	public:
-		TMaterialParamLoadStoreTexture(const String& name, const SPtr<MaterialParamsType>& params,
-			const SPtr<Vector<TGpuParamLoadStoreTexture<Core>>>& gpuParams);
+		TMaterialParamLoadStoreTexture(const String& name, const SPtr<MaterialParamsType>& params);
 		TMaterialParamLoadStoreTexture() { }
 
 		/** @copydoc GpuParamLoadStoreTexture::set */
@@ -147,13 +140,12 @@ namespace BansheeEngine
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t& nullval) const
 		{
-			return mGPUParams == nullptr;
+			return mMaterialParams == nullptr;
 		}
 
 	protected:
 		UINT32 mParamIndex;
 		SPtr<MaterialParamsType> mMaterialParams;
-		SPtr<Vector<TGpuParamLoadStoreTexture<Core>>> mGPUParams;
 	};
 	
 	/** @copydoc TMaterialDataParam */
@@ -164,8 +156,7 @@ namespace BansheeEngine
 		typedef typename TGpuBufferType<Core>::Type BufferType;
 
 	public:
-		TMaterialParamBuffer(const String& name, const SPtr<MaterialParamsType>& params,
-			const SPtr<Vector<TGpuParamBuffer<Core>>>& gpuParams);
+		TMaterialParamBuffer(const String& name, const SPtr<MaterialParamsType>& params);
 		TMaterialParamBuffer() { }
 
 		/** @copydoc GpuParamBuffer::set */
@@ -177,13 +168,12 @@ namespace BansheeEngine
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t& nullval) const
 		{
-			return mGPUParams == nullptr;
+			return mMaterialParams == nullptr;
 		}
 
 	protected:
 		UINT32 mParamIndex;
 		SPtr<MaterialParamsType> mMaterialParams;
-		SPtr<Vector<TGpuParamBuffer<Core>>> mGPUParams;
 	};
 
 	/** @copydoc TMaterialDataParam */
@@ -194,8 +184,7 @@ namespace BansheeEngine
 		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerStateType;
 
 	public:
-		TMaterialParamSampState(const String& name, const SPtr<MaterialParamsType>& params,
-			const SPtr<Vector<TGpuParamSampState<Core>>>& gpuParams);
+		TMaterialParamSampState(const String& name, const SPtr<MaterialParamsType>& params);
 		TMaterialParamSampState() { }
 
 		/** @copydoc GpuParamSampState::set */
@@ -207,13 +196,12 @@ namespace BansheeEngine
 		/** Checks if param is initialized. */
 		bool operator==(const nullptr_t& nullval) const
 		{
-			return mGPUParams == nullptr;
+			return mMaterialParams == nullptr;
 		}
 
 	protected:
 		UINT32 mParamIndex;
 		SPtr<MaterialParamsType> mMaterialParams;
-		SPtr<Vector<TGpuParamSampState<Core>>> mGPUParams;
 	};
 
 	/** @} */

+ 374 - 0
Source/BansheeCore/Source/BsGpuParamsSet.cpp

@@ -0,0 +1,374 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGpuParamsSet.h"
+#include "BsShader.h"
+#include "BsTechnique.h"
+#include "BsPass.h"
+#include "BsGpuProgram.h"
+#include "BsGpuParamDesc.h"
+#include "BsGpuParamBlockBuffer.h"
+
+namespace BansheeEngine
+{
+	struct ShaderBlockDesc
+	{
+		String name;
+		GpuParamBlockUsage usage;
+		int size;
+		bool external;
+	};
+
+	Vector<SPtr<GpuParamDesc>> getAllParamDescs(const SPtr<Technique>& technique)
+	{
+		Vector<SPtr<GpuParamDesc>> allParamDescs;
+
+		// Make sure all gpu programs are fully loaded
+		for (UINT32 i = 0; i < technique->getNumPasses(); i++)
+		{
+			SPtr<Pass> curPass = technique->getPass(i);
+
+			SPtr<GpuProgram> vertProgram = curPass->getVertexProgram();
+			if (vertProgram)
+			{
+				vertProgram->blockUntilCoreInitialized();
+				allParamDescs.push_back(vertProgram->getParamDesc());
+			}
+
+			SPtr<GpuProgram> fragProgram = curPass->getFragmentProgram();
+			if (fragProgram)
+			{
+				fragProgram->blockUntilCoreInitialized();
+				allParamDescs.push_back(fragProgram->getParamDesc());
+			}
+
+			SPtr<GpuProgram> geomProgram = curPass->getGeometryProgram();
+			if (geomProgram)
+			{
+				geomProgram->blockUntilCoreInitialized();
+				allParamDescs.push_back(geomProgram->getParamDesc());
+			}
+
+			SPtr<GpuProgram> hullProgram = curPass->getHullProgram();
+			if (hullProgram)
+			{
+				hullProgram->blockUntilCoreInitialized();
+				allParamDescs.push_back(hullProgram->getParamDesc());
+			}
+
+			SPtr<GpuProgram> domainProgram = curPass->getDomainProgram();
+			if (domainProgram)
+			{
+				domainProgram->blockUntilCoreInitialized();
+				allParamDescs.push_back(domainProgram->getParamDesc());
+			}
+
+			SPtr<GpuProgram> computeProgram = curPass->getComputeProgram();
+			if (computeProgram)
+			{
+				computeProgram->blockUntilCoreInitialized();
+				allParamDescs.push_back(computeProgram->getParamDesc());
+			}
+		}
+
+		return allParamDescs;
+	}
+
+	Vector<SPtr<GpuParamDesc>> getAllParamDescs(const SPtr<TechniqueCore>& technique)
+	{
+		Vector<SPtr<GpuParamDesc>> allParamDescs;
+
+		// Make sure all gpu programs are fully loaded
+		for (UINT32 i = 0; i < technique->getNumPasses(); i++)
+		{
+			SPtr<PassCore> curPass = technique->getPass(i);
+
+			SPtr<GpuProgramCore> vertProgram = curPass->getVertexProgram();
+			if (vertProgram)
+				allParamDescs.push_back(vertProgram->getParamDesc());
+
+			SPtr<GpuProgramCore> fragProgram = curPass->getFragmentProgram();
+			if (fragProgram)
+				allParamDescs.push_back(fragProgram->getParamDesc());
+
+			SPtr<GpuProgramCore> geomProgram = curPass->getGeometryProgram();
+			if (geomProgram)
+				allParamDescs.push_back(geomProgram->getParamDesc());
+
+			SPtr<GpuProgramCore> hullProgram = curPass->getHullProgram();
+			if (hullProgram)
+				allParamDescs.push_back(hullProgram->getParamDesc());
+
+			SPtr<GpuProgramCore> domainProgram = curPass->getDomainProgram();
+			if (domainProgram)
+				allParamDescs.push_back(domainProgram->getParamDesc());
+
+			SPtr<GpuProgramCore> computeProgram = curPass->getComputeProgram();
+			if (computeProgram)
+				allParamDescs.push_back(computeProgram->getParamDesc());
+		}
+
+		return allParamDescs;
+	}
+
+	bool areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets)
+	{
+		bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize
+			&& paramA.type == paramB.type && paramA.arrayElementStride == paramB.arrayElementStride;
+
+		if (!ignoreBufferOffsets)
+			equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
+
+		return equal;
+	}
+
+	Vector<ShaderBlockDesc> determineValidShareableParamBlocks(const Vector<SPtr<GpuParamDesc>>& paramDescs,
+		const Map<String, SHADER_PARAM_BLOCK_DESC>& shaderDesc)
+	{
+		struct BlockInfo
+		{
+			BlockInfo() { }
+			BlockInfo(const String& name, const SPtr<GpuParamDesc>& paramDesc, bool isValid = true)
+				:name(name), paramDesc(paramDesc), isValid(isValid)
+			{ }
+
+			String name;
+			SPtr<GpuParamDesc> paramDesc;
+			bool isValid;
+		};
+
+		// Make sure param blocks with the same name actually contain the same fields
+		Map<String, BlockInfo> uniqueParamBlocks;
+
+		for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
+		{
+			const GpuParamDesc& curDesc = **iter;
+			for (auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
+			{
+				bool isBlockValid = true;
+				const GpuParamBlockDesc& curBlock = blockIter->second;
+
+				if (!curBlock.isShareable) // Non-shareable buffers are handled differently, they're allowed same names
+					continue;
+
+				auto iterFind = uniqueParamBlocks.find(blockIter->first);
+				if (iterFind == uniqueParamBlocks.end())
+				{
+					uniqueParamBlocks[blockIter->first] = BlockInfo(blockIter->first, *iter);
+					continue;
+				}
+
+				// The block was already determined as invalid, no need to check further
+				if (!iterFind->second.isValid)
+					continue;
+
+				String otherBlockName = iterFind->second.name;
+				SPtr<GpuParamDesc> otherDesc = iterFind->second.paramDesc;
+
+				for (auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
+				{
+					const GpuParamDataDesc& myParam = myParamIter->second;
+
+					if (myParam.paramBlockSlot != curBlock.slot)
+						continue; // Param is in another block, so we will check it when its time for that block
+
+					auto otherParamFind = otherDesc->params.find(myParamIter->first);
+
+					// Cannot find other param, blocks aren't equal
+					if (otherParamFind == otherDesc->params.end())
+					{
+						isBlockValid = false;
+						break;
+					}
+
+					const GpuParamDataDesc& otherParam = otherParamFind->second;
+
+					if (!areParamsEqual(myParam, otherParam, false) || curBlock.name != otherBlockName)
+					{
+						isBlockValid = false;
+						break;
+					}
+				}
+
+				if (!isBlockValid)
+				{
+					LOGWRN("Found two param blocks with the same name but different contents: " + blockIter->first);
+					uniqueParamBlocks[blockIter->first] = BlockInfo(blockIter->first, nullptr, false);
+				}
+			}
+		}
+
+		Vector<ShaderBlockDesc> output;
+		for (auto& entry : uniqueParamBlocks)
+		{
+			if (!entry.second.isValid)
+				continue;
+
+			ShaderBlockDesc shaderBlockDesc;
+			shaderBlockDesc.external = false;
+			shaderBlockDesc.usage = GPBU_STATIC;
+			shaderBlockDesc.size = 0;
+			shaderBlockDesc.name = entry.first;
+
+			auto iterFind = shaderDesc.find(entry.first);
+			if (iterFind != shaderDesc.end())
+			{
+				shaderBlockDesc.external = iterFind->second.shared || iterFind->second.rendererSemantic != StringID::NONE;
+				shaderBlockDesc.usage = iterFind->second.usage;
+			}
+
+			for (auto iter2 = paramDescs.begin(); iter2 != paramDescs.end(); ++iter2)
+			{
+				auto findParamBlockDesc = (*iter2)->paramBlocks.find(entry.first);
+
+				if (findParamBlockDesc != (*iter2)->paramBlocks.end())
+				{
+					shaderBlockDesc.size = findParamBlockDesc->second.blockSize * sizeof(UINT32);
+					break;
+				}
+			}
+
+			output.push_back(shaderBlockDesc);
+		}
+
+		return output;
+	}
+
+	template<bool Core>
+	const UINT32 TGpuParamsSet<Core>::NUM_PARAMS = 6;
+
+	template<bool Core>
+	TGpuParamsSet<Core>::TGpuParamsSet(const SPtr<TechniqueType>& technique, const ShaderType& shader)
+		:mPassParams(technique->getNumPasses())
+	{
+		UINT32 numPasses = technique->getNumPasses();
+
+		// Create GpuParams for each pass and shader stage
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			SPtr<PassType> curPass = technique->getPass(i);
+
+			GpuProgramPtrType vertProgram = curPass->getVertexProgram();
+			if (vertProgram)
+				mPassParams[i].vertex = vertProgram->createParameters();
+
+			GpuProgramPtrType fragProgram = curPass->getFragmentProgram();
+			if (fragProgram)
+				mPassParams[i].fragment = fragProgram->createParameters();
+
+			GpuProgramPtrType geomProgram = curPass->getGeometryProgram();
+			if (geomProgram)
+				mPassParams[i].geometry = geomProgram->createParameters();
+
+			GpuProgramPtrType hullProgram = curPass->getHullProgram();
+			if (hullProgram)
+				mPassParams[i].hull = hullProgram->createParameters();
+
+			GpuProgramPtrType domainProgram = curPass->getDomainProgram();
+			if (domainProgram)
+				mPassParams[i].domain = domainProgram->createParameters();
+
+			GpuProgramPtrType computeProgram = curPass->getComputeProgram();
+			if (computeProgram)
+				mPassParams[i].compute = computeProgram->createParameters();
+		}
+
+		// Create and assign parameter block buffers
+		Vector<SPtr<GpuParamDesc>> allParamDescs = getAllParamDescs(technique);
+
+		//// Fill out various helper structures
+		Vector<ShaderBlockDesc> paramBlockData = determineValidShareableParamBlocks(allParamDescs, shader->getParamBlocks());
+
+		Map<String, ParamBlockPtrType> paramBlockBuffers;
+
+		//// Create param blocks
+		for (auto& paramBlock : paramBlockData)
+		{
+			ParamBlockPtrType newParamBlockBuffer;
+			if (!paramBlock.external)
+				newParamBlockBuffer = ParamBlockType::create(paramBlock.size, paramBlock.usage);
+
+			paramBlockBuffers[paramBlock.name] = newParamBlockBuffer;
+		}
+
+		//// Assign param block buffers
+		for (UINT32 i = 0; i < numPasses; i++)
+		{
+			for (UINT32 j = 0; j < NUM_PARAMS; j++)
+			{
+				GpuParamsType paramPtr = getParamByIdx(j, i);
+				if (paramPtr != nullptr)
+				{
+					// Assign shareable buffers
+					for (auto& block : paramBlockData)
+					{
+						const String& paramBlockName = block.name;
+						if (paramPtr->hasParamBlock(paramBlockName))
+						{
+							ParamBlockPtrType blockBuffer = paramBlockBuffers[paramBlockName];
+
+							paramPtr->setParamBlockBuffer(paramBlockName, blockBuffer);
+						}
+					}
+
+					// Create non-shareable ones (these are buffers defined by default by the RHI usually)
+					const GpuParamDesc& desc = paramPtr->getParamDesc();
+					for (auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
+					{
+						if (!iterBlockDesc->second.isShareable)
+						{
+							ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(iterBlockDesc->second.blockSize * sizeof(UINT32));
+
+							paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	template<bool Core>
+	typename TGpuParamsSet<Core>::GpuParamsType TGpuParamsSet<Core>::getGpuParams(GpuProgramType type, UINT32 passIdx)
+	{
+		if (passIdx >= mPassParams.size())
+			return nullptr;
+
+		switch (type)
+		{
+		case GPT_VERTEX_PROGRAM:
+			return mPassParams[passIdx].vertex;
+		case GPT_FRAGMENT_PROGRAM:
+			return mPassParams[passIdx].fragment;
+		case GPT_GEOMETRY_PROGRAM:
+			return mPassParams[passIdx].geometry;
+		case GPT_HULL_PROGRAM:
+			return mPassParams[passIdx].hull;
+		case GPT_DOMAIN_PROGRAM:
+			return mPassParams[passIdx].domain;
+		case GPT_COMPUTE_PROGRAM:
+			return mPassParams[passIdx].compute;
+		}
+
+		return nullptr;
+	}
+
+	template<bool Core>
+	void TGpuParamsSet<Core>::setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
+	{
+		UINT32 numPasses = (UINT32)mPassParams.size();
+		for (UINT32 j = 0; j < numPasses; j++)
+		{
+			for (UINT32 i = 0; i < NUM_PARAMS; i++)
+			{
+				GpuParamsType paramPtr = getParamByIdx(i);
+				if (paramPtr != nullptr)
+				{
+					if (paramPtr->hasParamBlock(name))
+						paramPtr->setParamBlockBuffer(name, paramBlock);
+				}
+			}
+		}
+	}
+
+	template class TGpuParamsSet <false>;
+	template class TGpuParamsSet <true>;
+}

+ 27 - 596
Source/BansheeCore/Source/BsMaterial.cpp

@@ -1,203 +1,29 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsMaterial.h"
-#include "BsException.h"
 #include "BsShader.h"
 #include "BsTechnique.h"
 #include "BsPass.h"
 #include "BsRenderAPI.h"
-#include "BsHardwareBufferManager.h"
-#include "BsGpuProgram.h"
-#include "BsGpuParamBlockBuffer.h"
-#include "BsGpuParamDesc.h"
 #include "BsMaterialRTTI.h"
 #include "BsMaterialManager.h"
-#include "BsDebug.h"
 #include "BsResources.h"
 #include "BsFrameAlloc.h"
 #include "BsMatrixNxM.h"
 #include "BsVectorNI.h"
 #include "BsMemorySerializer.h"
 #include "BsMaterialParams.h"
+#include "BsGpuParamsSet.h"
 
 namespace BansheeEngine
 {
-	struct ShaderBlockDesc
-	{
-		String name;
-		GpuParamBlockUsage usage;
-		int size;
-		bool create;
-	};
-
 	enum MaterialLoadFlags
 	{
 		Load_None	= 0,
 		Load_Shader	= 1,
 		Load_All	= 2
 	};
-
-	const UINT32 PassParameters::NUM_PARAMS = 6;
-	const UINT32 PassParametersCore::NUM_PARAMS = 6;
 	
-	SPtr<PassParametersCore> convertParamsToCore(const SPtr<PassParameters>& passParams)
-	{
-		SPtr<PassParametersCore> passParameters = bs_shared_ptr_new<PassParametersCore>();
-
-		if (passParams->mVertParams != nullptr)
-			passParameters->mVertParams = passParams->mVertParams->getCore();
-		else
-			passParameters->mVertParams = nullptr;
-
-		if (passParams->mFragParams != nullptr)
-			passParameters->mFragParams = passParams->mFragParams->getCore();
-		else
-			passParameters->mFragParams = nullptr;
-
-		if (passParams->mGeomParams != nullptr)
-			passParameters->mGeomParams = passParams->mGeomParams->getCore();
-		else
-			passParameters->mGeomParams = nullptr;
-
-		if (passParams->mHullParams != nullptr)
-			passParameters->mHullParams = passParams->mHullParams->getCore();
-		else
-			passParameters->mHullParams = nullptr;
-
-		if (passParams->mDomainParams != nullptr)
-			passParameters->mDomainParams = passParams->mDomainParams->getCore();
-		else
-			passParameters->mDomainParams = nullptr;
-
-		if (passParams->mComputeParams != nullptr)
-			passParameters->mComputeParams = passParams->mComputeParams->getCore();
-		else
-			passParameters->mComputeParams = nullptr;
-
-		return passParameters;
-	}
-
-	bool areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets)
-	{
-		bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize
-			&& paramA.type == paramB.type && paramA.arrayElementStride == paramB.arrayElementStride;
-
-		if (!ignoreBufferOffsets)
-			equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
-
-		return equal;
-	}
-
-	Set<String> determineValidShareableParamBlocks(const Vector<SPtr<GpuParamDesc>>& paramDescs)
-	{
-		// Make sure param blocks with the same name actually are the same
-		Map<String, std::pair<String, SPtr<GpuParamDesc>>> uniqueParamBlocks;
-		Map<String, bool> validParamBlocks;
-
-		for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
-		{
-			const GpuParamDesc& curDesc = **iter;
-			for (auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
-			{
-				bool isBlockValid = true;
-				const GpuParamBlockDesc& curBlock = blockIter->second;
-
-				if (!curBlock.isShareable) // Non-shareable buffers are handled differently, they're allowed same names
-					continue;
-
-				auto iterFind = uniqueParamBlocks.find(blockIter->first);
-				if (iterFind == uniqueParamBlocks.end())
-				{
-					uniqueParamBlocks[blockIter->first] = std::make_pair(blockIter->first, *iter);
-					validParamBlocks[blockIter->first] = true;
-					continue;
-				}
-
-				String otherBlockName = iterFind->second.first;
-				SPtr<GpuParamDesc> otherDesc = iterFind->second.second;
-
-				for (auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
-				{
-					const GpuParamDataDesc& myParam = myParamIter->second;
-
-					if (myParam.paramBlockSlot != curBlock.slot)
-						continue; // Param is in another block, so we will check it when its time for that block
-
-					auto otherParamFind = otherDesc->params.find(myParamIter->first);
-
-					// Cannot find other param, blocks aren't equal
-					if (otherParamFind == otherDesc->params.end())
-					{
-						isBlockValid = false;
-						break;
-					}
-
-					const GpuParamDataDesc& otherParam = otherParamFind->second;
-
-					if (!areParamsEqual(myParam, otherParam, false) || curBlock.name != otherBlockName)
-					{
-						isBlockValid = false;
-						break;
-					}
-				}
-
-				if (!isBlockValid)
-				{
-					if (validParamBlocks[blockIter->first])
-					{
-						LOGWRN("Found two param blocks with the same name but different contents: " + blockIter->first);
-						validParamBlocks[blockIter->first] = false;
-					}
-				}
-			}
-		}
-
-		Set<String> validParamBlocksReturn;
-		for (auto iter = validParamBlocks.begin(); iter != validParamBlocks.end(); ++iter)
-		{
-			if (iter->second)
-				validParamBlocksReturn.insert(iter->first);
-		}
-
-		return validParamBlocksReturn;
-	}
-
-	Vector<ShaderBlockDesc> determineShaderBlockData(const Set<String>& paramBlocks, const Vector<SPtr<GpuParamDesc>>& paramDescs,
-		const Map<String, SHADER_PARAM_BLOCK_DESC>& shaderDesc)
-	{
-		Vector<ShaderBlockDesc> output;
-		for (auto iter = paramBlocks.begin(); iter != paramBlocks.end(); ++iter)
-		{
-			ShaderBlockDesc shaderBlockDesc;
-			shaderBlockDesc.create = true;
-			shaderBlockDesc.usage = GPBU_STATIC;
-			shaderBlockDesc.size = 0;
-			shaderBlockDesc.name = *iter;
-
-			auto iterFind = shaderDesc.find(*iter);
-			if (iterFind != shaderDesc.end())
-			{
-				shaderBlockDesc.create = !iterFind->second.shared && iterFind->second.rendererSemantic == StringID::NONE;
-				shaderBlockDesc.usage = iterFind->second.usage;
-			}
-
-			for (auto iter2 = paramDescs.begin(); iter2 != paramDescs.end(); ++iter2)
-			{
-				auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
-
-				if (findParamBlockDesc != (*iter2)->paramBlocks.end())
-				{
-					shaderBlockDesc.size = findParamBlockDesc->second.blockSize * sizeof(UINT32);
-					break;
-				}
-			}
-
-			output.push_back(shaderBlockDesc);
-		}
-
-		return output;
-	}
-
 	template<class T>
 	bool isShaderValid(const T& shader) { return false; }
 
@@ -207,96 +33,20 @@ namespace BansheeEngine
 	template<>
 	bool isShaderValid(const SPtr<ShaderCore>& shader) { return shader != nullptr; }
 
-	Vector<SPtr<GpuParamDesc>> MaterialBase::getAllParamDescs(const SPtr<Technique>& technique)
+	template<bool Core>
+	SPtr<typename TMaterial<Core>::GpuParamsSetType> TMaterial<Core>::createParamsSet(UINT32 techniqueIdx)
 	{
-		Vector<SPtr<GpuParamDesc>> allParamDescs;
-
-		// Make sure all gpu programs are fully loaded
-		for (UINT32 i = 0; i < technique->getNumPasses(); i++)
-		{
-			SPtr<Pass> curPass = technique->getPass(i);
-
-			SPtr<GpuProgram> vertProgram = curPass->getVertexProgram();
-			if (vertProgram)
-			{
-				vertProgram->blockUntilCoreInitialized();
-				allParamDescs.push_back(vertProgram->getParamDesc());
-			}
-
-			SPtr<GpuProgram> fragProgram = curPass->getFragmentProgram();
-			if (fragProgram)
-			{
-				fragProgram->blockUntilCoreInitialized();
-				allParamDescs.push_back(fragProgram->getParamDesc());
-			}
-
-			SPtr<GpuProgram> geomProgram = curPass->getGeometryProgram();
-			if (geomProgram)
-			{
-				geomProgram->blockUntilCoreInitialized();
-				allParamDescs.push_back(geomProgram->getParamDesc());
-			}
-
-			SPtr<GpuProgram> hullProgram = curPass->getHullProgram();
-			if (hullProgram)
-			{
-				hullProgram->blockUntilCoreInitialized();
-				allParamDescs.push_back(hullProgram->getParamDesc());
-			}
-
-			SPtr<GpuProgram> domainProgram = curPass->getDomainProgram();
-			if (domainProgram)
-			{
-				domainProgram->blockUntilCoreInitialized();
-				allParamDescs.push_back(domainProgram->getParamDesc());
-			}
-
-			SPtr<GpuProgram> computeProgram = curPass->getComputeProgram();
-			if (computeProgram)
-			{
-				computeProgram->blockUntilCoreInitialized();
-				allParamDescs.push_back(computeProgram->getParamDesc());
-			}
-		}
+		if (techniqueIdx >= (UINT32)mTechniques.size())
+			return nullptr;
 
-		return allParamDescs;
+		SPtr<TechniqueType> technique = mTechniques[techniqueIdx];
+		return bs_shared_ptr_new<GpuParamsSetType>(technique, mShader);
 	}
 
-	Vector<SPtr<GpuParamDesc>> MaterialBase::getAllParamDescs(const SPtr<TechniqueCore>& technique)
+	template<bool Core>
+	void TMaterial<Core>::updateParamsSet(const SPtr<GpuParamsSetType>& paramsSet, UINT32 techniqueIdx, bool forceRefresh)
 	{
-		Vector<SPtr<GpuParamDesc>> allParamDescs;
-
-		// Make sure all gpu programs are fully loaded
-		for (UINT32 i = 0; i < technique->getNumPasses(); i++)
-		{
-			SPtr<PassCore> curPass = technique->getPass(i);
-
-			SPtr<GpuProgramCore> vertProgram = curPass->getVertexProgram();
-			if (vertProgram)
-				allParamDescs.push_back(vertProgram->getParamDesc());
-
-			SPtr<GpuProgramCore> fragProgram = curPass->getFragmentProgram();
-			if (fragProgram)
-				allParamDescs.push_back(fragProgram->getParamDesc());
-
-			SPtr<GpuProgramCore> geomProgram = curPass->getGeometryProgram();
-			if (geomProgram)
-				allParamDescs.push_back(geomProgram->getParamDesc());
-
-			SPtr<GpuProgramCore> hullProgram = curPass->getHullProgram();
-			if (hullProgram)
-				allParamDescs.push_back(hullProgram->getParamDesc());
-
-			SPtr<GpuProgramCore> domainProgram = curPass->getDomainProgram();
-			if (domainProgram)
-				allParamDescs.push_back(domainProgram->getParamDesc());
-
-			SPtr<GpuProgramCore> computeProgram = curPass->getComputeProgram();
-			if (computeProgram)
-				allParamDescs.push_back(computeProgram->getParamDesc());
-		}
-
-		return allParamDescs;
+		// TODO
 	}
 
 	template<bool Core>
@@ -343,8 +93,7 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		SPtr<Vector<TGpuParamStruct<Core>>> gpuParams;
-		return TMaterialParamStruct<Core>(name, mParams, gpuParams);
+		return TMaterialParamStruct<Core>(name, mParams);
 	}
 
 	template<bool Core>
@@ -352,42 +101,7 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		SPtr<Vector<TGpuParamTexture<Core>>> gpuParams;
-
-		if (mShader != nullptr)
-		{
-			const auto& params = mShader->getTextureParams();
-			auto iterFind = params.find(name);
-			if (iterFind != params.end())
-			{
-				for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-				{
-					SPtr<PassParamsType> params = *iter;
-					for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
-					{
-						GpuParamsType& paramPtr = params->getParamByIdx(i);
-						if (paramPtr)
-						{
-							for (auto& gpuVarName : iterFind->second.gpuVariableNames)
-							{
-								if (paramPtr->hasTexture(gpuVarName))
-								{
-									if (gpuParams == nullptr)
-										gpuParams = bs_shared_ptr_new<Vector<TGpuParamTexture<Core>>>();
-
-									gpuParams->push_back(TGpuParamTexture<Core>());
-									paramPtr->getTextureParam(gpuVarName, gpuParams->back());
-
-									break;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-
-		return TMaterialParamTexture<Core>(name, mParams, gpuParams);
+		return TMaterialParamTexture<Core>(name, mParams);
 	}
 
 	template<bool Core>
@@ -395,42 +109,7 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		SPtr<Vector<TGpuParamLoadStoreTexture<Core>>> gpuParams;
-
-		if (mShader != nullptr)
-		{
-			const auto& params = mShader->getTextureParams();
-			auto iterFind = params.find(name);
-			if (iterFind != params.end())
-			{
-				for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-				{
-					SPtr<PassParamsType> params = *iter;
-					for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
-					{
-						GpuParamsType& paramPtr = params->getParamByIdx(i);
-						if (paramPtr)
-						{
-							for (auto& gpuVarName : iterFind->second.gpuVariableNames)
-							{
-								if (paramPtr->hasLoadStoreTexture(gpuVarName))
-								{
-									if (gpuParams == nullptr)
-										gpuParams = bs_shared_ptr_new<Vector<TGpuParamLoadStoreTexture<Core>>>();
-
-									gpuParams->push_back(TGpuParamLoadStoreTexture<Core>());
-									paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams->back());
-
-									break;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-
-		return TMaterialParamLoadStoreTexture<Core>(name, mParams, gpuParams);
+		return TMaterialParamLoadStoreTexture<Core>(name, mParams);
 	}
 
 	template<bool Core>
@@ -438,42 +117,7 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		SPtr<Vector<TGpuParamBuffer<Core>>> gpuParams;
-
-		if (mShader != nullptr)
-		{
-			const auto& params = mShader->getBufferParams();
-			auto iterFind = params.find(name);
-			if (iterFind != params.end())
-			{
-				for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-				{
-					SPtr<PassParamsType> params = *iter;
-					for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
-					{
-						GpuParamsType& paramPtr = params->getParamByIdx(i);
-						if (paramPtr)
-						{
-							for (auto& gpuVarName : iterFind->second.gpuVariableNames)
-							{
-								if (paramPtr->hasBuffer(gpuVarName))
-								{
-									if (gpuParams == nullptr)
-										gpuParams = bs_shared_ptr_new<Vector<TGpuParamBuffer<Core>>>();
-
-									gpuParams->push_back(TGpuParamBuffer<Core>());
-									paramPtr->getBufferParam(gpuVarName, gpuParams->back());
-
-									break;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-
-		return TMaterialParamBuffer<Core>(name, mParams, gpuParams);
+		return TMaterialParamBuffer<Core>(name, mParams);
 	}
 
 	template<bool Core>
@@ -481,68 +125,13 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		SPtr<Vector<TGpuParamSampState<Core>>> gpuParams;
-
-		if (mShader != nullptr)
-		{
-			const auto& params = mShader->getSamplerParams();
-			auto iterFind = params.find(name);
-			if (iterFind != params.end())
-			{
-				for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-				{
-					SPtr<PassParamsType> params = *iter;
-					for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
-					{
-						GpuParamsType& paramPtr = params->getParamByIdx(i);
-						if (paramPtr)
-						{
-							for (auto& gpuVarName : iterFind->second.gpuVariableNames)
-							{
-								if (paramPtr->hasSamplerState(gpuVarName))
-								{
-									if(gpuParams == nullptr)
-										gpuParams = bs_shared_ptr_new<Vector<TGpuParamSampState<Core>>>();
-
-									gpuParams->push_back(TGpuParamSampState<Core>());
-									paramPtr->getSamplerStateParam(gpuVarName, gpuParams->back());
-
-									break;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-
-		return TMaterialParamSampState<Core>(name, mParams, gpuParams);
-	}
-
-	template<bool Core>
-	void TMaterial<Core>::setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
-	{
-		for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-		{
-			SPtr<PassParamsType> params = *iter;
-
-			for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
-			{
-				GpuParamsType& paramPtr = params->getParamByIdx(i);
-				if (paramPtr)
-				{
-					if (paramPtr->hasParamBlock(name))
-						paramPtr->setParamBlockBuffer(name, paramBlock);
-				}
-			}
-		}
+		return TMaterialParamSampState<Core>(name, mParams);
 	}
 
 	template<bool Core>
 	void TMaterial<Core>::initializeTechniques()
 	{
 		mTechniques.clear();
-		mParametersPerPass.clear();
 
 		if (isShaderValid(mShader))
 		{
@@ -552,96 +141,10 @@ namespace BansheeEngine
 			if (mTechniques.size() == 0)
 				return;
 
-			Vector<SPtr<GpuParamDesc>> allParamDescs = getAllParamDescs(mTechniques[0]);
-
-			// Fill out various helper structures
-			Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
-			Vector<ShaderBlockDesc> paramBlockData = determineShaderBlockData(validShareableParamBlocks, allParamDescs, mShader->getParamBlocks());
-
-			Map<String, ParamBlockPtrType> paramBlockBuffers;
-
-			// Create param blocks
-			for (auto& paramBlock : paramBlockData)
-			{
-				ParamBlockPtrType newParamBlockBuffer;
-				if (paramBlock.create)
-					newParamBlockBuffer = ParamBlockType::create(paramBlock.size, paramBlock.usage);
-
-				paramBlockBuffers[paramBlock.name] = newParamBlockBuffer;
-			}
-
-			for (UINT32 i = 0; i < mTechniques[0]->getNumPasses(); i++)
-			{
-				SPtr<PassType> curPass = mTechniques[0]->getPass(i);
-				SPtr<PassParamsType> params = SPtr<PassParamsType>(new PassParamsType());
-
-				GpuProgramType vertProgram = curPass->getVertexProgram();
-				if (vertProgram)
-					params->mVertParams = vertProgram->createParameters();
-
-				GpuProgramType fragProgram = curPass->getFragmentProgram();
-				if (fragProgram)
-					params->mFragParams = fragProgram->createParameters();
-
-				GpuProgramType geomProgram = curPass->getGeometryProgram();
-				if (geomProgram)
-					params->mGeomParams = geomProgram->createParameters();
-
-				GpuProgramType hullProgram = curPass->getHullProgram();
-				if (hullProgram)
-					params->mHullParams = hullProgram->createParameters();
-
-				GpuProgramType domainProgram = curPass->getDomainProgram();
-				if (domainProgram)
-					params->mDomainParams = domainProgram->createParameters();
-
-				GpuProgramType computeProgram = curPass->getComputeProgram();
-				if (computeProgram)
-					params->mComputeParams = computeProgram->createParameters();
-
-				mParametersPerPass.push_back(params);
-			}
-
-			// Assign param block buffers
-			for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-			{
-				SPtr<PassParamsType> params = *iter;
-
-				for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
-				{
-					GpuParamsType& paramPtr = params->getParamByIdx(i);
-					if (paramPtr)
-					{
-						// Assign shareable buffers
-						for (auto& block : paramBlockData)
-						{
-							const String& paramBlockName = block.name;
-							if (paramPtr->hasParamBlock(paramBlockName))
-							{
-								ParamBlockPtrType blockBuffer = paramBlockBuffers[paramBlockName];
-
-								paramPtr->setParamBlockBuffer(paramBlockName, blockBuffer);
-							}
-						}
-
-						// Create non-shareable ones
-						const GpuParamDesc& desc = paramPtr->getParamDesc();
-						for (auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
-						{
-							if (!iterBlockDesc->second.isShareable)
-							{
-								ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(iterBlockDesc->second.blockSize * sizeof(UINT32));
-
-								paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
-							}
-						}
-					}
-				}
-			}
-
-			// Assign default parameters
 			initDefaultParameters();
 		}
+		else
+			mParams = nullptr;
 
 		_markDependenciesDirty();
 	}
@@ -775,38 +278,7 @@ namespace BansheeEngine
 	{
 		throwIfNotInitialized();
 
-		SPtr<Vector<TGpuDataParam<T, Core>>> gpuParams;
-
-		if (mShader != nullptr)
-		{
-			const auto& params = mShader->getDataParams();
-			auto iterFind = params.find(name);
-			if (iterFind != params.end())
-			{
-				const String& gpuVarName = iterFind->second.gpuVariableName;
-				gpuParams = bs_shared_ptr_new<Vector<TGpuDataParam<T, Core>>>();
-
-				for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
-				{
-					SPtr<PassParamsType> params = *iter;
-
-					for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
-					{
-						GpuParamsType& paramPtr = params->getParamByIdx(i);
-						if (paramPtr)
-						{
-							if (paramPtr->hasParam(gpuVarName))
-							{
-								gpuParams->push_back(TGpuDataParam<T, Core>());
-								paramPtr->template getParam<T>(gpuVarName, gpuParams->back());
-							}
-						}
-					}
-				}
-			}
-		}
-
-		output = TMaterialDataParam<T, Core>(name, mParams, gpuParams);
+		output = TMaterialDataParam<T, Core>(name, mParams);
 	}
 
 	template<bool Core>
@@ -865,21 +337,18 @@ namespace BansheeEngine
 	template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix4x3, true>&) const;
 
 	MaterialCore::MaterialCore(const SPtr<ShaderCore>& shader)
+		: mVersion(1)
 	{
 		setShader(shader);
 	}
 
 	MaterialCore::MaterialCore(const SPtr<ShaderCore>& shader, const Vector<SPtr<TechniqueCore>>& techniques,
-		const SPtr<MaterialParamsCore>& materialParams, const Vector<SPtr<PassParametersCore>>& passParams)
+		const SPtr<MaterialParamsCore>& materialParams)
+		: mVersion(1)
 	{
 		mShader = shader;
 		mParams = materialParams;
 		mTechniques = techniques;
-
-		UINT32 numPassParams = (UINT32)passParams.size();
-		mParametersPerPass.resize(numPassParams);
-		for (UINT32 i = 0; i < numPassParams; i++)
-			mParametersPerPass[i] = passParams[i];
 	}
 
 	void MaterialCore::setShader(const SPtr<ShaderCore>& shader)
@@ -895,22 +364,10 @@ namespace BansheeEngine
 	{
 		char* dataPtr = (char*)data.getBuffer();
 
-		mParametersPerPass.clear();
-
-		UINT32 numPasses = 0;
-		dataPtr = rttiReadElem(numPasses, dataPtr);
-
-		for (UINT32 i = 0; i < numPasses; i++)
-		{
-			SPtr<PassParametersCore>* passParameters = (SPtr<PassParametersCore>*)dataPtr;
-
-			mParametersPerPass.push_back(*passParameters);
-
-			passParameters->~SPtr<PassParametersCore>();
-			dataPtr += sizeof(SPtr<PassParametersCore>);
-		}
-
 		SPtr<ShaderCore>* shader = (SPtr<ShaderCore>*)dataPtr;
+		if (mShader != *shader)
+			mVersion++;
+
 		mShader = *shader;
 		shader->~SPtr<ShaderCore>();
 		dataPtr += sizeof(SPtr<ShaderCore>);
@@ -1009,13 +466,9 @@ namespace BansheeEngine
 			for (UINT32 i = 0; i < (UINT32)mTechniques.size(); i++)
 				techniques[i] = mTechniques[i]->getCore();
 			
-			Vector<SPtr<PassParametersCore>> passParams;
-			for (auto& passParam : mParametersPerPass)
-				passParams.push_back(convertParamsToCore(passParam));
-
 			SPtr<MaterialParamsCore> materialParams = bs_shared_ptr_new<MaterialParamsCore>(shader, mParams);
 
-			material = new (bs_alloc<MaterialCore>()) MaterialCore(shader, techniques, materialParams, passParams);
+			material = new (bs_alloc<MaterialCore>()) MaterialCore(shader, techniques, materialParams);
 		}
 		
 		if (material == nullptr)
@@ -1029,27 +482,15 @@ namespace BansheeEngine
 
 	CoreSyncData Material::syncToCore(FrameAlloc* allocator)
 	{
-		UINT32 numPasses = (UINT32)mParametersPerPass.size();
-
 		UINT32 paramsSize = 0;
 		if (mParams != nullptr)
 			mParams->getSyncData(nullptr, paramsSize);
 
-		UINT32 size = sizeof(UINT32) * 3 + numPasses * sizeof(SPtr<PassParametersCore>)
-			+ sizeof(SPtr<ShaderCore>) + sizeof(SPtr<TechniqueCore>) + paramsSize;
+		UINT32 size = sizeof(UINT32) * 2 + sizeof(SPtr<ShaderCore>) + sizeof(SPtr<TechniqueCore>) + paramsSize;
 
 		UINT8* buffer = allocator->alloc(size);
 		char* dataPtr = (char*)buffer;
-		dataPtr = rttiWriteElem(numPasses, dataPtr);
-
-		for (UINT32 i = 0; i < numPasses; i++)
-		{
-			SPtr<PassParametersCore>* passParameters = new (dataPtr) SPtr<PassParametersCore>();
-			*passParameters = convertParamsToCore(mParametersPerPass[i]);
-
-			dataPtr += sizeof(SPtr<PassParametersCore>);
-		}
-
+		
 		SPtr<ShaderCore>* shader = new (dataPtr)SPtr<ShaderCore>();
 		if (mShader.isLoaded(false))
 			*shader = mShader->getCore();
@@ -1082,16 +523,6 @@ namespace BansheeEngine
 	{
 		if (mShader.isLoaded())
 			dependencies.push_back(mShader.get());
-
-		for (auto& params : mParametersPerPass)
-		{
-			for (UINT32 i = 0; i < PassParameters::NUM_PARAMS; i++)
-			{
-				SPtr<GpuParams> gpuParams = params->getParamByIdx(i);
-				if (gpuParams != nullptr)
-					dependencies.push_back(gpuParams.get());
-			}
-		}
 	}
 
 	void Material::getListenerResources(Vector<HResource>& resources)

+ 13 - 54
Source/BansheeCore/Source/BsMaterialParam.cpp

@@ -8,9 +8,8 @@
 namespace BansheeEngine
 {
 	template<class T, bool Core>
-	TMaterialDataParam<T, Core>::TMaterialDataParam(const String& name, const SPtr<MaterialParamsType>& params,
-		const SPtr<Vector<TGpuDataParam<T, Core>>>& gpuParams)
-		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
+	TMaterialDataParam<T, Core>::TMaterialDataParam(const String& name, const SPtr<MaterialParamsType>& params)
+		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr)
 	{
 		if(params != nullptr)
 		{
@@ -43,12 +42,6 @@ namespace BansheeEngine
 		}
 
 		mMaterialParams->setDataParam(mParamIndex, arrayIdx, value);
-
-		if (mGPUParams != nullptr)
-		{
-			for (auto& param : *mGPUParams)
-				param.set(value, arrayIdx);
-		}
 	}
 
 	template<class T, bool Core>
@@ -63,9 +56,8 @@ namespace BansheeEngine
 	}
 
 	template<bool Core>
-	TMaterialParamStruct<Core>::TMaterialParamStruct(const String& name, const SPtr<MaterialParamsType>& params,
-		const SPtr<Vector<TGpuParamStruct<Core>>>& gpuParams)
-		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
+	TMaterialParamStruct<Core>::TMaterialParamStruct(const String& name, const SPtr<MaterialParamsType>& params)
+		:mParamIndex(0), mArraySize(0), mMaterialParams(nullptr)
 	{
 		if (params != nullptr)
 		{
@@ -97,12 +89,6 @@ namespace BansheeEngine
 		}
 
 		mMaterialParams->setStructData(mParamIndex + arrayIdx, value, sizeBytes);
-
-		if (mGPUParams != nullptr)
-		{
-			for (auto& param : *mGPUParams)
-				param.set(value, sizeBytes, arrayIdx);
-		}
 	}
 
 	template<bool Core>
@@ -121,9 +107,8 @@ namespace BansheeEngine
 	}
 
 	template<bool Core>
-	TMaterialParamTexture<Core>::TMaterialParamTexture(const String& name, const SPtr<MaterialParamsType>& params,
-		const SPtr<Vector<TGpuParamTexture<Core>>>& gpuParams)
-		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
+	TMaterialParamTexture<Core>::TMaterialParamTexture(const String& name, const SPtr<MaterialParamsType>& params)
+		:mParamIndex(0), mMaterialParams(nullptr)
 	{
 		if (params != nullptr)
 		{
@@ -152,12 +137,6 @@ namespace BansheeEngine
 			mMaterialParams->getDefaultTexture(mParamIndex, newValue);
 
 		mMaterialParams->setTexture(mParamIndex, newValue);
-
-		if (mGPUParams != nullptr)
-		{
-			for (auto& param : *mGPUParams)
-				param.set(newValue);
-		}
 	}
 
 	template<bool Core>
@@ -173,9 +152,9 @@ namespace BansheeEngine
 	}
 	
 	template<bool Core>
-	TMaterialParamLoadStoreTexture<Core>::TMaterialParamLoadStoreTexture(const String& name, const SPtr<MaterialParamsType>& params,
-		const SPtr<Vector<TGpuParamLoadStoreTexture<Core>>>& gpuParams)
-		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
+	TMaterialParamLoadStoreTexture<Core>::TMaterialParamLoadStoreTexture(const String& name, 
+		const SPtr<MaterialParamsType>& params)
+		:mParamIndex(0), mMaterialParams(nullptr)
 	{
 		if (params != nullptr)
 		{
@@ -199,12 +178,6 @@ namespace BansheeEngine
 			return;
 
 		mMaterialParams->setLoadStoreTexture(mParamIndex, texture, surface);
-
-		if (mGPUParams != nullptr)
-		{
-			for (auto& param : *mGPUParams)
-				param.set(texture, surface);
-		}
 	}
 
 	template<bool Core>
@@ -221,9 +194,8 @@ namespace BansheeEngine
 	}
 	
 	template<bool Core>
-	TMaterialParamBuffer<Core>::TMaterialParamBuffer(const String& name, const SPtr<MaterialParamsType>& params,
-		const SPtr<Vector<TGpuParamBuffer<Core>>>& gpuParams)
-		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
+	TMaterialParamBuffer<Core>::TMaterialParamBuffer(const String& name, const SPtr<MaterialParamsType>& params)
+		:mParamIndex(0), mMaterialParams(nullptr)
 	{
 		if (params != nullptr)
 		{
@@ -247,12 +219,6 @@ namespace BansheeEngine
 			return;
 
 		mMaterialParams->setBuffer(mParamIndex, buffer);
-
-		if (mGPUParams != nullptr)
-		{
-			for (auto& param : *mGPUParams)
-				param.set(buffer);
-		}
 	}
 
 	template<bool Core>
@@ -268,9 +234,8 @@ namespace BansheeEngine
 	}
 
 	template<bool Core>
-	TMaterialParamSampState<Core>::TMaterialParamSampState(const String& name, const SPtr<MaterialParamsType>& params,
-		const SPtr<Vector<TGpuParamSampState<Core>>>& gpuParams)
-		:mParamIndex(0), mMaterialParams(nullptr), mGPUParams(gpuParams)
+	TMaterialParamSampState<Core>::TMaterialParamSampState(const String& name, const SPtr<MaterialParamsType>& params)
+		:mParamIndex(0), mMaterialParams(nullptr)
 	{
 		if (params != nullptr)
 		{
@@ -299,12 +264,6 @@ namespace BansheeEngine
 			mMaterialParams->getDefaultSamplerState(mParamIndex, newValue);
 
 		mMaterialParams->setSamplerState(mParamIndex, newValue);
-
-		if (mGPUParams != nullptr)
-		{
-			for (auto& param : *mGPUParams)
-				param.set(newValue);
-		}
 	}
 
 	template<bool Core>

+ 1 - 0
Source/BansheeEditor/Include/BsDockManager.h

@@ -298,6 +298,7 @@ namespace BansheeEngine
 		
 		SPtr<CameraCore> mCamera;
 		SPtr<MaterialCore> mMaterial;
+		SPtr<GpuParamsSetCore> mParams;
 		SPtr<MeshCore> mMesh;
 		DockManager::DockLocation mHighlightedDropLoc;
 		bool mShowOverlay;

+ 16 - 12
Source/BansheeEditor/Include/BsGizmoManager.h

@@ -487,39 +487,43 @@ namespace BansheeEngine
 		struct SolidMaterialData
 		{
 			SPtr<MaterialCore> mat;
-			GpuParamMat4Core mViewProj;
-			GpuParamVec4Core mViewDir;
+			SPtr<GpuParamsSetCore> params;
+			GpuParamMat4Core viewProj;
+			GpuParamVec4Core viewDir;
 		};
 
 		/**	Wire gizmo material and parameter handles. */
 		struct WireMaterialData
 		{
 			SPtr<MaterialCore> mat;
-			GpuParamMat4Core mViewProj;
+			SPtr<GpuParamsSetCore> params;
+			GpuParamMat4Core viewProj;
 		};
 
 		/**	Icon gizmo material and parameter handles. */
 		struct IconMaterialData
 		{
 			SPtr<MaterialCore> mat;
-			SPtr<GpuParamsCore> mFragParams[2];
-			GpuParamMat4Core mViewProj[2];
-			GpuParamTextureCore mTexture[2];
+			SPtr<GpuParamsSetCore> params;
+			GpuParamMat4Core viewProj[2];
+			GpuParamTextureCore texture[2];
 		};
 
 		/**	Text gizmo material and parameter handles. */
 		struct TextMaterialData
 		{
 			SPtr<MaterialCore> mat;
-			GpuParamMat4Core mViewProj;
-			GpuParamTextureCore mTexture;
+			SPtr<GpuParamsSetCore> params;
+			GpuParamMat4Core viewProj;
+			GpuParamTextureCore texture;
 		};
 
 		/**	Gizmo material and parameter handles used for picking. */
 		struct PickingMaterialData
 		{
 			SPtr<MaterialCore> mat;
-			GpuParamMat4Core mViewProj;
+			SPtr<GpuParamsSetCore> params;
+			GpuParamMat4Core viewProj;
 		};
 
 		/**
@@ -528,9 +532,9 @@ namespace BansheeEngine
 		struct AlphaPickingMaterialData
 		{
 			SPtr<MaterialCore> mat;
-			SPtr<GpuParamsCore> mFragParams;
-			GpuParamMat4Core mViewProj;
-			GpuParamTextureCore mTexture;
+			SPtr<GpuParamsSetCore> params;
+			GpuParamMat4Core viewProj;
+			GpuParamTextureCore texture;
 		};
 
 		/** Type of mesh that can be drawn. */

+ 3 - 0
Source/BansheeEditor/Include/BsHandleDrawManager.h

@@ -206,6 +206,7 @@ namespace BansheeEngine
 		struct SolidMaterialData
 		{
 			SPtr<MaterialCore> mat;
+			SPtr<GpuParamsSetCore> params;
 			GpuParamMat4Core viewProj;
 			GpuParamVec4Core viewDir;
 		};
@@ -214,6 +215,7 @@ namespace BansheeEngine
 		struct LineMaterialData
 		{
 			SPtr<MaterialCore> mat;
+			SPtr<GpuParamsSetCore> params;
 			GpuParamMat4Core viewProj;
 		};
 
@@ -221,6 +223,7 @@ namespace BansheeEngine
 		struct TextMaterialData
 		{
 			SPtr<MaterialCore> mat;
+			SPtr<GpuParamsSetCore> params;
 			GpuParamMat4Core viewProj;
 			GpuParamTextureCore texture;
 		};

+ 1 - 0
Source/BansheeEditor/Include/BsSceneGrid.h

@@ -114,6 +114,7 @@ namespace BansheeEngine
 		SPtr<CameraCore> mCamera;
 		SPtr<MeshCore> mGridMesh;
 		SPtr<MaterialCore> mGridMaterial;
+		SPtr<GpuParamsSetCore> mMaterialParams;
 		float mSpacing = 1.0f;
 		bool mFadeGrid = true;
 		Vector3 mGridPlaneNormal;

+ 2 - 4
Source/BansheeEditor/Include/BsScenePicking.h

@@ -84,10 +84,8 @@ namespace BansheeEngine
 			SPtr<MaterialCore> mMatPickingCore;
 			SPtr<MaterialCore> mMatPickingAlphaCore;
 
-			SPtr<GpuParamsCore> mParamPickingVertParams;
-			SPtr<GpuParamsCore> mParamPickingFragParams;
-			SPtr<GpuParamsCore> mParamPickingAlphaVertParams;
-			SPtr<GpuParamsCore> mParamPickingAlphaFragParams;
+			SPtr<GpuParamsSetCore> mPickingParams;
+			SPtr<GpuParamsSetCore> mPickingAlphaParams;
 
 			GpuParamMat4Core mParamPickingWVP;
 			GpuParamMat4Core mParamPickingAlphaWVP;

+ 1 - 0
Source/BansheeEditor/Include/BsSelectionRenderer.h

@@ -87,6 +87,7 @@ namespace BansheeEngine
 
 		// Immutable
 		SPtr<MaterialCore> mMaterial;
+		SPtr<GpuParamsSetCore> mParams;
 		GpuParamMat4Core mMatWorldViewProj;
 		GpuParamColorCore mColor;
 

+ 4 - 1
Source/BansheeEditor/Source/BsDockManager.cpp

@@ -1145,6 +1145,7 @@ namespace BansheeEngine
 	void DockOverlayRenderer::initialize(const SPtr<MaterialCore>& material)
 	{
 		mMaterial = material;
+		mParams = material->createParamsSet();
 	}
 
 	void DockOverlayRenderer::updateData(const SPtr<CameraCore>& camera, const SPtr<MeshCore>& mesh, bool active, 
@@ -1205,8 +1206,10 @@ namespace BansheeEngine
 		}
 
 		mMaterial->setColor("highlightActive", highlightColor);
+		mMaterial->updateParamsSet(mParams);
 
-		gRendererUtility().setPass(mMaterial, 0);
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParams);
 		gRendererUtility().draw(mMesh, mMesh->getProperties().getSubMesh(0));
 	}
 }

+ 65 - 58
Source/BansheeEditor/Source/BsGizmoManager.cpp

@@ -13,6 +13,7 @@
 #include "BsBuiltinEditorResources.h"
 #include "BsMaterial.h"
 #include "BsGpuParams.h"
+#include "BsGpuParamsSet.h"
 #include "BsRenderAPI.h"
 #include "BsCoreRenderer.h"
 #include "BsRendererUtility.h"
@@ -958,78 +959,72 @@ namespace BansheeEngine
 		mAlphaPickingMaterial.mat = initData.alphaPickingMat;
 
 		{
-			SPtr<MaterialCore> mat = mLineMaterial.mat;
-			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
+			mLineMaterial.params = mLineMaterial.mat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams = mLineMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
 
-			vertParams->getParam("matViewProj", mLineMaterial.mViewProj);
+			vertParams->getParam("matViewProj", mLineMaterial.viewProj);
 		}
 
 		{
-			SPtr<MaterialCore> mat = mSolidMaterial.mat;
-			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
-			SPtr<GpuParamsCore> fragParams = mat->getPassParameters(0)->mFragParams;
+			mSolidMaterial.params = mSolidMaterial.mat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams = mSolidMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
+			SPtr<GpuParamsCore> fragParams = mSolidMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			vertParams->getParam("matViewProj", mSolidMaterial.mViewProj);
-			fragParams->getParam("viewDir", mSolidMaterial.mViewDir);
+			vertParams->getParam("matViewProj", mSolidMaterial.viewProj);
+			fragParams->getParam("viewDir", mSolidMaterial.viewDir);
 		}
 
 		{
-			SPtr<MaterialCore> mat = mWireMaterial.mat;
-			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
-			SPtr<GpuParamsCore> fragParams = mat->getPassParameters(0)->mFragParams;
+			mWireMaterial.params = mWireMaterial.mat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams = mWireMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
+			SPtr<GpuParamsCore> fragParams = mWireMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			vertParams->getParam("matViewProj", mWireMaterial.mViewProj);
+			vertParams->getParam("matViewProj", mWireMaterial.viewProj);
 		}
 
 		{
-			SPtr<MaterialCore> mat = mIconMaterial.mat;
-			SPtr<PassParametersCore> pass0Params = mat->getPassParameters(0);
-			SPtr<PassParametersCore> pass1Params = mat->getPassParameters(1);
+			mIconMaterial.params = mIconMaterial.mat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams0 = mIconMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM, 0);
+			SPtr<GpuParamsCore> vertParams1 = mIconMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM, 1);
 
-			SPtr<GpuParamsCore> vertParams0 = pass0Params->mVertParams;
-			SPtr<GpuParamsCore> vertParams1 = pass1Params->mVertParams;
+			SPtr<GpuParamsCore> fragParams0 = mIconMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM, 0);
+			SPtr<GpuParamsCore> fragParams1 = mIconMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM, 1);
 
-			vertParams0->getParam("matViewProj", mIconMaterial.mViewProj[0]);
-			vertParams1->getParam("matViewProj", mIconMaterial.mViewProj[1]);
+			vertParams0->getParam("matViewProj", mIconMaterial.viewProj[0]);
+			vertParams1->getParam("matViewProj", mIconMaterial.viewProj[1]);
 
-			mIconMaterial.mFragParams[0] = pass0Params->mFragParams;
-			mIconMaterial.mFragParams[1] = pass1Params->mFragParams;
-
-			mIconMaterial.mFragParams[0]->getTextureParam("mainTexture", mIconMaterial.mTexture[0]);
-			mIconMaterial.mFragParams[1]->getTextureParam("mainTexture", mIconMaterial.mTexture[1]);
+			fragParams0->getTextureParam("mainTexture", mIconMaterial.texture[0]);
+			fragParams1->getTextureParam("mainTexture", mIconMaterial.texture[1]);
 		}
 
 		{
-			SPtr<MaterialCore> mat = mPickingMaterial.mat;
-			SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
+			mPickingMaterial.params = mPickingMaterial.mat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams = mPickingMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
 
-			vertParams->getParam("matViewProj", mPickingMaterial.mViewProj);
+			vertParams->getParam("matViewProj", mPickingMaterial.viewProj);
 		}
 
 		{
-			SPtr<MaterialCore> mat = mAlphaPickingMaterial.mat;
-			SPtr<PassParametersCore> passParams = mat->getPassParameters(0);
-			SPtr<GpuParamsCore> vertParams = passParams->mVertParams;
-
-			vertParams->getParam("matViewProj", mAlphaPickingMaterial.mViewProj);
+			mAlphaPickingMaterial.params = mAlphaPickingMaterial.mat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams = mAlphaPickingMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
+			SPtr<GpuParamsCore> fragParams = mAlphaPickingMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			mAlphaPickingMaterial.mFragParams = passParams->mFragParams;
-			mAlphaPickingMaterial.mFragParams->getTextureParam("mainTexture", mAlphaPickingMaterial.mTexture);
+			vertParams->getParam("matViewProj", mAlphaPickingMaterial.viewProj);
+			fragParams->getTextureParam("mainTexture", mAlphaPickingMaterial.texture);
 
 			GpuParamFloatCore alphaCutoffParam;
-			mAlphaPickingMaterial.mFragParams->getParam("alphaCutoff", alphaCutoffParam);
+			fragParams->getParam("alphaCutoff", alphaCutoffParam);
 			alphaCutoffParam.set(PICKING_ALPHA_CUTOFF);
 		}
 
 		{
-			SPtr<MaterialCore> mat = mTextMaterial.mat;
+			mTextMaterial.params = mTextMaterial.mat->createParamsSet();
 
-			SPtr<PassParametersCore> passParams = mat->getPassParameters(0);
-			SPtr<GpuParamsCore> vertParams = passParams->mVertParams;
-			SPtr<GpuParamsCore> fragParams = passParams->mFragParams;
+			SPtr<GpuParamsCore> vertParams = mTextMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
+			SPtr<GpuParamsCore> fragParams = mTextMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-			vertParams->getParam("matViewProj", mTextMaterial.mViewProj);
-			fragParams->getTextureParam("mainTexture", mTextMaterial.mTexture);
+			vertParams->getParam("matViewProj", mTextMaterial.viewProj);
+			fragParams->getTextureParam("mainTexture", mTextMaterial.texture);
 		}
 	}
 
@@ -1107,31 +1102,37 @@ namespace BansheeEngine
 		switch (material)
 		{
 		case GizmoManager::GizmoMaterial::Solid:
-			mSolidMaterial.mViewProj.set(viewProjMat);
-			mSolidMaterial.mViewDir.set((Vector4)viewDir);
+			mSolidMaterial.viewProj.set(viewProjMat);
+			mSolidMaterial.viewDir.set((Vector4)viewDir);
 			gRendererUtility().setPass(mSolidMaterial.mat);
+			gRendererUtility().setPassParams(mSolidMaterial.params);
 			break;
 		case GizmoManager::GizmoMaterial::Wire:
-			mWireMaterial.mViewProj.set(viewProjMat);
+			mWireMaterial.viewProj.set(viewProjMat);
 			gRendererUtility().setPass(mWireMaterial.mat);
+			gRendererUtility().setPassParams(mWireMaterial.params);
 			break;
 		case GizmoManager::GizmoMaterial::Line:
-			mLineMaterial.mViewProj.set(viewProjMat);
+			mLineMaterial.viewProj.set(viewProjMat);
 			gRendererUtility().setPass(mLineMaterial.mat);
+			gRendererUtility().setPassParams(mLineMaterial.params);
 			break;
 		case GizmoManager::GizmoMaterial::Picking:
-			mPickingMaterial.mViewProj.set(viewProjMat);
+			mPickingMaterial.viewProj.set(viewProjMat);
 			gRendererUtility().setPass(mPickingMaterial.mat);
+			gRendererUtility().setPassParams(mPickingMaterial.params);
 			break;
 		case GizmoManager::GizmoMaterial::PickingAlpha:
-			mAlphaPickingMaterial.mViewProj.set(viewProjMat);
-			mAlphaPickingMaterial.mTexture.set(texture);
+			mAlphaPickingMaterial.viewProj.set(viewProjMat);
+			mAlphaPickingMaterial.texture.set(texture);
 			gRendererUtility().setPass(mAlphaPickingMaterial.mat);
+			gRendererUtility().setPassParams(mAlphaPickingMaterial.params);
 			break;
 		case GizmoManager::GizmoMaterial::Text:
-			mTextMaterial.mViewProj.set(viewProjMat);
-			mTextMaterial.mTexture.set(texture);
+			mTextMaterial.viewProj.set(viewProjMat);
+			mTextMaterial.texture.set(texture);
 			gRendererUtility().setPass(mTextMaterial.mat);
+			gRendererUtility().setPassParams(mTextMaterial.params);
 			break;
 		}
 		gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
@@ -1172,18 +1173,21 @@ namespace BansheeEngine
 
 		if (!usePickingMaterial)
 		{
-			mIconMaterial.mViewProj[0].set(projMat);
-			mIconMaterial.mViewProj[1].set(projMat);
+			mIconMaterial.viewProj[0].set(projMat);
+			mIconMaterial.viewProj[1].set(projMat);
 
 			for (UINT32 passIdx = 0; passIdx < 2; passIdx++)
 			{
 				gRendererUtility().setPass(mIconMaterial.mat, passIdx);
+				gRendererUtility().setPassParams(mIconMaterial.params, passIdx);
 
 				UINT32 curIndexOffset = mesh->getIndexOffset();
 				for (auto curRenderData : *renderData)
 				{
-					mIconMaterial.mTexture[passIdx].set(curRenderData.texture);
-					gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, mIconMaterial.mFragParams[passIdx]);
+					mIconMaterial.texture[passIdx].set(curRenderData.texture);
+
+					SPtr<GpuParamsCore> fragParams = mIconMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM, passIdx);
+					gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, fragParams);
 
 					rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 					curIndexOffset += curRenderData.count * 6;
@@ -1192,15 +1196,18 @@ namespace BansheeEngine
 		}
 		else
 		{
-			mAlphaPickingMaterial.mViewProj.set(projMat);
+			mAlphaPickingMaterial.viewProj.set(projMat);
 
-			gRendererUtility().setPass(mAlphaPickingMaterial.mat, 0);
+			gRendererUtility().setPass(mAlphaPickingMaterial.mat);
+			gRendererUtility().setPassParams(mAlphaPickingMaterial.params);
 
 			UINT32 curIndexOffset = 0;
 			for (auto curRenderData : *renderData)
 			{
-				mAlphaPickingMaterial.mTexture.set(curRenderData.texture);
-				gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, mAlphaPickingMaterial.mFragParams);
+				mAlphaPickingMaterial.texture.set(curRenderData.texture);
+
+				SPtr<GpuParamsCore> fragParams = mAlphaPickingMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
+				gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, fragParams);
 
 				rapi.drawIndexed(curIndexOffset, curRenderData.count * 6, mesh->getVertexOffset(), curRenderData.count * 4);
 				curIndexOffset += curRenderData.count * 6;

+ 20 - 6
Source/BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -3,6 +3,7 @@
 #include "BsHandleDrawManager.h"
 #include "BsDrawHelper.h"
 #include "BsMaterial.h"
+#include "BsGpuParamsSet.h"
 #include "BsBuiltinEditorResources.h"
 #include "BsCoreThread.h"
 #include "BsRendererManager.h"
@@ -251,24 +252,27 @@ namespace BansheeEngine
 	{
 		{
 			mLineMaterial.mat = lineMat;
-			SPtr<GpuParamsCore> vertParams = lineMat->getPassParameters(0)->mVertParams;
+			mLineMaterial.params = lineMat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams = mLineMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
 
 			vertParams->getParam("matViewProj", mLineMaterial.viewProj);
 		}
 
 		{
 			mSolidMaterial.mat = solidMat;
-			SPtr<GpuParamsCore> vertParams = solidMat->getPassParameters(0)->mVertParams;
-			SPtr<GpuParamsCore> fragParams = solidMat->getPassParameters(0)->mFragParams;
+			mSolidMaterial.params = solidMat->createParamsSet();
+			SPtr<GpuParamsCore> vertParams = mSolidMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
+			SPtr<GpuParamsCore> fragParams = mSolidMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
 			vertParams->getParam("matViewProj", mSolidMaterial.viewProj);
 			fragParams->getParam("viewDir", mSolidMaterial.viewDir);
 		}
 		{
 			mTextMaterial.mat = textMat;
+			mTextMaterial.params = textMat->createParamsSet();
 
-			SPtr<GpuParamsCore> vertParams = textMat->getPassParameters(0)->mVertParams;
-			SPtr<GpuParamsCore> fragParams = textMat->getPassParameters(0)->mFragParams;
+			SPtr<GpuParamsCore> vertParams = mTextMaterial.params->getGpuParams(GPT_VERTEX_PROGRAM);
+			SPtr<GpuParamsCore> fragParams = mTextMaterial.params->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
 			vertParams->getParam("matViewProj", mTextMaterial.viewProj);
 			fragParams->getTextureParam("mainTexture", mTextMaterial.texture);
@@ -333,13 +337,20 @@ namespace BansheeEngine
 			currentType = meshes[0].type;
 
 			if (currentType == MeshType::Solid)
+			{
 				gRendererUtility().setPass(mSolidMaterial.mat);
-			else if(currentType == MeshType::Line)
+				gRendererUtility().setPassParams(mSolidMaterial.params);
+			}
+			else if (currentType == MeshType::Line)
+			{
 				gRendererUtility().setPass(mLineMaterial.mat);
+				gRendererUtility().setPassParams(mLineMaterial.params);
+			}
 			else
 			{
 				mTextMaterial.texture.set(meshes[0].texture);
 				gRendererUtility().setPass(mTextMaterial.mat);
+				gRendererUtility().setPassParams(mTextMaterial.params);
 			}
 		}
 
@@ -350,15 +361,18 @@ namespace BansheeEngine
 				if (meshData.type == MeshType::Solid)
 				{
 					gRendererUtility().setPass(mSolidMaterial.mat);
+					gRendererUtility().setPassParams(mSolidMaterial.params);
 				}
 				else if (meshData.type == MeshType::Line)
 				{
 					gRendererUtility().setPass(mLineMaterial.mat);
+					gRendererUtility().setPassParams(mLineMaterial.params);
 				}
 				else
 				{
 					mTextMaterial.texture.set(meshData.texture);
 					gRendererUtility().setPass(mTextMaterial.mat);
+					gRendererUtility().setPassParams(mTextMaterial.params);
 				}
 
 				currentType = meshData.type;

+ 4 - 0
Source/BansheeEditor/Source/BsSceneGrid.cpp

@@ -197,6 +197,7 @@ namespace BansheeEngine
 	{
 		mCamera = camera;
 		mGridMaterial = material;
+		mMaterialParams = material->createParamsSet();
 
 		mViewProjParam = mGridMaterial->getParamMat4("matViewProj");
 		mWorldCameraPosParam = mGridMaterial->getParamVec4("worldCameraPos");
@@ -246,7 +247,10 @@ namespace BansheeEngine
 			mGridFadeOutEndParam.set(1500.0f);
 		}
 
+		mGridMaterial->updateParamsSet(mMaterialParams);
+
 		gRendererUtility().setPass(mGridMaterial, 0);
+		gRendererUtility().setPassParams(mMaterialParams);
 		gRendererUtility().draw(mGridMesh, mGridMesh->getProperties().getSubMesh(0));
 	}
 }

+ 17 - 21
Source/BansheeEditor/Source/BsScenePicking.cpp

@@ -15,12 +15,11 @@
 #include "BsRenderAPI.h"
 #include "BsMaterial.h"
 #include "BsPass.h"
-#include "BsBlendState.h"
-#include "BsDepthStencilState.h"
 #include "BsRasterizerState.h"
 #include "BsRenderTarget.h"
 #include "BsPixelData.h"
 #include "BsGpuParams.h"
+#include "BsGpuParamsSet.h"
 #include "BsBuiltinEditorResources.h"
 #include "BsShader.h"
 #include "BsCoreRenderer.h"
@@ -224,28 +223,25 @@ namespace BansheeEngine
 			MaterialData& md = mMaterialData[i];
 
 			{
-				SPtr<PassParametersCore> passParams = md.mMatPickingCore->getPassParameters(0);
+				md.mPickingParams = md.mMatPickingCore->createParamsSet();
+				SPtr<GpuParamsCore> vertParams = md.mPickingParams->getGpuParams(GPT_VERTEX_PROGRAM);
+				SPtr<GpuParamsCore> fragParams = md.mPickingParams->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-				md.mParamPickingVertParams = passParams->mVertParams;
-				md.mParamPickingVertParams->getParam("matWorldViewProj", md.mParamPickingWVP);
-
-				md.mParamPickingFragParams = passParams->mFragParams;
-				md.mParamPickingFragParams->getParam("colorIndex", md.mParamPickingColor);
+				vertParams->getParam("matWorldViewProj", md.mParamPickingWVP);
+				fragParams->getParam("colorIndex", md.mParamPickingColor);
 			}
 
 			{
-				SPtr<PassParametersCore> passParams = md.mMatPickingAlphaCore->getPassParameters(0);
-
-				md.mParamPickingAlphaVertParams = passParams->mVertParams;
-				md.mParamPickingAlphaVertParams->getParam("matWorldViewProj", md.mParamPickingAlphaWVP);
+				md.mPickingAlphaParams = md.mMatPickingAlphaCore->createParamsSet();
+				SPtr<GpuParamsCore> vertParams = md.mPickingAlphaParams->getGpuParams(GPT_VERTEX_PROGRAM);
+				SPtr<GpuParamsCore> fragParams = md.mPickingAlphaParams->getGpuParams(GPT_FRAGMENT_PROGRAM);
 
-				md.mParamPickingAlphaFragParams = passParams->mFragParams;
-
-				md.mParamPickingAlphaFragParams->getParam("colorIndex", md.mParamPickingAlphaColor);
-				md.mParamPickingAlphaFragParams->getTextureParam("mainTexture", md.mParamPickingAlphaTexture);
+				vertParams->getParam("matWorldViewProj", md.mParamPickingAlphaWVP);
+				fragParams->getParam("colorIndex", md.mParamPickingAlphaColor);
+				fragParams->getTextureParam("mainTexture", md.mParamPickingAlphaTexture);
 
 				GpuParamFloatCore alphaCutoffParam;
-				md.mParamPickingAlphaFragParams->getParam("alphaCutoff", alphaCutoffParam);
+				fragParams->getParam("alphaCutoff", alphaCutoffParam);
 				alphaCutoffParam.set(ALPHA_CUTOFF);
 			}
 		}
@@ -268,6 +264,8 @@ namespace BansheeEngine
 		rs.setScissorRect(position.x, position.y, position.x + area.x, position.y + area.y);
 
 		gRendererUtility().setPass(mMaterialData[0].mMatPickingCore, 0);
+		gRendererUtility().setPassParams(mMaterialData[0].mPickingParams, 0);
+
 		bool activeMaterialIsAlpha = false;
 		CullingMode activeMaterialCull = (CullingMode)0;
 
@@ -293,16 +291,14 @@ namespace BansheeEngine
 				md.mParamPickingAlphaColor.set(color);
 				md.mParamPickingAlphaTexture.set(renderable.mainTexture->getCore());
 
-				gRendererUtility().setGpuParams(GPT_VERTEX_PROGRAM, md.mParamPickingAlphaVertParams);
-				gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, md.mParamPickingAlphaFragParams);
+				gRendererUtility().setPassParams(md.mPickingAlphaParams);
 			}
 			else
 			{
 				md.mParamPickingWVP.set(renderable.wvpTransform);
 				md.mParamPickingColor.set(color);
 
-				gRendererUtility().setGpuParams(GPT_VERTEX_PROGRAM, md.mParamPickingVertParams);
-				gRendererUtility().setGpuParams(GPT_FRAGMENT_PROGRAM, md.mParamPickingFragParams);
+				gRendererUtility().setPassParams(md.mPickingParams);
 			}
 
 			UINT32 numSubmeshes = renderable.mesh->getProperties().getNumSubMeshes();

+ 5 - 2
Source/BansheeEditor/Source/BsSelectionRenderer.cpp

@@ -8,6 +8,7 @@
 #include "BsBuiltinEditorResources.h"
 #include "BsMaterial.h"
 #include "BsGpuParams.h"
+#include "BsGpuParamsSet.h"
 #include "BsRenderAPI.h"
 #include "BsCoreRenderer.h"
 #include "BsRendererManager.h"
@@ -97,11 +98,12 @@ namespace BansheeEngine
 		THROW_IF_NOT_CORE_THREAD;
 
 		mMaterial = mat;
+		mParams = mat->createParamsSet();
 
-		SPtr<GpuParamsCore> vertParams = mat->getPassParameters(0)->mVertParams;
+		SPtr<GpuParamsCore> vertParams = mParams->getGpuParams(GPT_VERTEX_PROGRAM);
 		vertParams->getParam("matWorldViewProj", mMatWorldViewProj);
 
-		SPtr<GpuParamsCore> fragParams = mat->getPassParameters(0)->mFragParams;
+		SPtr<GpuParamsCore> fragParams = mParams->getGpuParams(GPT_FRAGMENT_PROGRAM);
 		fragParams->getParam("selColor", mColor);
 	}
 
@@ -138,6 +140,7 @@ namespace BansheeEngine
 			mColor.set(SELECTION_COLOR);
 
 			gRendererUtility().setPass(mMaterial, 0);
+			gRendererUtility().setPassParams(mParams, 0);
 
 			UINT32 numSubmeshes = objData.mesh->getProperties().getNumSubMeshes();
 

+ 5 - 0
Source/BansheeEngine/Include/BsRendererMaterial.h

@@ -45,10 +45,14 @@ namespace BansheeEngine
 		/**	Returns the internal material. */
 		SPtr<MaterialCore> getMaterial() const { return mMaterial; }
 
+		/** Returns the internal parameter set containing GPU bindable parameters. */
+		SPtr<GpuParamsSetCore> getParamsSet() const { return mParamsSet; }
+
 	protected:
 		friend class RendererMaterialManager;
 
 		SPtr<MaterialCore> mMaterial;
+		SPtr<GpuParamsSetCore> mParamsSet;
 	};
 
 	/**	Helper class to initialize all renderer materials as soon as the library is loaded. */
@@ -74,6 +78,7 @@ namespace BansheeEngine
 		{
 			mInitOnStart.instantiate();
 			mMaterial = MaterialCore::create(mMetaData.shader);
+			mParamsSet = mMaterial->createParamsSet();
 		}
 
 		virtual ~RendererMaterial() { }

+ 5 - 11
Source/BansheeEngine/Include/BsRendererUtility.h

@@ -34,36 +34,30 @@ namespace BansheeEngine
 		 *
 		 * @param[in]	material		Material containing the pass.
 		 * @param[in]	passIdx			Index of the pass in the material.
-		 * @param[in]	bindParameters	If true, any GPU program parameters will be bound as well. Otherwise the caller
-		 *								is required to bind them manually via setPassParams() or setGpuParams() before
-		 *								using the pass.
 		 *
 		 * @note	Core thread.
 		 */
-		void setPass(const SPtr<MaterialCore>& material, UINT32 passIdx = 0, bool bindParameters = true);
+		void setPass(const SPtr<MaterialCore>& material, UINT32 passIdx = 0);
 
 		/**
 		 * Activates the specified material pass for compute. Any further dispatch calls will be executed using this pass.
 		 *
 		 * @param[in]	material		Material containing the pass.
 		 * @param[in]	passIdx			Index of the pass in the material.
-		 * @param[in]	bindParameters	If true, any GPU program parameters will be bound as well. Otherwise the caller
-		 *								is required to bind them manually via setPassParams() or setGpuParams() before
-		 *								using the pass.
 		 *
 		 * @note	Core thread.
 		 */
-		void setComputePass(const SPtr<MaterialCore>& material, UINT32 passIdx = 0, bool bindParameters = true);
+		void setComputePass(const SPtr<MaterialCore>& material, UINT32 passIdx = 0);
 
 		/**
 		 * Sets parameters (textures, samplers, buffers) for the currently active pass.
 		 *
-		 * @param[in]	material	Material whose pass' parameters to bind.
-		 * @param[in]	passIdx		Index of the pass in the material.
+		 * @param[in]	params		Object containing the parameters.
+		 * @param[in]	passIdx		Pass for which to set the parameters.
 		 *					
 		 * @note	Core thread.
 		 */
-		void setPassParams(const SPtr<MaterialCore>& material, UINT32 passIdx = 0);
+		void setPassParams(const SPtr<GpuParamsSetCore>& params, UINT32 passIdx = 0);
 
 		/**
 		 * Sets parameters (textures, samplers, buffers) for the provided GPU program type.

+ 27 - 60
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -5,6 +5,7 @@
 #include "BsMesh.h"
 #include "BsVertexDataDesc.h"
 #include "BsMaterial.h"
+#include "BsGpuParamsSet.h"
 #include "BsPass.h"
 #include "BsBlendState.h"
 #include "BsDepthStencilState.h"
@@ -116,44 +117,27 @@ namespace BansheeEngine
 
 	}
 
-	void RendererUtility::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, bool bindParameters)
+	void RendererUtility::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx)
 	{
 		RenderAPICore& rapi = RenderAPICore::instance();
 
 		SPtr<PassCore> pass = material->getPass(passIdx);
-		SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
 
 		struct StageData
 		{
 			GpuProgramType type;
 			bool enable;
-			SPtr<GpuParamsCore> params;
 			SPtr<GpuProgramCore> program;
 		};
 
 		const UINT32 numStages = 5;
 		StageData stages[numStages] =
 		{
-			{
-				GPT_VERTEX_PROGRAM, pass->hasVertexProgram(),
-				passParams->mVertParams, pass->getVertexProgram()
-			},
-			{
-				GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(),
-				passParams->mFragParams, pass->getFragmentProgram()
-			},
-			{
-				GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(),
-				passParams->mGeomParams, pass->getGeometryProgram()
-			},
-			{
-				GPT_HULL_PROGRAM, pass->hasHullProgram(),
-				passParams->mHullParams, pass->getHullProgram()
-			},
-			{
-				GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(),
-				passParams->mDomainParams, pass->getDomainProgram()
-			}
+			{ GPT_VERTEX_PROGRAM, pass->hasVertexProgram(), pass->getVertexProgram() },
+			{ GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(), pass->getFragmentProgram() },
+			{ GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(), pass->getGeometryProgram() },
+			{ GPT_HULL_PROGRAM, pass->hasHullProgram(), pass->getHullProgram() },
+			{ GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(), pass->getDomainProgram() }
 		};
 
 		for (UINT32 i = 0; i < numStages; i++)
@@ -161,13 +145,7 @@ namespace BansheeEngine
 			const StageData& stage = stages[i];
 
 			if (stage.enable)
-			{
 				rapi.bindGpuProgram(stage.program);
-
-				if(bindParameters)
-					setGpuParams(stage.type, stage.params);
-
-			}
 			else
 				rapi.unbindGpuProgram(stage.type);
 		}
@@ -189,54 +167,37 @@ namespace BansheeEngine
 			rapi.setRasterizerState(RasterizerStateCore::getDefault());
 	}
 
-	void RendererUtility::setComputePass(const SPtr<MaterialCore>& material, UINT32 passIdx, bool bindParameters)
+	void RendererUtility::setComputePass(const SPtr<MaterialCore>& material, UINT32 passIdx)
 	{
 		RenderAPICore& rapi = RenderAPICore::instance();
-
 		SPtr<PassCore> pass = material->getPass(passIdx);
-		SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
 
 		if(pass->hasComputeProgram())
-		{
 			rapi.bindGpuProgram(pass->getComputeProgram());
-
-			if (bindParameters)
-				setGpuParams(GPT_COMPUTE_PROGRAM, passParams->mComputeParams);
-		}
 		else
 			rapi.unbindGpuProgram(GPT_COMPUTE_PROGRAM);
 	}
 
-	void RendererUtility::setPassParams(const SPtr<MaterialCore>& material, UINT32 passIdx)
+	void RendererUtility::setPassParams(const SPtr<GpuParamsSetCore>& params, UINT32 passIdx)
 	{
-		const SPtr<PassParametersCore>& passParams = material->getPassParameters(passIdx);
-
-		struct StageData
-		{
-			GpuProgramType type;
-			SPtr<GpuParamsCore> params;
-		};
-
 		const UINT32 numStages = 6;
-		StageData stages[numStages] =
+		GpuProgramType stages[numStages] =
 		{
-			{ GPT_VERTEX_PROGRAM, passParams->mVertParams },
-			{ GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
-			{ GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
-			{ GPT_HULL_PROGRAM, passParams->mHullParams },
-			{ GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
-			{ GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
+			{ GPT_VERTEX_PROGRAM },
+			{ GPT_FRAGMENT_PROGRAM },
+			{ GPT_GEOMETRY_PROGRAM },
+			{ GPT_HULL_PROGRAM },
+			{ GPT_DOMAIN_PROGRAM },
+			{ GPT_COMPUTE_PROGRAM }
 		};
 
 		for (UINT32 i = 0; i < numStages; i++)
 		{
-			const StageData& stage = stages[i];
-
-			SPtr<GpuParamsCore> params = stage.params;
-			if (params == nullptr)
+			SPtr<GpuParamsCore> gpuParams = params->getGpuParams(stages[i], passIdx);
+			if (gpuParams == nullptr)
 				continue;
 
-			setGpuParams(stage.type, params);
+			setGpuParams(stages[i], gpuParams);
 		}
 	}
 
@@ -340,19 +301,22 @@ namespace BansheeEngine
 	{
 		auto& texProps = texture->getProperties();
 		SPtr<MaterialCore> mat;
+		SPtr<GpuParamsSetCore> params;
 		if (texProps.getMultisampleCount() > 1)
 		{
 			mat = mResolveMat->getMaterial();
+			params = mResolveMat->getParamsSet();
 			mResolveMat->setParameters(texture);
 		}
 		else
 		{
 			mat = mBlitMat->getMaterial();
+			params = mBlitMat->getParamsSet();
 			mBlitMat->setParameters(texture);
 		}
 
-		setPass(mat, 0);
-		setPassParams(mat);
+		setPass(mat);
+		setPassParams(params);
 
 		Rect2 fArea((float)area.x, (float)area.y, (float)area.width, (float)area.height);
 		if(area.width == 0 || area.height == 0)
@@ -440,6 +404,7 @@ namespace BansheeEngine
 	void BlitMat::setParameters(const SPtr<TextureCore>& source)
 	{
 		mSource.set(source);
+		mMaterial->updateParamsSet(mParamsSet);
 	}
 
 	ResolveMat::ResolveMat()
@@ -459,5 +424,7 @@ namespace BansheeEngine
 
 		UINT32 sampleCount = source->getProperties().getMultisampleCount();
 		mNumSamples.set(sampleCount);
+
+		mMaterial->updateParamsSet(mParamsSet);
 	}
 }

+ 2 - 1
Source/RenderBeast/Include/BsLightRendering.h

@@ -25,7 +25,7 @@ namespace BansheeEngine
 	class LightRenderingParams
 	{
 	public:
-		LightRenderingParams(const SPtr<MaterialCore>& lightMaterial);
+		LightRenderingParams(const SPtr<MaterialCore>& lightMaterial, const SPtr<GpuParamsSetCore>& paramsSet);
 
 		/** Updates parameters that are common for all lights. */
 		void setStaticParameters(const SPtr<RenderTargets>& gbuffer,
@@ -38,6 +38,7 @@ namespace BansheeEngine
 		const SPtr<GpuParamBlockBufferCore>& getBuffer() const;
 	private:
 		SPtr<MaterialCore> mMaterial;
+		SPtr<GpuParamsSetCore> mParamsSet;
 
 		MaterialParamTextureCore mGBufferA;
 		MaterialParamTextureCore mGBufferB;

+ 11 - 2
Source/RenderBeast/Include/BsRenderBeast.h

@@ -57,6 +57,13 @@ namespace BansheeEngine
 			LightCore* internal;
 		};
 
+		/** Renderer information for a single material. */
+		struct RendererMaterial
+		{
+			Vector<SPtr<GpuParamsSetCore>> params;
+			UINT32 matVersion;
+		};
+
 	public:
 		RenderBeast();
 		~RenderBeast() { }
@@ -185,13 +192,15 @@ namespace BansheeEngine
 		/**
 		 * Sets parameters (textures, samplers, buffers) for the currently active pass.
 		 *
-		 * @param[in]	passParams			Structure containing parameters for all stages of the pass.
+		 * @param[in]	paramsSet			Structure containing parameters for a material.
 		 * @param[in]	samplerOverrides	Optional samplers to use instead of the those in the pass parameters. Number of
 		 *									samplers must match number in pass parameters.
+		 * @param[in]	passIdx				Index of the pass whose parameters to bind.
 		 *
 		 * @note	Core thread.
 		 */
-		static void setPassParams(const SPtr<PassParametersCore>& passParams, const PassSamplerOverrides* samplerOverrides);
+		static void setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const PassSamplerOverrides* samplerOverrides, 
+			UINT32 passIdx);
 
 		// Core thread only fields
 		Vector<RendererRenderTarget> mRenderTargets;

+ 3 - 0
Source/RenderBeast/Include/BsRendererObject.h

@@ -27,6 +27,9 @@ namespace BansheeEngine
 		 */
 		MaterialSamplerOverrides* samplerOverrides;
 
+		/** All GPU parameters from the material used by the renderable. */
+		SPtr<GpuParamsSetCore> params;
+
 		/**	Identifier of the owner renderable. */
 		UINT32 renderableId;
 

+ 3 - 3
Source/RenderBeast/Include/BsSamplerOverrides.h

@@ -37,10 +37,10 @@ namespace BansheeEngine
 	{
 	public:
 		/**
-		 * Generates a set of sampler overrides for the specified material. Overrides are generates according to the
-		 * provided render options. 
+		 * Generates a set of sampler overrides for the specified set of GPU program parameters. Overrides are generates
+		 * according to the provided render options. 
 		 */
-		static MaterialSamplerOverrides* generateSamplerOverrides(const SPtr<MaterialCore>& material, 
+		static MaterialSamplerOverrides* generateSamplerOverrides(const SPtr<GpuParamsSetCore>& paramsSet,
 			const SPtr<RenderBeastOptions>& options);
 
 		/**	Destroys sampler overrides previously generated with generateSamplerOverrides(). */

+ 13 - 11
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -6,13 +6,14 @@
 #include "BsRenderBeast.h"
 #include "BsRenderTargets.h"
 #include "BsGpuParams.h"
+#include "BsGpuParamsSet.h"
 #include "BsLight.h"
 #include "BsRendererUtility.h"
 
 namespace BansheeEngine
 {
-	LightRenderingParams::LightRenderingParams(const SPtr<MaterialCore>& material)
-		:mMaterial(material)
+	LightRenderingParams::LightRenderingParams(const SPtr<MaterialCore>& material, const SPtr<GpuParamsSetCore>& paramsSet)
+		:mMaterial(material), mParamsSet(paramsSet)
 	{
 		auto& texParams = material->getShader()->getTextureParams();
 		for (auto& entry : texParams)
@@ -33,10 +34,11 @@ namespace BansheeEngine
 		mGBufferB.set(gbuffer->getTextureB());
 		mGBufferDepth.set(gbuffer->getTextureDepth());
 
-		mMaterial->setParamBlockBuffer("PerLight", getBuffer());
-		mMaterial->setParamBlockBuffer("PerCamera", perCamera);
+		mParamsSet->setParamBlockBuffer("PerLight", getBuffer());
+		mParamsSet->setParamBlockBuffer("PerCamera", perCamera);
 
-		gRendererUtility().setPassParams(mMaterial);
+		mMaterial->updateParamsSet(mParamsSet);
+		gRendererUtility().setPassParams(mParamsSet);
 	}
 
 	void LightRenderingParams::setParameters(const LightCore* light)
@@ -104,7 +106,7 @@ namespace BansheeEngine
 	}
 	
 	DirectionalLightMat::DirectionalLightMat()
-		:mParams(mMaterial)
+		:mParams(mMaterial, mParamsSet)
 	{
 		
 	}
@@ -117,7 +119,7 @@ namespace BansheeEngine
 	void DirectionalLightMat::bind(const SPtr<RenderTargets>& gbuffer,
 		const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
-		RendererUtility::instance().setPass(mMaterial, 0, false);
+		RendererUtility::instance().setPass(mMaterial, 0);
 		mParams.setStaticParameters(gbuffer, perCamera);
 	}
 
@@ -127,7 +129,7 @@ namespace BansheeEngine
 	}
 
 	PointLightInMat::PointLightInMat()
-		:mParams(mMaterial)
+		:mParams(mMaterial, mParamsSet)
 	{
 
 	}
@@ -140,7 +142,7 @@ namespace BansheeEngine
 	void PointLightInMat::bind(const SPtr<RenderTargets>& gbuffer, 
 		const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
-		RendererUtility::instance().setPass(mMaterial, 0, false);
+		RendererUtility::instance().setPass(mMaterial, 0);
 		mParams.setStaticParameters(gbuffer, perCamera);
 	}
 
@@ -150,7 +152,7 @@ namespace BansheeEngine
 	}
 
 	PointLightOutMat::PointLightOutMat()
-		:mParams(mMaterial)
+		:mParams(mMaterial, mParamsSet)
 	{
 		
 	}
@@ -163,7 +165,7 @@ namespace BansheeEngine
 	void PointLightOutMat::bind(const SPtr<RenderTargets>& gbuffer,
 		const SPtr<GpuParamBlockBufferCore>& perCamera)
 	{
-		RendererUtility::instance().setPass(mMaterial, 0, false);
+		RendererUtility::instance().setPass(mMaterial, 0);
 		mParams.setStaticParameters(gbuffer, perCamera);
 	}
 

+ 4 - 3
Source/RenderBeast/Source/BsObjectRendering.cpp

@@ -8,6 +8,7 @@
 #include "BsMesh.h"
 #include "BsSkeleton.h"
 #include "BsGpuBuffer.h"
+#include "BsGpuParamsSet.h"
 
 namespace BansheeEngine
 {
@@ -49,9 +50,9 @@ namespace BansheeEngine
 		
 		// Note: Perhaps perform buffer validation to ensure expected buffer has the same size and layout as the provided
 		// buffer, and show a warning otherwise. But this is perhaps better handled on a higher level.
-		element.material->setParamBlockBuffer(perFrameBlockName, mPerFrameParams.getBuffer());
-		element.material->setParamBlockBuffer(perCameraBlockName, mPerCameraParams.getBuffer());
-		element.material->setParamBlockBuffer(perObjectBlockName, mPerObjectParams.getBuffer());
+		element.params->setParamBlockBuffer(perFrameBlockName, mPerFrameParams.getBuffer());
+		element.params->setParamBlockBuffer(perCameraBlockName, mPerCameraParams.getBuffer());
+		element.params->setParamBlockBuffer(perObjectBlockName, mPerObjectParams.getBuffer());
 
 		if (!boneMatricesParamName.empty())
 		{

+ 20 - 12
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -6,12 +6,13 @@
 #include "BsRendererUtility.h"
 #include "BsTextureManager.h"
 #include "BsCamera.h"
+#include "BsGpuParamsSet.h"
 
 namespace BansheeEngine
 {
 	DownsampleMat::DownsampleMat()
 	{
-		mMaterial->setParamBlockBuffer("Input", mParams.getBuffer());
+		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
 		mInputTexture = mMaterial->getParamTexture("gInputTex");
 		mInvTexSize = mMaterial->getParamVec2("gInvTexSize");
@@ -47,7 +48,8 @@ namespace BansheeEngine
 		RenderAPICore& rapi = RenderAPICore::instance();
 		rapi.setRenderTarget(ppInfo.downsampledSceneTex->renderTexture, true);
 
-		gRendererUtility().setPass(mMaterial, 0);
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
 		gRendererUtility().drawScreenQuad();
 
 		rapi.setRenderTarget(nullptr);
@@ -63,7 +65,7 @@ namespace BansheeEngine
 
 	EyeAdaptHistogramMat::EyeAdaptHistogramMat()
 	{
-		mMaterial->setParamBlockBuffer("Input", mParams.getBuffer());
+		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
 		mSceneColor = mMaterial->getParamTexture("gSceneColorTex");
 		mOutputTex = mMaterial->getParamLoadStoreTexture("gOutputTex");
@@ -105,6 +107,7 @@ namespace BansheeEngine
 
 		RenderAPICore& rapi = RenderAPICore::instance();
 		gRendererUtility().setComputePass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
 		rapi.dispatchCompute(threadGroupCount.x, threadGroupCount.y);
 
 		// Note: This is ugly, add a better way to clear load/store textures?
@@ -147,7 +150,7 @@ namespace BansheeEngine
 
 	EyeAdaptHistogramReduceMat::EyeAdaptHistogramReduceMat()
 	{
-		mMaterial->setParamBlockBuffer("Input", mParams.getBuffer());
+		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
 		mHistogramTex = mMaterial->getParamTexture("gHistogramTex");
 		mEyeAdaptationTex = mMaterial->getParamTexture("gEyeAdaptationTex");
@@ -188,7 +191,9 @@ namespace BansheeEngine
 		RenderAPICore& rapi = RenderAPICore::instance();
 		rapi.setRenderTarget(ppInfo.histogramReduceTex->renderTexture, true);
 
-		gRendererUtility().setPass(mMaterial, 0);
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
+
 		Rect2 drawUV(0.0f, 0.0f, (float)EyeAdaptHistogramMat::HISTOGRAM_NUM_TEXELS, 2.0f);
 		gRendererUtility().drawScreenQuad(drawUV);
 
@@ -205,7 +210,7 @@ namespace BansheeEngine
 
 	EyeAdaptationMat::EyeAdaptationMat()
 	{
-		mMaterial->setParamBlockBuffer("Input", mParams.getBuffer());
+		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
 		mReducedHistogramTex = mMaterial->getParamTexture("gHistogramTex");
 	}
@@ -263,7 +268,8 @@ namespace BansheeEngine
 		RenderAPICore& rapi = RenderAPICore::instance();
 		rapi.setRenderTarget(eyeAdaptationRT->renderTexture, true);
 
-		gRendererUtility().setPass(mMaterial, 0);
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
 		gRendererUtility().drawScreenQuad();
 
 		rapi.setRenderTarget(nullptr);
@@ -271,8 +277,8 @@ namespace BansheeEngine
 
 	CreateTonemapLUTMat::CreateTonemapLUTMat()
 	{
-		mMaterial->setParamBlockBuffer("Input", mParams.getBuffer());
-		mMaterial->setParamBlockBuffer("WhiteBalanceInput", mWhiteBalanceParams.getBuffer());
+		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
+		mParamsSet->setParamBlockBuffer("WhiteBalanceInput", mWhiteBalanceParams.getBuffer());
 	}
 
 	void CreateTonemapLUTMat::_initDefines(ShaderDefines& defines)
@@ -323,7 +329,8 @@ namespace BansheeEngine
 		RenderAPICore& rapi = RenderAPICore::instance();
 		rapi.setRenderTarget(ppInfo.colorLUT->renderTexture);
 
-		gRendererUtility().setPass(mMaterial, 0);
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
 		gRendererUtility().drawScreenQuad(LUT_SIZE);
 	}
 
@@ -335,7 +342,7 @@ namespace BansheeEngine
 	template<bool GammaOnly, bool AutoExposure>
 	TonemappingMat<GammaOnly, AutoExposure>::TonemappingMat()
 	{
-		mMaterial->setParamBlockBuffer("Input", mParams.getBuffer());
+		mParamsSet->setParamBlockBuffer("Input", mParams.getBuffer());
 
 		mInputTex = mMaterial->getParamTexture("gInputTex");
 		mColorLUT = mMaterial->getParamTexture("gColorLUT");
@@ -384,7 +391,8 @@ namespace BansheeEngine
 		rapi.setRenderTarget(target);
 		rapi.setViewport(outputViewport->getNormArea());
 
-		gRendererUtility().setPass(mMaterial, 0);
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
 		gRendererUtility().drawScreenQuad();
 	}
 

+ 58 - 30
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -28,6 +28,7 @@
 #include "BsAnimationManager.h"
 #include "BsSkeleton.h"
 #include "BsGpuBuffer.h"
+#include "BsGpuParamsSet.h"
 
 using namespace std::placeholders;
 
@@ -173,6 +174,37 @@ namespace BansheeEngine
 				if (renElement.material == nullptr)
 					renElement.material = mDefaultMaterial->getMaterial();
 
+				// Generate or assigned renderer specific data for the material
+				Any materialInfo = renElement.material->getRendererData();
+				if(materialInfo.empty())
+				{
+					RendererMaterial matInfo;
+					matInfo.params.resize(1);
+					matInfo.params[0] = renElement.material->createParamsSet(0);
+					matInfo.matVersion = renElement.material->getVersion();
+
+					renElement.material->updateParamsSet(matInfo.params[0], 0, true);
+					renElement.material->setRendererData(matInfo);
+					renElement.params = matInfo.params[0];
+				}
+				else
+				{
+					RendererMaterial& matInfo = any_cast_ref<RendererMaterial>(materialInfo);
+					if(matInfo.matVersion != renElement.material->getVersion())
+					{
+						if (matInfo.params.size() < 1)
+							matInfo.params.resize(1);
+
+						matInfo.params[0] = renElement.material->createParamsSet(0);
+						matInfo.matVersion = renElement.material->getVersion();
+
+						renElement.material->updateParamsSet(matInfo.params[0], 0, true);
+					}
+
+					renElement.params = matInfo.params[0];
+				}
+
+				// Generate or assign sampler state overrides
 				auto iterFind = mSamplerOverrides.find(renElement.material);
 				if (iterFind != mSamplerOverrides.end())
 				{
@@ -181,7 +213,7 @@ namespace BansheeEngine
 				}
 				else
 				{
-					MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(renElement.material, mCoreOptions);
+					MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(renElement.params, mCoreOptions);
 					mSamplerOverrides[renElement.material] = samplerOverrides;
 
 					renElement.samplerOverrides = samplerOverrides;
@@ -755,14 +787,12 @@ namespace BansheeEngine
 		mObjectRenderer->setPerObjectParams(element, mRenderableShaderData[rendererId], worldViewProjMatrix, boneMatrices);
 
 		if (bindPass)
-			RendererUtility::instance().setPass(material, passIdx, false);
-
-		SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
+			RendererUtility::instance().setPass(material, passIdx);
 
 		if (element.samplerOverrides != nullptr)
-			setPassParams(passParams, &element.samplerOverrides->passes[passIdx]);
+			setPassParams(element.params, &element.samplerOverrides->passes[passIdx], passIdx);
 		else
-			setPassParams(passParams, nullptr);
+			setPassParams(element.params, nullptr, passIdx);
 
 		gRendererUtility().draw(element.mesh, element.subMesh);
 	}
@@ -771,29 +801,28 @@ namespace BansheeEngine
 	{
 		for (auto& entry : mSamplerOverrides)
 		{
-			SPtr<MaterialCore> material = entry.first;
+			SPtr<GpuParamsSetCore> paramsSet = entry.first;
 
 			if (force)
 			{
 				SamplerOverrideUtility::destroySamplerOverrides(entry.second);
-				entry.second = SamplerOverrideUtility::generateSamplerOverrides(material, mCoreOptions);
+				entry.second = SamplerOverrideUtility::generateSamplerOverrides(paramsSet, mCoreOptions);
 			}
 			else
 			{
 				MaterialSamplerOverrides* materialOverrides = entry.second;
-				UINT32 numPasses = material->getNumPasses();
+				UINT32 numPasses = paramsSet->getNumPasses();
 
 				assert(numPasses == materialOverrides->numPasses);
 				for (UINT32 i = 0; i < numPasses; i++)
 				{
-					SPtr<PassParametersCore> passParams = material->getPassParameters(i);
 					PassSamplerOverrides& passOverrides = materialOverrides->passes[i];
 
-					for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
+					for (UINT32 j = 0; j < GpuParamsSetCore::NUM_PARAMS; j++)
 					{
 						StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
 
-						SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+						SPtr<GpuParamsCore> params = paramsSet->getParamByIdx(j, i);
 						if (params == nullptr)
 							continue;
 
@@ -820,7 +849,8 @@ namespace BansheeEngine
 		}
 	}
 
-	void RenderBeast::setPassParams(const SPtr<PassParametersCore>& passParams, const PassSamplerOverrides* samplerOverrides)
+	void RenderBeast::setPassParams(const SPtr<GpuParamsSetCore>& paramsSet, const PassSamplerOverrides* samplerOverrides, 
+		UINT32 passIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -833,21 +863,19 @@ namespace BansheeEngine
 		};
 
 		const UINT32 numStages = 6;
-		StageData stages[numStages] =
+		GpuProgramType stages[numStages] =
 		{
-			{ GPT_VERTEX_PROGRAM, passParams->mVertParams },
-			{ GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
-			{ GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
-			{ GPT_HULL_PROGRAM, passParams->mHullParams },
-			{ GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
-			{ GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
+			{ GPT_VERTEX_PROGRAM },
+			{ GPT_FRAGMENT_PROGRAM },
+			{ GPT_GEOMETRY_PROGRAM },
+			{ GPT_HULL_PROGRAM },
+			{ GPT_DOMAIN_PROGRAM },
+			{ GPT_COMPUTE_PROGRAM }
 		};
 
 		for (UINT32 i = 0; i < numStages; i++)
 		{
-			const StageData& stage = stages[i];
-
-			SPtr<GpuParamsCore> params = stage.params;
+			SPtr<GpuParamsCore> params = paramsSet->getGpuParams(stages[i], passIdx);
 			if (params == nullptr)
 				continue;
 
@@ -863,15 +891,15 @@ namespace BansheeEngine
 					samplerState = params->getSamplerState(iter->second.slot);
 
 				if (samplerState == nullptr)
-					rapi.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
+					rapi.setSamplerState(stages[i], iter->second.slot, SamplerStateCore::getDefault());
 				else
-					rapi.setSamplerState(stage.type, iter->second.slot, samplerState);
+					rapi.setSamplerState(stages[i], iter->second.slot, samplerState);
 			}
 
 			for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
 			{
 				SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
-				rapi.setTexture(stage.type, iter->second.slot, texture);
+				rapi.setTexture(stages[i], iter->second.slot, texture);
 			}
 
 			for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
@@ -880,9 +908,9 @@ namespace BansheeEngine
 				const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
 
 				if (texture == nullptr)
-					rapi.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
+					rapi.setLoadStoreTexture(stages[i], iter->second.slot, false, nullptr, surface);
 				else
-					rapi.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
+					rapi.setLoadStoreTexture(stages[i], iter->second.slot, true, texture, surface);
 			}
 
 			for (auto iter = paramDesc.buffers.begin(); iter != paramDesc.buffers.end(); ++iter)
@@ -892,7 +920,7 @@ namespace BansheeEngine
 				bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
 					iter->second.type != GPOT_STRUCTURED_BUFFER;
 
-				rapi.setBuffer(stage.type, iter->second.slot, buffer, isLoadStore);
+				rapi.setBuffer(stages[i], iter->second.slot, buffer, isLoadStore);
 			}
 
 			for (auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
@@ -900,7 +928,7 @@ namespace BansheeEngine
 				SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.slot);
 				blockBuffer->flushToGPU();
 
-				rapi.setParamBuffer(stage.type, iter->second.slot, blockBuffer, paramDesc);
+				rapi.setParamBuffer(stages[i], iter->second.slot, blockBuffer, paramDesc);
 			}
 		}
 	}

+ 9 - 10
Source/RenderBeast/Source/BsSamplerOverrides.cpp

@@ -4,26 +4,26 @@
 #include "BsRenderBeastOptions.h"
 #include "BsMaterial.h"
 #include "BsGpuParams.h"
+#include "BsGpuParamsSet.h"
 #include "BsGpuParamDesc.h"
 #include "BsSamplerState.h"
 #include "BsRenderStateManager.h"
 
 namespace BansheeEngine
 {
-	MaterialSamplerOverrides* SamplerOverrideUtility::generateSamplerOverrides(const SPtr<MaterialCore>& material, const SPtr<RenderBeastOptions>& options)
+	MaterialSamplerOverrides* SamplerOverrideUtility::generateSamplerOverrides(const SPtr<GpuParamsSetCore>& paramsSet, const SPtr<RenderBeastOptions>& options)
 	{
-		UINT32 numPasses = material->getNumPasses();
+		UINT32 numPasses = paramsSet->getNumPasses();
 
 		// First pass just determine if we even need to override and count the number of sampler states
 		UINT32 totalNumSamplerStates = 0;
 		for (UINT32 i = 0; i < numPasses; i++)
 		{
-			SPtr<PassParametersCore> passParams = material->getPassParameters(i);
 			UINT32 maxSamplerSlot = 0;
 
-			for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
+			for (UINT32 j = 0; j < GpuParamsSetCore::NUM_PARAMS; j++)
 			{
-				SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+				SPtr<GpuParamsCore> params = paramsSet->getParamByIdx(j, i);
 				if (params == nullptr)
 					continue;
 
@@ -40,7 +40,7 @@ namespace BansheeEngine
 		}
 
 		UINT32 outputSize = sizeof(MaterialSamplerOverrides) +
-			numPasses * (sizeof(PassSamplerOverrides) + PassParametersCore::NUM_PARAMS * sizeof(StageSamplerOverrides)) +
+			numPasses * (sizeof(PassSamplerOverrides) + GpuParamsSetCore::NUM_PARAMS * sizeof(StageSamplerOverrides)) +
 			totalNumSamplerStates * sizeof(SPtr<SamplerStateCore>);
 
 		UINT8* outputData = (UINT8*)bs_alloc(outputSize);
@@ -59,18 +59,17 @@ namespace BansheeEngine
 			for (UINT32 i = 0; i < numPasses; i++)
 			{
 				PassSamplerOverrides& passOverrides = output->passes[i];
-				passOverrides.numStages = PassParametersCore::NUM_PARAMS;
+				passOverrides.numStages = GpuParamsSetCore::NUM_PARAMS;
 				passOverrides.stages = (StageSamplerOverrides*)outputData;
-				outputData += sizeof(StageSamplerOverrides) * PassParametersCore::NUM_PARAMS;
+				outputData += sizeof(StageSamplerOverrides) * GpuParamsSetCore::NUM_PARAMS;
 
-				SPtr<PassParametersCore> passParams = material->getPassParameters(i);
 				for (UINT32 j = 0; j < passOverrides.numStages; j++)
 				{
 					StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
 					stageOverrides.numStates = 0;
 					stageOverrides.stateOverrides = (SPtr<SamplerStateCore>*)outputData;
 
-					SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
+					SPtr<GpuParamsCore> params = paramsSet->getParamByIdx(j, i);
 					if (params == nullptr)
 						continue;